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