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