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