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