xref: /inferno-os/utils/cc/lex.c (revision 2b69dba5038ffd0b59cf30a4c44bce549e5097f8)
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, mydup(1, -1), OWRITE);
207 			mydup(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 	if(mpatof(symb, &yylval.dval)) {
894 		yyerror("overflow in float constant");
895 		yylval.dval = 0;
896 	}
897 	if(c1 & Numflt)
898 		return LFCONST;
899 	return LDCONST;
900 }
901 
902 /*
903  * convert a string, s, to vlong in *v
904  * return conversion overflow.
905  * required syntax is [0[x]]d*
906  */
907 int
908 mpatov(char *s, vlong *v)
909 {
910 	vlong n, nn;
911 	int c;
912 
913 	n = 0;
914 	c = *s;
915 	if(c == '0')
916 		goto oct;
917 	while(c = *s++) {
918 		if(c >= '0' && c <= '9')
919 			nn = n*10 + c-'0';
920 		else
921 			goto bad;
922 		if(n < 0 && nn >= 0)
923 			goto bad;
924 		n = nn;
925 	}
926 	goto out;
927 
928 oct:
929 	s++;
930 	c = *s;
931 	if(c == 'x' || c == 'X')
932 		goto hex;
933 	while(c = *s++) {
934 		if(c >= '0' || c <= '7')
935 			nn = n*8 + c-'0';
936 		else
937 			goto bad;
938 		if(n < 0 && nn >= 0)
939 			goto bad;
940 		n = nn;
941 	}
942 	goto out;
943 
944 hex:
945 	s++;
946 	while(c = *s++) {
947 		if(c >= '0' && c <= '9')
948 			c += 0-'0';
949 		else
950 		if(c >= 'a' && c <= 'f')
951 			c += 10-'a';
952 		else
953 		if(c >= 'A' && c <= 'F')
954 			c += 10-'A';
955 		else
956 			goto bad;
957 		nn = n*16 + c;
958 		if(n < 0 && nn >= 0)
959 			goto bad;
960 		n = nn;
961 	}
962 out:
963 	*v = n;
964 	return 0;
965 
966 bad:
967 	*v = ~0;
968 	return 1;
969 }
970 
971 int
972 getc(void)
973 {
974 	int c;
975 
976 	if(peekc != IGN) {
977 		c = peekc;
978 		peekc = IGN;
979 	} else
980 		c = GETC();
981 	if(c == '\n')
982 		lineno++;
983 	if(c == EOF) {
984 		yyerror("End of file");
985 		errorexit();
986 	}
987 	return c;
988 }
989 
990 long
991 getr(void)
992 {
993 	int c, i;
994 	char str[UTFmax+1];
995 	Rune rune;
996 
997 
998 	c = getc();
999 	if(c < Runeself)
1000 		return c;
1001 	i = 0;
1002 	str[i++] = c;
1003 
1004 loop:
1005 	c = getc();
1006 	str[i++] = c;
1007 	if(!fullrune(str, i))
1008 		goto loop;
1009 	c = chartorune(&rune, str);
1010 	if(rune == Runeerror && c == 1) {
1011 		nearln = lineno;
1012 		diag(Z, "illegal rune in string");
1013 		for(c=0; c<i; c++)
1014 			print(" %.2x", *(uchar*)(str+c));
1015 		print("\n");
1016 	}
1017 	return rune;
1018 }
1019 
1020 int
1021 getnsc(void)
1022 {
1023 	int c;
1024 
1025 	if(peekc != IGN) {
1026 		c = peekc;
1027 		peekc = IGN;
1028 	} else
1029 		c = GETC();
1030 	for(;;) {
1031 		if(!isspace(c))
1032 			return c;
1033 		if(c == '\n') {
1034 			lineno++;
1035 			return c;
1036 		}
1037 		c = GETC();
1038 	}
1039 }
1040 
1041 void
1042 unget(int c)
1043 {
1044 
1045 	peekc = c;
1046 	if(c == '\n')
1047 		lineno--;
1048 }
1049 
1050 long
1051 escchar(long e, int longflg, int escflg)
1052 {
1053 	long c, l;
1054 	int i;
1055 
1056 loop:
1057 	c = getr();
1058 	if(c == '\n') {
1059 		yyerror("newline in string");
1060 		return EOF;
1061 	}
1062 	if(c != '\\') {
1063 		if(c == e)
1064 			c = EOF;
1065 		return c;
1066 	}
1067 	c = getr();
1068 	if(c == 'x') {
1069 		/*
1070 		 * note this is not ansi,
1071 		 * supposed to only accept 2 hex
1072 		 */
1073 		i = 2;
1074 		if(longflg)
1075 			i = 4;
1076 		l = 0;
1077 		for(; i>0; i--) {
1078 			c = getc();
1079 			if(c >= '0' && c <= '9') {
1080 				l = l*16 + c-'0';
1081 				continue;
1082 			}
1083 			if(c >= 'a' && c <= 'f') {
1084 				l = l*16 + c-'a' + 10;
1085 				continue;
1086 			}
1087 			if(c >= 'A' && c <= 'F') {
1088 				l = l*16 + c-'A' + 10;
1089 				continue;
1090 			}
1091 			unget(c);
1092 			break;
1093 		}
1094 		if(escflg)
1095 			l |= ESC;
1096 		return l;
1097 	}
1098 	if(c >= '0' && c <= '7') {
1099 		/*
1100 		 * note this is not ansi,
1101 		 * supposed to only accept 3 oct
1102 		 */
1103 		i = 2;
1104 		if(longflg)
1105 			i = 5;
1106 		l = c - '0';
1107 		for(; i>0; i--) {
1108 			c = getc();
1109 			if(c >= '0' && c <= '7') {
1110 				l = l*8 + c-'0';
1111 				continue;
1112 			}
1113 			unget(c);
1114 		}
1115 		if(escflg)
1116 			l |= ESC;
1117 		return l;
1118 	}
1119 	switch(c)
1120 	{
1121 	case '\n':	goto loop;
1122 	case 'n':	return '\n';
1123 	case 't':	return '\t';
1124 	case 'b':	return '\b';
1125 	case 'r':	return '\r';
1126 	case 'f':	return '\f';
1127 	case 'a':	return '\a';
1128 	case 'v':	return '\v';
1129 	}
1130 	return c;
1131 }
1132 
1133 struct
1134 {
1135 	char	*name;
1136 	ushort	lexical;
1137 	ushort	type;
1138 } itab[] =
1139 {
1140 	"auto",		LAUTO,		0,
1141 	"break",	LBREAK,		0,
1142 	"case",		LCASE,		0,
1143 	"char",		LCHAR,		TCHAR,
1144 	"const",	LCONSTNT,	0,
1145 	"continue",	LCONTINUE,	0,
1146 	"default",	LDEFAULT,	0,
1147 	"do",		LDO,		0,
1148 	"double",	LDOUBLE,	TDOUBLE,
1149 	"else",		LELSE,		0,
1150 	"enum",		LENUM,		0,
1151 	"extern",	LEXTERN,	0,
1152 	"float",	LFLOAT,		TFLOAT,
1153 	"for",		LFOR,		0,
1154 	"goto",		LGOTO,		0,
1155 	"if",		LIF,		0,
1156 	"inline",	LINLINE,	0,
1157 	"int",		LINT,		TINT,
1158 	"long",		LLONG,		TLONG,
1159 	"register",	LREGISTER,	0,
1160 	"restrict",	LRESTRICT,	0,
1161 	"return",	LRETURN,	0,
1162 	"SET",		LSET,		0,
1163 	"short",	LSHORT,		TSHORT,
1164 	"signed",	LSIGNED,	0,
1165 	"signof",	LSIGNOF,	0,
1166 	"sizeof",	LSIZEOF,	0,
1167 	"static",	LSTATIC,	0,
1168 	"struct",	LSTRUCT,	0,
1169 	"switch",	LSWITCH,	0,
1170 	"typedef",	LTYPEDEF,	0,
1171 	"typestr",	LTYPESTR,	0,
1172 	"union",	LUNION,		0,
1173 	"unsigned",	LUNSIGNED,	0,
1174 	"USED",		LUSED,		0,
1175 	"void",		LVOID,		TVOID,
1176 	"volatile",	LVOLATILE,	0,
1177 	"while",	LWHILE,		0,
1178 	0
1179 };
1180 
1181 void
1182 cinit(void)
1183 {
1184 	Sym *s;
1185 	int i;
1186 	Type *t;
1187 
1188 	nerrors = 0;
1189 	lineno = 1;
1190 	iostack = I;
1191 	iofree = I;
1192 	peekc = IGN;
1193 	nhunk = 0;
1194 
1195 	types[TXXX] = T;
1196 	types[TCHAR] = typ(TCHAR, T);
1197 	types[TUCHAR] = typ(TUCHAR, T);
1198 	types[TSHORT] = typ(TSHORT, T);
1199 	types[TUSHORT] = typ(TUSHORT, T);
1200 	types[TINT] = typ(TINT, T);
1201 	types[TUINT] = typ(TUINT, T);
1202 	types[TLONG] = typ(TLONG, T);
1203 	types[TULONG] = typ(TULONG, T);
1204 	types[TVLONG] = typ(TVLONG, T);
1205 	types[TUVLONG] = typ(TUVLONG, T);
1206 	types[TFLOAT] = typ(TFLOAT, T);
1207 	types[TDOUBLE] = typ(TDOUBLE, T);
1208 	types[TVOID] = typ(TVOID, T);
1209 	types[TENUM] = typ(TENUM, T);
1210 	types[TFUNC] = typ(TFUNC, types[TINT]);
1211 	types[TIND] = typ(TIND, types[TVOID]);
1212 
1213 	for(i=0; i<NHASH; i++)
1214 		hash[i] = S;
1215 	for(i=0; itab[i].name; i++) {
1216 		s = slookup(itab[i].name);
1217 		s->lexical = itab[i].lexical;
1218 		if(itab[i].type != 0)
1219 			s->type = types[itab[i].type];
1220 	}
1221 	blockno = 0;
1222 	autobn = 0;
1223 	autoffset = 0;
1224 
1225 	t = typ(TARRAY, types[TCHAR]);
1226 	t->width = 0;
1227 	symstring = slookup(".string");
1228 	symstring->class = CSTATIC;
1229 	symstring->type = t;
1230 
1231 	t = typ(TARRAY, types[TCHAR]);
1232 	t->width = 0;
1233 
1234 	nodproto = new(OPROTO, Z, Z);
1235 	dclstack = D;
1236 
1237 	pathname = allocn(pathname, 0, 100);
1238 	if(mygetwd(pathname, 99) == 0) {
1239 		pathname = allocn(pathname, 100, 900);
1240 		if(mygetwd(pathname, 999) == 0)
1241 			strcpy(pathname, "/???");
1242 	}
1243 
1244 	fmtinstall('O', Oconv);
1245 	fmtinstall('T', Tconv);
1246 	fmtinstall('F', FNconv);
1247 	fmtinstall('L', Lconv);
1248 	fmtinstall('Q', Qconv);
1249 	fmtinstall('|', VBconv);
1250 }
1251 
1252 int
1253 filbuf(void)
1254 {
1255 	Io *i;
1256 
1257 loop:
1258 	i = iostack;
1259 	if(i == I)
1260 		return EOF;
1261 	if(i->f < 0)
1262 		goto pop;
1263 	fi.c = read(i->f, i->b, BUFSIZ) - 1;
1264 	if(fi.c < 0) {
1265 		close(i->f);
1266 		linehist(0, 0);
1267 		goto pop;
1268 	}
1269 	fi.p = i->b + 1;
1270 	return i->b[0] & 0xff;
1271 
1272 pop:
1273 	iostack = i->link;
1274 	i->link = iofree;
1275 	iofree = i;
1276 	i = iostack;
1277 	if(i == I)
1278 		return EOF;
1279 	fi.p = i->p;
1280 	fi.c = i->c;
1281 	if(--fi.c < 0)
1282 		goto loop;
1283 	return *fi.p++ & 0xff;
1284 }
1285 
1286 int
1287 Oconv(Fmt *fp)
1288 {
1289 	int a;
1290 
1291 	a = va_arg(fp->args, int);
1292 	if(a < OXXX || a > OEND)
1293 		return fmtprint(fp, "***badO %d***", a);
1294 
1295 	return fmtstrcpy(fp, onames[a]);
1296 }
1297 
1298 int
1299 Lconv(Fmt *fp)
1300 {
1301 	char str[STRINGSZ], s[STRINGSZ];
1302 	Hist *h;
1303 	struct
1304 	{
1305 		Hist*	incl;	/* start of this include file */
1306 		long	idel;	/* delta line number to apply to include */
1307 		Hist*	line;	/* start of this #line directive */
1308 		long	ldel;	/* delta line number to apply to #line */
1309 	} a[HISTSZ];
1310 	long l, d;
1311 	int i, n;
1312 
1313 	l = va_arg(fp->args, long);
1314 	n = 0;
1315 	for(h = hist; h != H; h = h->link) {
1316 		if(l < h->line)
1317 			break;
1318 		if(h->name) {
1319 			if(h->offset != 0) {		/* #line directive, not #pragma */
1320 				if(n > 0 && n < HISTSZ && h->offset >= 0) {
1321 					a[n-1].line = h;
1322 					a[n-1].ldel = h->line - h->offset + 1;
1323 				}
1324 			} else {
1325 				if(n < HISTSZ) {	/* beginning of file */
1326 					a[n].incl = h;
1327 					a[n].idel = h->line;
1328 					a[n].line = 0;
1329 				}
1330 				n++;
1331 			}
1332 			continue;
1333 		}
1334 		n--;
1335 		if(n > 0 && n < HISTSZ) {
1336 			d = h->line - a[n].incl->line;
1337 			a[n-1].ldel += d;
1338 			a[n-1].idel += d;
1339 		}
1340 	}
1341 	if(n > HISTSZ)
1342 		n = HISTSZ;
1343 	str[0] = 0;
1344 	for(i=n-1; i>=0; i--) {
1345 		if(i != n-1) {
1346 			if(fp->flags & ~(FmtWidth|FmtPrec))	/* BUG ROB - was f3 */
1347 				break;
1348 			strcat(str, " ");
1349 		}
1350 		if(a[i].line)
1351 			snprint(s, STRINGSZ, "%s:%ld[%s:%ld]",
1352 				a[i].line->name, l-a[i].ldel+1,
1353 				a[i].incl->name, l-a[i].idel+1);
1354 		else
1355 			snprint(s, STRINGSZ, "%s:%ld",
1356 				a[i].incl->name, l-a[i].idel+1);
1357 		if(strlen(s)+strlen(str) >= STRINGSZ-10)
1358 			break;
1359 		strcat(str, s);
1360 		l = a[i].incl->line - 1;	/* now print out start of this file */
1361 	}
1362 	if(n == 0)
1363 		strcat(str, "<eof>");
1364 	return fmtstrcpy(fp, str);
1365 }
1366 
1367 int
1368 Tconv(Fmt *fp)
1369 {
1370 	char str[STRINGSZ+20], s[STRINGSZ+20];
1371 	Type *t, *t1;
1372 	int et;
1373 	long n;
1374 
1375 	str[0] = 0;
1376 	for(t = va_arg(fp->args, Type*); t != T; t = t->link) {
1377 		et = t->etype;
1378 		if(str[0])
1379 			strcat(str, " ");
1380 		if(t->garb&~GINCOMPLETE) {
1381 			sprint(s, "%s ", gnames[t->garb&~GINCOMPLETE]);
1382 			if(strlen(str) + strlen(s) < STRINGSZ)
1383 				strcat(str, s);
1384 		}
1385 		sprint(s, "%s", tnames[et]);
1386 		if(strlen(str) + strlen(s) < STRINGSZ)
1387 			strcat(str, s);
1388 		if(et == TFUNC && (t1 = t->down)) {
1389 			sprint(s, "(%T", t1);
1390 			if(strlen(str) + strlen(s) < STRINGSZ)
1391 				strcat(str, s);
1392 			while(t1 = t1->down) {
1393 				sprint(s, ", %T", t1);
1394 				if(strlen(str) + strlen(s) < STRINGSZ)
1395 					strcat(str, s);
1396 			}
1397 			if(strlen(str) + strlen(s) < STRINGSZ)
1398 				strcat(str, ")");
1399 		}
1400 		if(et == TARRAY) {
1401 			n = t->width;
1402 			if(t->link && t->link->width)
1403 				n /= t->link->width;
1404 			sprint(s, "[%ld]", n);
1405 			if(strlen(str) + strlen(s) < STRINGSZ)
1406 				strcat(str, s);
1407 		}
1408 		if(t->nbits) {
1409 			sprint(s, " %d:%d", t->shift, t->nbits);
1410 			if(strlen(str) + strlen(s) < STRINGSZ)
1411 				strcat(str, s);
1412 		}
1413 		if(typesu[et]) {
1414 			if(t->tag) {
1415 				strcat(str, " ");
1416 				if(strlen(str) + strlen(t->tag->name) < STRINGSZ)
1417 					strcat(str, t->tag->name);
1418 			} else
1419 				strcat(str, " {}");
1420 			break;
1421 		}
1422 	}
1423 	return fmtstrcpy(fp, str);
1424 }
1425 
1426 int
1427 FNconv(Fmt *fp)
1428 {
1429 	char *str;
1430 	Node *n;
1431 
1432 	n = va_arg(fp->args, Node*);
1433 	str = "<indirect>";
1434 	if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM))
1435 		str = n->sym->name;
1436 	return fmtstrcpy(fp, str);
1437 }
1438 
1439 int
1440 Qconv(Fmt *fp)
1441 {
1442 	char str[STRINGSZ+20], *s;
1443 	long b;
1444 	int i;
1445 
1446 	str[0] = 0;
1447 	for(b = va_arg(fp->args, long); b;) {
1448 		i = bitno(b);
1449 		if(str[0])
1450 			strcat(str, " ");
1451 		s = qnames[i];
1452 		if(strlen(str) + strlen(s) >= STRINGSZ)
1453 			break;
1454 		strcat(str, s);
1455 		b &= ~(1L << i);
1456 	}
1457 	return fmtstrcpy(fp, str);
1458 }
1459 
1460 int
1461 VBconv(Fmt *fp)
1462 {
1463 	char str[STRINGSZ];
1464 	int i, n, t, pc;
1465 
1466 	n = va_arg(fp->args, int);
1467 	pc = 0;	/* BUG: was printcol */
1468 	i = 0;
1469 	while(pc < n) {
1470 		t = (pc+4) & ~3;
1471 		if(t <= n) {
1472 			str[i++] = '\t';
1473 			pc = t;
1474 			continue;
1475 		}
1476 		str[i++] = ' ';
1477 		pc++;
1478 	}
1479 	str[i] = 0;
1480 
1481 	return fmtstrcpy(fp, str);
1482 }
1483 
1484 /*
1485  * real allocs
1486  */
1487 void*
1488 alloc(long n)
1489 {
1490 	void *p;
1491 
1492 	while((uintptr)hunk & MAXALIGN) {
1493 		hunk++;
1494 		nhunk--;
1495 	}
1496 	while(nhunk < n)
1497 		gethunk();
1498 	p = hunk;
1499 	nhunk -= n;
1500 	hunk += n;
1501 	return p;
1502 }
1503 
1504 void*
1505 allocn(void *p, long on, long n)
1506 {
1507 	void *q;
1508 
1509 	q = (uchar*)p + on;
1510 	if(q != hunk || nhunk < n) {
1511 		while(nhunk < on+n)
1512 			gethunk();
1513 		memmove(hunk, p, on);
1514 		p = hunk;
1515 		hunk += on;
1516 		nhunk -= on;
1517 	}
1518 	hunk += n;
1519 	nhunk -= n;
1520 	return p;
1521 }
1522 
1523 void
1524 setinclude(char *p)
1525 {
1526 	int i;
1527 	char *e;
1528 
1529 	while(*p != 0) {
1530 		e = strchr(p, ' ');
1531 		if(e != 0)
1532 			*e = '\0';
1533 
1534 		for(i=1; i < ninclude; i++)
1535 			if(strcmp(p, include[i]) == 0)
1536 				break;
1537 
1538 		if(i >= ninclude)
1539 			include[ninclude++] = p;
1540 
1541 		if(ninclude > nelem(include)) {
1542 			diag(Z, "ninclude too small %d", nelem(include));
1543 			exits("ninclude");
1544 		}
1545 
1546 		if(e == 0)
1547 			break;
1548 		p = e+1;
1549 	}
1550 }
1551