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