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