Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"cc.h"
2
#include	"y.tab.h"
3
 
4
#ifndef	CPP
5
#define	CPP	"/bin/cpp"
6
#endif
7
 
8
/*
9
 * known debug flags
10
 *	-a		acid declaration output
11
 *	-A		!B
12
 *	-B		non ANSI
13
 *	-d		print declarations
14
 *	-D name		define
15
 *	-F		format specification check
16
 *	-i		print initialization
17
 *	-I path		include
18
 *	-l		generate little-endian code
19
 *	-L		print every NAME symbol
20
 *	-M		constant multiplication
21
 *	-m		print add/sub/mul trees
22
 *	-n		print acid to file (%.c=%.acid) (with -a or -aa)
23
 *	-o file		output file
24
 *	-p		use standard cpp ANSI preprocessor (not on windows)
25
 *	-r		print registerization
26
 *	-s		print structure offsets (with -a or -aa)
27
 *	-S		print assembly
28
 *	-t		print type trees
29
 *	-V		enable void* conversion warnings
30
 *	-v		verbose printing
31
 *	-w		print warnings
32
 *	-X		abort on error
33
 *	-.		Inhibit search for includes in source directory
34
 */
35
 
36
void
37
main(int argc, char *argv[])
38
{
39
	char **defs, **np, *p;
40
	int nproc, nout, status, i, c, ndef, maxdef;
41
 
42
	memset(debug, 0, sizeof(debug));
43
	tinit();
44
	cinit();
45
	ginit();
46
	arginit();
47
 
48
	profileflg = 1;	/* #pragma can turn it off */
49
	tufield = simplet((1L<<tfield->etype) | BUNSIGNED);
50
	maxdef = 0;
51
	ndef = 0;
52
	outfile = 0;
53
	defs = nil;
54
	setinclude(".");
55
	ARGBEGIN {
56
	default:
57
		c = ARGC();
58
		if(c >= 0 && c < sizeof(debug))
59
			debug[c]++;
60
		break;
61
 
62
	case 'l':			/* for little-endian mips */
63
		if(thechar != 'v'){
64
			print("can only use -l with vc");
65
			errorexit();
66
		}
67
		thechar = '0';
68
		thestring = "spim";
69
		break;
70
 
71
	case 'o':
72
		outfile = ARGF();
73
		break;
74
 
75
	case 'D':
76
		p = ARGF();
77
		if(p) {
78
			if(ndef >= maxdef){
79
				maxdef += 50;
80
				np = alloc(maxdef * sizeof *np);
81
				if(defs != nil)
82
					memmove(np, defs, (maxdef - 50) * sizeof *np);
83
				defs = np;
84
			}
85
			defs[ndef++] = p;
86
			dodefine(p);
87
		}
88
		break;
89
 
90
	case 'I':
91
		p = ARGF();
92
		if(p)
93
			setinclude(p);
94
		break;
95
	} ARGEND
96
	if(argc < 1 && outfile == 0) {
97
		print("usage: %cc [-options] files\n", thechar);
98
		errorexit();
99
	}
100
	if(argc > 1 && systemtype(Windows)){
101
		print("can't compile multiple files on windows\n");
102
		errorexit();
103
	}
104
	if(argc > 1 && !systemtype(Windows)) {
105
		nproc = 1;
106
		/*
107
		 * if we're writing acid to standard output, don't compile
108
		 * concurrently, to avoid interleaving output.
109
		 */
110
		if(((!debug['a'] && !debug['Z']) || debug['n']) &&
111
		    (p = getenv("NPROC")) != nil)
112
			nproc = atol(p);	/* */
113
		c = 0;
114
		nout = 0;
115
		for(;;) {
116
			while(nout < nproc && argc > 0) {
117
				i = myfork();
118
				if(i < 0) {
119
					i = mywait(&status);
120
					if(i < 0) {
121
						print("cannot create a process\n");
122
						errorexit();
123
					}
124
					if(status)
125
						c++;
126
					nout--;
127
					continue;
128
				}
129
				if(i == 0) {
130
					fprint(2, "%s:\n", *argv);
131
					if (compile(*argv, defs, ndef))
132
						errorexit();
133
					exits(0);
134
				}
135
				nout++;
136
				argc--;
137
				argv++;
138
			}
139
			i = mywait(&status);
140
			if(i < 0) {
141
				if(c)
142
					errorexit();
143
				exits(0);
144
			}
145
			if(status)
146
				c++;
147
			nout--;
148
		}
149
	}
150
 
151
	if(argc == 0)
152
		c = compile("stdin", defs, ndef);
153
	else
154
		c = compile(argv[0], defs, ndef);
155
 
156
	if(c)
157
		errorexit();
158
	exits(0);
159
}
160
 
161
int
162
compile(char *file, char **defs, int ndef)
163
{
164
	char ofile[400], incfile[20];
165
	char *p, **av, opt[256];
166
	int i, c, fd[2];
167
	static int first = 1;
168
 
169
	strcpy(ofile, file);
170
	p = utfrrune(ofile, pathchar());
171
	if(p) {
172
		*p++ = 0;
173
		if(!debug['.'])
174
			include[0] = strdup(ofile);
175
	} else
176
		p = ofile;
177
 
178
	if(outfile == 0) {
179
		outfile = p;
180
		if(outfile) {
181
			if(p = utfrrune(outfile, '.'))
182
				if(p[1] == 'c' && p[2] == 0)
183
					p[0] = 0;
184
			p = utfrune(outfile, 0);
185
			if(debug['a'] && debug['n'])
186
				strcat(p, ".acid");
187
			else if(debug['Z'] && debug['n'])
188
				strcat(p, "_pickle.c");
189
			else {
190
				p[0] = '.';
191
				p[1] = thechar;
192
				p[2] = 0;
193
			}
194
		} else
195
			outfile = "/dev/null";
196
	}
197
 
198
	if(p = getenv("INCLUDE")) {
199
		setinclude(p);
200
	} else {
201
		if(systemtype(Plan9)) {
202
			sprint(incfile, "/%s/include", thestring);
203
			setinclude(strdup(incfile));
204
			setinclude("/sys/include");
205
		}
206
	}
207
	if (first)
208
		Binit(&diagbuf, 1, OWRITE);
209
	/*
210
	 * if we're writing acid to standard output, don't keep scratching
211
	 * outbuf.
212
	 */
213
	if((debug['a'] || debug['Z']) && !debug['n']) {
214
		if (first) {
215
			outfile = 0;
216
			Binit(&outbuf, dup(1, -1), OWRITE);
217
			dup(2, 1);
218
		}
219
	} else {
220
		c = mycreat(outfile, 0664);
221
		if(c < 0) {
222
			diag(Z, "cannot open %s - %r", outfile);
223
			outfile = 0;
224
			errorexit();
225
		}
226
		Binit(&outbuf, c, OWRITE);
227
	}
228
	newio();
229
	first = 0;
230
 
231
	/* Use an ANSI preprocessor */
232
	if(debug['p']) {
233
		if(systemtype(Windows)) {
234
			diag(Z, "-p option not supported on windows");
235
			errorexit();
236
		}
237
		if(myaccess(file) < 0) {
238
			diag(Z, "%s does not exist", file);
239
			errorexit();
240
		}
241
		if(mypipe(fd) < 0) {
242
			diag(Z, "pipe failed");
243
			errorexit();
244
		}
245
		switch(myfork()) {
246
		case -1:
247
			diag(Z, "fork failed");
248
			errorexit();
249
		case 0:
250
			close(fd[0]);
251
			mydup(fd[1], 1);
252
			close(fd[1]);
253
			av = alloc((3 + ndef + ninclude + 2) * sizeof *av);
254
			av[0] = CPP;
255
			i = 1;
256
			if(debug['.'])
257
				av[i++] = strdup("-.");
258
			/* 1999 ANSI C requires recognising // comments */
259
			av[i++] = strdup("-+");
260
			for(c = 0; c < ndef; c++) {
261
				sprint(opt, "-D%s", defs[c]);
262
				av[i++] = strdup(opt);
263
			}
264
			for(c = 0; c < ninclude; c++) {
265
				sprint(opt, "-I%s", include[c]);
266
				av[i++] = strdup(opt);
267
			}
268
			if(strcmp(file, "stdin") != 0)
269
				av[i++] = file;
270
			av[i] = 0;
271
			if(debug['p'] > 1) {
272
				for(c = 0; c < i; c++)
273
					fprint(2, "%s ", av[c]);
274
				fprint(2, "\n");
275
			}
276
			myexec(av[0], av);
277
			fprint(2, "can't exec C preprocessor %s: %r\n", CPP);
278
			errorexit();
279
		default:
280
			close(fd[1]);
281
			newfile(file, fd[0]);
282
			break;
283
		}
284
	} else {
285
		if(strcmp(file, "stdin") == 0)
286
			newfile(file, 0);
287
		else
288
			newfile(file, -1);
289
	}
290
	yyparse();
291
	if(!debug['a'] && !debug['Z'])
292
		gclean();
293
	return nerrors;
294
}
295
 
296
void
297
errorexit(void)
298
{
299
	if(outfile)
300
		remove(outfile);
301
	exits("error");
302
}
303
 
304
void
305
pushio(void)
306
{
307
	Io *i;
308
 
309
	i = iostack;
310
	if(i == I) {
311
		yyerror("botch in pushio");
312
		errorexit();
313
	}
314
	i->p = fi.p;
315
	i->c = fi.c;
316
}
317
 
318
void
319
newio(void)
320
{
321
	Io *i;
322
	static int pushdepth = 0;
323
 
324
	i = iofree;
325
	if(i == I) {
326
		pushdepth++;
327
		if(pushdepth > 1000) {
328
			yyerror("macro/io expansion too deep");
329
			errorexit();
330
		}
331
		i = alloc(sizeof(*i));
332
	} else
333
		iofree = i->link;
334
	i->c = 0;
335
	i->f = -1;
336
	ionext = i;
337
}
338
 
339
void
340
newfile(char *s, int f)
341
{
342
	Io *i;
343
 
344
	if(debug['e'])
345
		print("%L: %s\n", lineno, s);
346
 
347
	i = ionext;
348
	i->link = iostack;
349
	iostack = i;
350
	i->f = f;
351
	if(f < 0)
352
		i->f = open(s, 0);
353
	if(i->f < 0) {
354
		yyerror("%cc: %r: %s", thechar, s);
355
		errorexit();
356
	}
357
	fi.c = 0;
358
	linehist(s, 0);
359
}
360
 
361
Sym*
362
slookup(char *s)
363
{
364
 
365
	strcpy(symb, s);
366
	return lookup();
367
}
368
 
369
Sym*
370
lookup(void)
371
{
372
	Sym *s;
373
	ulong h;
374
	char *p;
375
	int c, n;
376
 
377
	h = 0;
378
	for(p=symb; *p;) {
379
		h = h * 3;
380
		h += *p++;
381
	}
382
	n = (p - symb) + 1;
383
	if((long)h < 0)
384
		h = ~h;
385
	h %= NHASH;
386
	c = symb[0];
387
	for(s = hash[h]; s != S; s = s->link) {
388
		if(s->name[0] != c)
389
			continue;
390
		if(strcmp(s->name, symb) == 0)
391
			return s;
392
	}
393
	s = alloc(sizeof(*s));
394
	s->name = alloc(n);
395
	memmove(s->name, symb, n);
396
 
397
	strcpy(s->name, symb);
398
	s->link = hash[h];
399
	hash[h] = s;
400
	syminit(s);
401
 
402
	return s;
403
}
404
 
405
void
406
syminit(Sym *s)
407
{
408
	s->lexical = LNAME;
409
	s->block = 0;
410
	s->offset = 0;
411
	s->type = T;
412
	s->suetag = T;
413
	s->class = CXXX;
414
	s->aused = 0;
415
	s->sig = SIGNONE;
416
}
417
 
418
#define	EOF	(-1)
419
#define	IGN	(-2)
420
#define	ESC	(Runemask+1)		/* Rune flag: a literal byte */
421
#define	GETC()	((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff))
422
 
423
enum
424
{
425
	Numdec		= 1<<0,
426
	Numlong		= 1<<1,
427
	Numuns		= 1<<2,
428
	Numvlong	= 1<<3,
429
	Numflt		= 1<<4,
430
};
431
 
432
long
433
yylex(void)
434
{
435
	vlong vv;
436
	long c, c1, t;
437
	char *cp;
438
	Rune rune;
439
	Sym *s;
440
 
441
	if(peekc != IGN) {
442
		c = peekc;
443
		peekc = IGN;
444
		goto l1;
445
	}
446
l0:
447
	c = GETC();
448
 
449
l1:
450
	if(c >= Runeself) {
451
		/*
452
		 * extension --
453
		 *	all multibyte runes are alpha
454
		 */
455
		cp = symb;
456
		goto talph;
457
	}
458
	if(isspace(c)) {
459
		if(c == '\n')
460
			lineno++;
461
		goto l0;
462
	}
463
	if(isalpha(c)) {
464
		cp = symb;
465
		if(c != 'L')
466
			goto talph;
467
		*cp++ = c;
468
		c = GETC();
469
		if(c == '\'') {
470
			/* L'x' */
471
			c = escchar('\'', 1, 0);
472
			if(c == EOF)
473
				c = '\'';
474
			c1 = escchar('\'', 1, 0);
475
			if(c1 != EOF) {
476
				yyerror("missing '");
477
				peekc = c1;
478
			}
479
			yylval.vval = convvtox(c, TRUNE);
480
			return LUCONST;
481
		}
482
		if(c == '"') {
483
			goto caselq;
484
		}
485
		goto talph;
486
	}
487
	if(isdigit(c))
488
		goto tnum;
489
	switch(c)
490
	{
491
 
492
	case EOF:
493
		peekc = EOF;
494
		return -1;
495
 
496
	case '_':
497
		cp = symb;
498
		goto talph;
499
 
500
	case '#':
501
		domacro();
502
		goto l0;
503
 
504
	case '.':
505
		c1 = GETC();
506
		if(isdigit(c1)) {
507
			cp = symb;
508
			*cp++ = c;
509
			c = c1;
510
			c1 = 0;
511
			goto casedot;
512
		}
513
		break;
514
 
515
	case '"':
516
		strcpy(symb, "\"<string>\"");
517
		cp = alloc(0);
518
		c1 = 0;
519
 
520
		/* "..." */
521
		for(;;) {
522
			c = escchar('"', 0, 1);
523
			if(c == EOF)
524
				break;
525
			if(c & ESC) {
526
				cp = allocn(cp, c1, 1);
527
				cp[c1++] = c;
528
			} else {
529
				rune = c;
530
				c = runelen(rune);
531
				cp = allocn(cp, c1, c);
532
				runetochar(cp+c1, &rune);
533
				c1 += c;
534
			}
535
		}
536
		yylval.sval.l = c1;
537
		do {
538
			cp = allocn(cp, c1, 1);
539
			cp[c1++] = 0;
540
		} while(c1 & MAXALIGN);
541
		yylval.sval.s = cp;
542
		return LSTRING;
543
 
544
	caselq:
545
		/* L"..." */
546
		strcpy(symb, "\"L<string>\"");
547
		cp = alloc(0);
548
		c1 = 0;
549
		for(;;) {
550
			c = escchar('"', 1, 0);
551
			if(c == EOF)
552
				break;
553
			cp = allocn(cp, c1, sizeof(TRune));
554
			*(TRune*)(cp + c1) = c;
555
			c1 += sizeof(TRune);
556
		}
557
		yylval.sval.l = c1;
558
		do {
559
			cp = allocn(cp, c1, sizeof(TRune));
560
			*(TRune*)(cp + c1) = 0;
561
			c1 += sizeof(TRune);
562
		} while(c1 & MAXALIGN);
563
		yylval.sval.s = cp;
564
		return LLSTRING;
565
 
566
	case '\'':
567
		/* '.' */
568
		c = escchar('\'', 0, 0);
569
		if(c == EOF)
570
			c = '\'';
571
		c1 = escchar('\'', 0, 0);
572
		if(c1 != EOF) {
573
			yyerror("missing '");
574
			peekc = c1;
575
		}
576
		vv = c;
577
		yylval.vval = convvtox(vv, TUCHAR);
578
		if(yylval.vval != vv)
579
			yyerror("overflow in character constant: 0x%lx", c);
580
		else
581
		if(c & 0x80){
582
			nearln = lineno;
583
			warn(Z, "sign-extended character constant");
584
		}
585
		yylval.vval = convvtox(vv, TCHAR);
586
		return LCONST;
587
 
588
	case '/':
589
		c1 = GETC();
590
		if(c1 == '*') {
591
			for(;;) {
592
				c = getr();
593
				while(c == '*') {
594
					c = getr();
595
					if(c == '/')
596
						goto l0;
597
				}
598
				if(c == EOF) {
599
					yyerror("eof in comment");
600
					errorexit();
601
				}
602
			}
603
		}
604
		if(c1 == '/') {
605
			for(;;) {
606
				c = getr();
607
				if(c == '\n')
608
					goto l0;
609
				if(c == EOF) {
610
					yyerror("eof in comment");
611
					errorexit();
612
				}
613
			}
614
		}
615
		if(c1 == '=')
616
			return LDVE;
617
		break;
618
 
619
	case '*':
620
		c1 = GETC();
621
		if(c1 == '=')
622
			return LMLE;
623
		break;
624
 
625
	case '%':
626
		c1 = GETC();
627
		if(c1 == '=')
628
			return LMDE;
629
		break;
630
 
631
	case '+':
632
		c1 = GETC();
633
		if(c1 == '+')
634
			return LPP;
635
		if(c1 == '=')
636
			return LPE;
637
		break;
638
 
639
	case '-':
640
		c1 = GETC();
641
		if(c1 == '-')
642
			return LMM;
643
		if(c1 == '=')
644
			return LME;
645
		if(c1 == '>')
646
			return LMG;
647
		break;
648
 
649
	case '>':
650
		c1 = GETC();
651
		if(c1 == '>') {
652
			c = LRSH;
653
			c1 = GETC();
654
			if(c1 == '=')
655
				return LRSHE;
656
			break;
657
		}
658
		if(c1 == '=')
659
			return LGE;
660
		break;
661
 
662
	case '<':
663
		c1 = GETC();
664
		if(c1 == '<') {
665
			c = LLSH;
666
			c1 = GETC();
667
			if(c1 == '=')
668
				return LLSHE;
669
			break;
670
		}
671
		if(c1 == '=')
672
			return LLE;
673
		break;
674
 
675
	case '=':
676
		c1 = GETC();
677
		if(c1 == '=')
678
			return LEQ;
679
		break;
680
 
681
	case '!':
682
		c1 = GETC();
683
		if(c1 == '=')
684
			return LNE;
685
		break;
686
 
687
	case '&':
688
		c1 = GETC();
689
		if(c1 == '&')
690
			return LANDAND;
691
		if(c1 == '=')
692
			return LANDE;
693
		break;
694
 
695
	case '|':
696
		c1 = GETC();
697
		if(c1 == '|')
698
			return LOROR;
699
		if(c1 == '=')
700
			return LORE;
701
		break;
702
 
703
	case '^':
704
		c1 = GETC();
705
		if(c1 == '=')
706
			return LXORE;
707
		break;
708
 
709
	default:
710
		return c;
711
	}
712
	peekc = c1;
713
	return c;
714
 
715
talph:
716
	/*
717
	 * cp is set to symb and some
718
	 * prefix has been stored
719
	 */
720
	for(;;) {
721
		if(c >= Runeself) {
722
			for(c1=0;;) {
723
				cp[c1++] = c;
724
				if(fullrune(cp, c1))
725
					break;
726
				c = GETC();
727
			}
728
			cp += c1;
729
			c = GETC();
730
			continue;
731
		}
732
		if(!isalnum(c) && c != '_')
733
			break;
734
		*cp++ = c;
735
		c = GETC();
736
	}
737
	*cp = 0;
738
	if(debug['L'])
739
		print("%L: %s\n", lineno, symb);
740
	peekc = c;
741
	s = lookup();
742
	if(s->macro) {
743
		newio();
744
		cp = ionext->b;
745
		macexpand(s, cp);
746
		pushio();
747
		ionext->link = iostack;
748
		iostack = ionext;
749
		fi.p = cp;
750
		fi.c = strlen(cp);
751
		if(peekc != IGN) {
752
			cp[fi.c++] = peekc;
753
			cp[fi.c] = 0;
754
			peekc = IGN;
755
		}
756
		goto l0;
757
	}
758
	yylval.sym = s;
759
	if(s->class == CTYPEDEF || s->class == CTYPESTR)
760
		return LTYPE;
761
	return s->lexical;
762
 
763
tnum:
764
	c1 = 0;
765
	cp = symb;
766
	if(c != '0') {
767
		c1 |= Numdec;
768
		for(;;) {
769
			*cp++ = c;
770
			c = GETC();
771
			if(isdigit(c))
772
				continue;
773
			goto dc;
774
		}
775
	}
776
	*cp++ = c;
777
	c = GETC();
778
	if(c == 'x' || c == 'X')
779
		for(;;) {
780
			*cp++ = c;
781
			c = GETC();
782
			if(isdigit(c))
783
				continue;
784
			if(c >= 'a' && c <= 'f')
785
				continue;
786
			if(c >= 'A' && c <= 'F')
787
				continue;
788
			if(cp == symb+2)
789
				yyerror("malformed hex constant");
790
			goto ncu;
791
		}
792
	if(c < '0' || c > '7')
793
		goto dc;
794
	for(;;) {
795
		if(c >= '0' && c <= '7') {
796
			*cp++ = c;
797
			c = GETC();
798
			continue;
799
		}
800
		goto ncu;
801
	}
802
 
803
dc:
804
	if(c == '.')
805
		goto casedot;
806
	if(c == 'e' || c == 'E')
807
		goto casee;
808
 
809
ncu:
810
	if((c == 'U' || c == 'u') && !(c1 & Numuns)) {
811
		c = GETC();
812
		c1 |= Numuns;
813
		goto ncu;
814
	}
815
	if((c == 'L' || c == 'l') && !(c1 & Numvlong)) {
816
		c = GETC();
817
		if(c1 & Numlong)
818
			c1 |= Numvlong;
819
		c1 |= Numlong;
820
		goto ncu;
821
	}
822
	*cp = 0;
823
	peekc = c;
824
	if(mpatov(symb, &yylval.vval))
825
		yyerror("overflow in constant");
826
 
827
	vv = yylval.vval;
828
	if(c1 & Numvlong) {
829
		if((c1 & Numuns) || convvtox(vv, TVLONG) < 0) {
830
			c = LUVLCONST;
831
			t = TUVLONG;
832
			goto nret;
833
		}
834
		c = LVLCONST;
835
		t = TVLONG;
836
		goto nret;
837
	}
838
	if(c1 & Numlong) {
839
		if((c1 & Numuns) || convvtox(vv, TLONG) < 0) {
840
			c = LULCONST;
841
			t = TULONG;
842
			goto nret;
843
		}
844
		c = LLCONST;
845
		t = TLONG;
846
		goto nret;
847
	}
848
	if((c1 & Numuns) || convvtox(vv, TINT) < 0) {
849
		c = LUCONST;
850
		t = TUINT;
851
		goto nret;
852
	}
853
	c = LCONST;
854
	t = TINT;
855
	goto nret;
856
 
857
nret:
858
	yylval.vval = convvtox(vv, t);
859
	if(yylval.vval != vv){
860
		nearln = lineno;
861
		warn(Z, "truncated constant: %T %s", types[t], symb);
862
	}
863
	return c;
864
 
865
casedot:
866
	for(;;) {
867
		*cp++ = c;
868
		c = GETC();
869
		if(!isdigit(c))
870
			break;
871
	}
872
	if(c != 'e' && c != 'E')
873
		goto caseout;
874
 
875
casee:
876
	*cp++ = 'e';
877
	c = GETC();
878
	if(c == '+' || c == '-') {
879
		*cp++ = c;
880
		c = GETC();
881
	}
882
	if(!isdigit(c))
883
		yyerror("malformed fp constant exponent");
884
	while(isdigit(c)) {
885
		*cp++ = c;
886
		c = GETC();
887
	}
888
 
889
caseout:
890
	if(c == 'L' || c == 'l') {
891
		c = GETC();
892
		c1 |= Numlong;
893
	} else
894
	if(c == 'F' || c == 'f') {
895
		c = GETC();
896
		c1 |= Numflt;
897
	}
898
	*cp = 0;
899
	peekc = c;
900
	yylval.dval = strtod(symb, nil);
901
	if(isInf(yylval.dval, 1) || isInf(yylval.dval, -1)) {
902
		yyerror("overflow in float constant");
903
		yylval.dval = 0;
904
	}
905
	if(c1 & Numflt)
906
		return LFCONST;
907
	return LDCONST;
908
}
909
 
910
/*
911
 * convert a string, s, to vlong in *v
912
 * return conversion overflow.
913
 * required syntax is [0[x]]d*
914
 */
915
int
916
mpatov(char *s, vlong *v)
917
{
918
	vlong n, nn;
919
	int c;
920
 
921
	n = 0;
922
	c = *s;
923
	if(c == '0')
924
		goto oct;
925
	while(c = *s++) {
926
		if(c >= '0' && c <= '9')
927
			nn = n*10 + c-'0';
928
		else
929
			goto bad;
930
		if(n < 0 && nn >= 0)
931
			goto bad;
932
		n = nn;
933
	}
934
	goto out;
935
 
936
oct:
937
	s++;
938
	c = *s;
939
	if(c == 'x' || c == 'X')
940
		goto hex;
941
	while(c = *s++) {
942
		if(c >= '0' || c <= '7')
943
			nn = n*8 + c-'0';
944
		else
945
			goto bad;
946
		if(n < 0 && nn >= 0)
947
			goto bad;
948
		n = nn;
949
	}
950
	goto out;
951
 
952
hex:
953
	s++;
954
	while(c = *s++) {
955
		if(c >= '0' && c <= '9')
956
			c += 0-'0';
957
		else
958
		if(c >= 'a' && c <= 'f')
959
			c += 10-'a';
960
		else
961
		if(c >= 'A' && c <= 'F')
962
			c += 10-'A';
963
		else
964
			goto bad;
965
		nn = n*16 + c;
966
		if(n < 0 && nn >= 0)
967
			goto bad;
968
		n = nn;
969
	}
970
out:
971
	*v = n;
972
	return 0;
973
 
974
bad:
975
	*v = ~0;
976
	return 1;
977
}
978
 
979
int
980
getc(void)
981
{
982
	int c;
983
 
984
	if(peekc != IGN) {
985
		c = peekc;
986
		peekc = IGN;
987
	} else
988
		c = GETC();
989
	if(c == '\n')
990
		lineno++;
991
	if(c == EOF) {
992
		yyerror("End of file");
993
		errorexit();
994
	}
995
	return c;
996
}
997
 
998
long
999
getr(void)
1000
{
1001
	int c, i;
1002
	char str[UTFmax+1];
1003
	Rune rune;
1004
 
1005
 
1006
	c = getc();
1007
	if(c < Runeself)
1008
		return c;
1009
	i = 0;
1010
	str[i++] = c;
1011
 
1012
loop:
1013
	c = getc();
1014
	str[i++] = c;
1015
	if(!fullrune(str, i))
1016
		goto loop;
1017
	c = chartorune(&rune, str);
1018
	if(rune == Runeerror && c == 1) {
1019
		nearln = lineno;
1020
		diag(Z, "illegal rune in string");
1021
		for(c=0; c<i; c++)
1022
			print(" %.2x", *(uchar*)(str+c));
1023
		print("\n");
1024
	}
1025
	return rune;
1026
}
1027
 
1028
int
1029
getnsc(void)
1030
{
1031
	int c;
1032
 
1033
	if(peekc != IGN) {
1034
		c = peekc;
1035
		peekc = IGN;
1036
	} else
1037
		c = GETC();
1038
	for(;;) {
1039
		if(c >= Runeself || !isspace(c))
1040
			return c;
1041
		if(c == '\n') {
1042
			lineno++;
1043
			return c;
1044
		}
1045
		c = GETC();
1046
	}
1047
}
1048
 
1049
void
1050
unget(int c)
1051
{
1052
 
1053
	peekc = c;
1054
	if(c == '\n')
1055
		lineno--;
1056
}
1057
 
1058
long
1059
escchar(long e, int longflg, int escflg)
1060
{
1061
	long c, l;
1062
	int i;
1063
 
1064
loop:
1065
	c = getr();
1066
	if(c == '\n') {
1067
		yyerror("newline in string");
1068
		return EOF;
1069
	}
1070
	if(c != '\\') {
1071
		if(c == e)
1072
			c = EOF;
1073
		return c;
1074
	}
1075
	c = getr();
1076
	if(c == 'x') {
1077
		/*
1078
		 * note this is not ansi,
1079
		 * supposed to only accept 2 hex
1080
		 */
1081
		i = 2;
1082
		if(longflg)
1083
			i = 6;
1084
		l = 0;
1085
		for(; i>0; i--) {
1086
			c = getc();
1087
			if(c >= '0' && c <= '9') {
1088
				l = l*16 + c-'0';
1089
				continue;
1090
			}
1091
			if(c >= 'a' && c <= 'f') {
1092
				l = l*16 + c-'a' + 10;
1093
				continue;
1094
			}
1095
			if(c >= 'A' && c <= 'F') {
1096
				l = l*16 + c-'A' + 10;
1097
				continue;
1098
			}
1099
			unget(c);
1100
			break;
1101
		}
1102
		if(escflg)
1103
			l |= ESC;
1104
		return l;
1105
	}
1106
	if(c >= '0' && c <= '7') {
1107
		/*
1108
		 * note this is not ansi,
1109
		 * supposed to only accept 3 oct
1110
		 */
1111
		i = 2;
1112
		if(longflg)
1113
			i = 8;
1114
		l = c - '0';
1115
		for(; i>0; i--) {
1116
			c = getc();
1117
			if(c >= '0' && c <= '7') {
1118
				l = l*8 + c-'0';
1119
				continue;
1120
			}
1121
			unget(c);
1122
		}
1123
		if(escflg)
1124
			l |= ESC;
1125
		return l;
1126
	}
1127
	switch(c)
1128
	{
1129
	case '\n':	goto loop;
1130
	case 'n':	return '\n';
1131
	case 't':	return '\t';
1132
	case 'b':	return '\b';
1133
	case 'r':	return '\r';
1134
	case 'f':	return '\f';
1135
	case 'a':	return '\a';
1136
	case 'v':	return '\v';
1137
	}
1138
	return c;
1139
}
1140
 
1141
struct
1142
{
1143
	char	*name;
1144
	ushort	lexical;
1145
	ushort	type;
1146
} itab[] =
1147
{
1148
	"auto",		LAUTO,		0,
1149
	"break",	LBREAK,		0,
1150
	"case",		LCASE,		0,
1151
	"char",		LCHAR,		TCHAR,
1152
	"const",	LCONSTNT,	0,
1153
	"continue",	LCONTINUE,	0,
1154
	"default",	LDEFAULT,	0,
1155
	"do",		LDO,		0,
1156
	"double",	LDOUBLE,	TDOUBLE,
1157
	"else",		LELSE,		0,
1158
	"enum",		LENUM,		0,
1159
	"extern",	LEXTERN,	0,
1160
	"float",	LFLOAT,		TFLOAT,
1161
	"for",		LFOR,		0,
1162
	"goto",		LGOTO,		0,
1163
	"if",		LIF,		0,
1164
	"inline",	LINLINE,	0,
1165
	"int",		LINT,		TINT,
1166
	"long",		LLONG,		TLONG,
1167
	"register",	LREGISTER,	0,
1168
	"restrict",	LRESTRICT,	0,
1169
	"return",	LRETURN,	0,
1170
	"SET",		LSET,		0,
1171
	"short",	LSHORT,		TSHORT,
1172
	"signed",	LSIGNED,	0,
1173
	"signof",	LSIGNOF,	0,
1174
	"sizeof",	LSIZEOF,	0,
1175
	"static",	LSTATIC,	0,
1176
	"struct",	LSTRUCT,	0,
1177
	"switch",	LSWITCH,	0,
1178
	"typedef",	LTYPEDEF,	0,
1179
	"typestr",	LTYPESTR,	0,
1180
	"union",	LUNION,		0,
1181
	"unsigned",	LUNSIGNED,	0,
1182
	"USED",		LUSED,		0,
1183
	"void",		LVOID,		TVOID,
1184
	"volatile",	LVOLATILE,	0,
1185
	"while",	LWHILE,		0,
1186
 
1187
};
1188
 
1189
void
1190
cinit(void)
1191
{
1192
	Sym *s;
1193
	int i;
1194
	Type *t;
1195
 
1196
	nerrors = 0;
1197
	lineno = 1;
1198
	iostack = I;
1199
	iofree = I;
1200
	peekc = IGN;
1201
	nhunk = 0;
1202
 
1203
	types[TXXX] = T;
1204
	types[TCHAR] = typ(TCHAR, T);
1205
	types[TUCHAR] = typ(TUCHAR, T);
1206
	types[TSHORT] = typ(TSHORT, T);
1207
	types[TUSHORT] = typ(TUSHORT, T);
1208
	types[TINT] = typ(TINT, T);
1209
	types[TUINT] = typ(TUINT, T);
1210
	types[TLONG] = typ(TLONG, T);
1211
	types[TULONG] = typ(TULONG, T);
1212
	types[TVLONG] = typ(TVLONG, T);
1213
	types[TUVLONG] = typ(TUVLONG, T);
1214
	types[TFLOAT] = typ(TFLOAT, T);
1215
	types[TDOUBLE] = typ(TDOUBLE, T);
1216
	types[TVOID] = typ(TVOID, T);
1217
	types[TENUM] = typ(TENUM, T);
1218
	types[TFUNC] = typ(TFUNC, types[TINT]);
1219
	types[TIND] = typ(TIND, types[TVOID]);
1220
 
1221
	for(i=0; i<NHASH; i++)
1222
		hash[i] = S;
1223
	for(i=0; itab[i].name; i++) {
1224
		s = slookup(itab[i].name);
1225
		s->lexical = itab[i].lexical;
1226
		if(itab[i].type != 0)
1227
			s->type = types[itab[i].type];
1228
	}
1229
	blockno = 0;
1230
	autobn = 0;
1231
	autoffset = 0;
1232
 
1233
	t = typ(TARRAY, types[TCHAR]);
1234
	t->width = 0;
1235
	symstring = slookup(".string");
1236
	symstring->class = CSTATIC;
1237
	symstring->type = t;
1238
 
1239
	t = typ(TARRAY, types[TCHAR]);
1240
	t->width = 0;
1241
 
1242
	nodproto = new(OPROTO, Z, Z);
1243
	dclstack = D;
1244
 
1245
	pathname = allocn(pathname, 0, 100);
1246
	if(mygetwd(pathname, 99) == 0) {
1247
		pathname = allocn(pathname, 100, 900);
1248
		if(mygetwd(pathname, 999) == 0)
1249
			strcpy(pathname, "/???");
1250
	}
1251
 
1252
	fmtinstall('O', Oconv);
1253
	fmtinstall('T', Tconv);
1254
	fmtinstall('F', FNconv);
1255
	fmtinstall('L', Lconv);
1256
	fmtinstall('Q', Qconv);
1257
	fmtinstall('|', VBconv);
1258
}
1259
 
1260
int
1261
filbuf(void)
1262
{
1263
	Io *i;
1264
 
1265
loop:
1266
	i = iostack;
1267
	if(i == I)
1268
		return EOF;
1269
	if(i->f < 0)
1270
		goto pop;
1271
	fi.c = read(i->f, i->b, BUFSIZ) - 1;
1272
	if(fi.c < 0) {
1273
		close(i->f);
1274
		linehist(0, 0);
1275
		goto pop;
1276
	}
1277
	fi.p = i->b + 1;
1278
	return i->b[0] & 0xff;
1279
 
1280
pop:
1281
	iostack = i->link;
1282
	i->link = iofree;
1283
	iofree = i;
1284
	i = iostack;
1285
	if(i == I)
1286
		return EOF;
1287
	fi.p = i->p;
1288
	fi.c = i->c;
1289
	if(--fi.c < 0)
1290
		goto loop;
1291
	return *fi.p++ & 0xff;
1292
}
1293
 
1294
int
1295
Oconv(Fmt *fp)
1296
{
1297
	int a;
1298
 
1299
	a = va_arg(fp->args, int);
1300
	if(a < OXXX || a > OEND)
1301
		return fmtprint(fp, "***badO %d***", a);
1302
 
1303
	return fmtstrcpy(fp, onames[a]);
1304
}
1305
 
1306
int
1307
Lconv(Fmt *fp)
1308
{
1309
	char str[STRINGSZ], s[STRINGSZ];
1310
	Hist *h;
1311
	struct
1312
	{
1313
		Hist*	incl;	/* start of this include file */
1314
		long	idel;	/* delta line number to apply to include */
1315
		Hist*	line;	/* start of this #line directive */
1316
		long	ldel;	/* delta line number to apply to #line */
1317
	} a[HISTSZ];
1318
	long l, d;
1319
	int i, n;
1320
 
1321
	l = va_arg(fp->args, long);
1322
	n = 0;
1323
	for(h = hist; h != H; h = h->link) {
1324
		if(l < h->line)
1325
			break;
1326
		if(h->name) {
1327
			if(h->offset != 0) {		/* #line directive, not #pragma */
1328
				if(n > 0 && n < HISTSZ && h->offset >= 0) {
1329
					a[n-1].line = h;
1330
					a[n-1].ldel = h->line - h->offset + 1;
1331
				}
1332
			} else {
1333
				if(n < HISTSZ) {	/* beginning of file */
1334
					a[n].incl = h;
1335
					a[n].idel = h->line;
1336
					a[n].line = 0;
1337
				}
1338
				n++;
1339
			}
1340
			continue;
1341
		}
1342
		n--;
1343
		if(n > 0 && n < HISTSZ) {
1344
			d = h->line - a[n].incl->line;
1345
			a[n-1].ldel += d;
1346
			a[n-1].idel += d;
1347
		}
1348
	}
1349
	if(n > HISTSZ)
1350
		n = HISTSZ;
1351
	str[0] = 0;
1352
	for(i=n-1; i>=0; i--) {
1353
		if(i != n-1) {
1354
			if(fp->flags & ~(FmtWidth|FmtPrec))	/* BUG ROB - was f3 */
1355
				break;
1356
			strcat(str, " ");
1357
		}
1358
		if(a[i].line)
1359
			snprint(s, STRINGSZ, "%s:%ld[%s:%ld]",
1360
				a[i].line->name, l-a[i].ldel+1,
1361
				a[i].incl->name, l-a[i].idel+1);
1362
		else
1363
			snprint(s, STRINGSZ, "%s:%ld",
1364
				a[i].incl->name, l-a[i].idel+1);
1365
		if(strlen(s)+strlen(str) >= STRINGSZ-10)
1366
			break;
1367
		strcat(str, s);
1368
		l = a[i].incl->line - 1;	/* now print out start of this file */
1369
	}
1370
	if(n == 0)
1371
		strcat(str, "<eof>");
1372
	return fmtstrcpy(fp, str);
1373
}
1374
 
1375
int
1376
Tconv(Fmt *fp)
1377
{
1378
	char str[STRINGSZ+20], s[STRINGSZ+20];
1379
	Type *t, *t1;
1380
	int et;
1381
	long n;
1382
 
1383
	str[0] = 0;
1384
	for(t = va_arg(fp->args, Type*); t != T; t = t->link) {
1385
		et = t->etype;
1386
		if(str[0])
1387
			strcat(str, " ");
1388
		if(t->garb&~GINCOMPLETE) {
1389
			sprint(s, "%s ", gnames[t->garb&~GINCOMPLETE]);
1390
			if(strlen(str) + strlen(s) < STRINGSZ)
1391
				strcat(str, s);
1392
		}
1393
		sprint(s, "%s", tnames[et]);
1394
		if(strlen(str) + strlen(s) < STRINGSZ)
1395
			strcat(str, s);
1396
		if(et == TFUNC && (t1 = t->down)) {
1397
			sprint(s, "(%T", t1);
1398
			if(strlen(str) + strlen(s) < STRINGSZ)
1399
				strcat(str, s);
1400
			while(t1 = t1->down) {
1401
				sprint(s, ", %T", t1);
1402
				if(strlen(str) + strlen(s) < STRINGSZ)
1403
					strcat(str, s);
1404
			}
1405
			if(strlen(str) + strlen(s) < STRINGSZ)
1406
				strcat(str, ")");
1407
		}
1408
		if(et == TARRAY) {
1409
			n = t->width;
1410
			if(t->link && t->link->width)
1411
				n /= t->link->width;
1412
			sprint(s, "[%ld]", n);
1413
			if(strlen(str) + strlen(s) < STRINGSZ)
1414
				strcat(str, s);
1415
		}
1416
		if(t->nbits) {
1417
			sprint(s, " %d:%d", t->shift, t->nbits);
1418
			if(strlen(str) + strlen(s) < STRINGSZ)
1419
				strcat(str, s);
1420
		}
1421
		if(typesu[et]) {
1422
			if(t->tag) {
1423
				strcat(str, " ");
1424
				if(strlen(str) + strlen(t->tag->name) < STRINGSZ)
1425
					strcat(str, t->tag->name);
1426
			} else
1427
				strcat(str, " {}");
1428
			break;
1429
		}
1430
	}
1431
	return fmtstrcpy(fp, str);
1432
}
1433
 
1434
int
1435
FNconv(Fmt *fp)
1436
{
1437
	char *str;
1438
	Node *n;
1439
 
1440
	n = va_arg(fp->args, Node*);
1441
	str = "<indirect>";
1442
	if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM))
1443
		str = n->sym->name;
1444
	return fmtstrcpy(fp, str);
1445
}
1446
 
1447
int
1448
Qconv(Fmt *fp)
1449
{
1450
	char str[STRINGSZ+20], *s;
1451
	long b;
1452
	int i;
1453
 
1454
	str[0] = 0;
1455
	for(b = va_arg(fp->args, long); b;) {
1456
		i = bitno(b);
1457
		if(str[0])
1458
			strcat(str, " ");
1459
		s = qnames[i];
1460
		if(strlen(str) + strlen(s) >= STRINGSZ)
1461
			break;
1462
		strcat(str, s);
1463
		b &= ~(1L << i);
1464
	}
1465
	return fmtstrcpy(fp, str);
1466
}
1467
 
1468
int
1469
VBconv(Fmt *fp)
1470
{
1471
	char str[STRINGSZ];
1472
	int i, n, t, pc;
1473
 
1474
	n = va_arg(fp->args, int);
1475
	pc = 0;	/* BUG: was printcol */
1476
	i = 0;
1477
	while(pc < n) {
1478
		t = (pc+4) & ~3;
1479
		if(t <= n) {
1480
			str[i++] = '\t';
1481
			pc = t;
1482
			continue;
1483
		}
1484
		str[i++] = ' ';
1485
		pc++;
1486
	}
1487
	str[i] = 0;
1488
 
1489
	return fmtstrcpy(fp, str);
1490
}
1491
 
1492
/*
1493
 * real allocs
1494
 */
1495
void*
1496
alloc(long n)
1497
{
1498
	void *p;
1499
 
1500
	while((uintptr)hunk & MAXALIGN) {
1501
		hunk++;
1502
		nhunk--;
1503
	}
1504
	while(nhunk < n)
1505
		gethunk();
1506
	p = hunk;
1507
	nhunk -= n;
1508
	hunk += n;
1509
	return p;
1510
}
1511
 
1512
void*
1513
allocn(void *p, long on, long n)
1514
{
1515
	void *q;
1516
 
1517
	q = (uchar*)p + on;
1518
	if(q != hunk || nhunk < n) {
1519
		while(nhunk < on+n)
1520
			gethunk();
1521
		memmove(hunk, p, on);
1522
		p = hunk;
1523
		hunk += on;
1524
		nhunk -= on;
1525
	}
1526
	hunk += n;
1527
	nhunk -= n;
1528
	return p;
1529
}
1530
 
1531
void
1532
setinclude(char *p)
1533
{
1534
	int i;
1535
	char *e, **np;
1536
 
1537
	while(*p != 0) {
1538
		e = strchr(p, ' ');
1539
		if(e != 0)
1540
			*e = '\0';
1541
 
1542
		for(i=0; i < ninclude; i++)
1543
			if(strcmp(p, include[i]) == 0)
1544
				break;
1545
 
1546
		if(i >= ninclude){
1547
			if(i >= maxinclude){
1548
				maxinclude += 20;
1549
				np = alloc(maxinclude * sizeof *np);
1550
				if(include != nil)
1551
					memmove(np, include, (maxinclude - 20) * sizeof *np);
1552
				include = np;
1553
			}
1554
			include[ninclude++] = p;
1555
		}
1556
 
1557
		if(e == 0)
1558
			break;
1559
		p = e+1;
1560
	}
1561
}