xref: /inferno-os/utils/c2l/lex.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
174a4d8c2SCharles.Forsyth #include	"cc.h"
274a4d8c2SCharles.Forsyth #include	"y.tab.h"
374a4d8c2SCharles.Forsyth 
474a4d8c2SCharles.Forsyth #ifndef	CPP
574a4d8c2SCharles.Forsyth #define	CPP	"/bin/cpp"
674a4d8c2SCharles.Forsyth #endif
774a4d8c2SCharles.Forsyth 
874a4d8c2SCharles.Forsyth static int ansip;
974a4d8c2SCharles.Forsyth 
1074a4d8c2SCharles.Forsyth void
main(int argc,char * argv[])1174a4d8c2SCharles.Forsyth main(int argc, char *argv[])
1274a4d8c2SCharles.Forsyth {
1374a4d8c2SCharles.Forsyth 	char *defs[50], *p;
1474a4d8c2SCharles.Forsyth 	int nproc, nout, status, i, c, ndef;
1574a4d8c2SCharles.Forsyth 
1674a4d8c2SCharles.Forsyth 	tinit();
1774a4d8c2SCharles.Forsyth 	cinit();
1874a4d8c2SCharles.Forsyth 	ginit();
1974a4d8c2SCharles.Forsyth 	arginit();
2074a4d8c2SCharles.Forsyth 
2174a4d8c2SCharles.Forsyth 	tufield = simplet((1L<<tfield->etype) | BUNSIGNED);
2274a4d8c2SCharles.Forsyth 	ndef = 0;
2374a4d8c2SCharles.Forsyth 	include[ninclude++] = ".";
2474a4d8c2SCharles.Forsyth 	strings = 1;
2574a4d8c2SCharles.Forsyth 	passes = 1;
2674a4d8c2SCharles.Forsyth 
2774a4d8c2SCharles.Forsyth 	ARGBEGIN {
2874a4d8c2SCharles.Forsyth 	default:
2974a4d8c2SCharles.Forsyth 		break;
3074a4d8c2SCharles.Forsyth 
3174a4d8c2SCharles.Forsyth 	case 'p':
3274a4d8c2SCharles.Forsyth 		ansip = 1;
3374a4d8c2SCharles.Forsyth 		break;
3474a4d8c2SCharles.Forsyth 
3574a4d8c2SCharles.Forsyth 	case 'D':
3674a4d8c2SCharles.Forsyth 		p = ARGF();
3774a4d8c2SCharles.Forsyth 		if(p) {
3874a4d8c2SCharles.Forsyth 			defs[ndef++] = p;
3974a4d8c2SCharles.Forsyth 			dodefine(p);
4074a4d8c2SCharles.Forsyth 		}
4174a4d8c2SCharles.Forsyth 		break;
4274a4d8c2SCharles.Forsyth 
4374a4d8c2SCharles.Forsyth 	case 'I':
4474a4d8c2SCharles.Forsyth 		p = ARGF();
4574a4d8c2SCharles.Forsyth 		setinclude(p);
4674a4d8c2SCharles.Forsyth 		break;
4774a4d8c2SCharles.Forsyth 
4874a4d8c2SCharles.Forsyth 	case 'm':
4974a4d8c2SCharles.Forsyth 		domod = 1;
5074a4d8c2SCharles.Forsyth 		break;
5174a4d8c2SCharles.Forsyth 
5274a4d8c2SCharles.Forsyth 	case 'i':
5374a4d8c2SCharles.Forsyth 		doinc = 1;
5474a4d8c2SCharles.Forsyth 		break;
5574a4d8c2SCharles.Forsyth 
5674a4d8c2SCharles.Forsyth 	case 'l':
5774a4d8c2SCharles.Forsyth 		doloc = 1;
5874a4d8c2SCharles.Forsyth 		break;
5974a4d8c2SCharles.Forsyth 
6074a4d8c2SCharles.Forsyth 	case 'c':
6174a4d8c2SCharles.Forsyth 		justcode = 1;
6274a4d8c2SCharles.Forsyth 		break;
6374a4d8c2SCharles.Forsyth 
6474a4d8c2SCharles.Forsyth 	case 'v':
6574a4d8c2SCharles.Forsyth 		comm = 1;
6674a4d8c2SCharles.Forsyth 		break;
6774a4d8c2SCharles.Forsyth 
6874a4d8c2SCharles.Forsyth 	case 's':
6974a4d8c2SCharles.Forsyth 		strings = 0;
7074a4d8c2SCharles.Forsyth 		break;
7174a4d8c2SCharles.Forsyth 
7274a4d8c2SCharles.Forsyth 	case 'S':
7374a4d8c2SCharles.Forsyth 		strings = 2;
7474a4d8c2SCharles.Forsyth 		break;
7574a4d8c2SCharles.Forsyth 
7674a4d8c2SCharles.Forsyth 	case 'M':
7774a4d8c2SCharles.Forsyth 		inmain = 1;
7874a4d8c2SCharles.Forsyth 		break;
7974a4d8c2SCharles.Forsyth 
8074a4d8c2SCharles.Forsyth 	case 'q':
8174a4d8c2SCharles.Forsyth 		passes = 0;
8274a4d8c2SCharles.Forsyth 		break;
8374a4d8c2SCharles.Forsyth 
8474a4d8c2SCharles.Forsyth 	case 'a':
8574a4d8c2SCharles.Forsyth 		doaddr = 1;
8674a4d8c2SCharles.Forsyth 		break;
8774a4d8c2SCharles.Forsyth 
8874a4d8c2SCharles.Forsyth 	case 'A':
8974a4d8c2SCharles.Forsyth 		doaddr = 1;
9074a4d8c2SCharles.Forsyth 		doalladdr = 1;
9174a4d8c2SCharles.Forsyth 		break;
9274a4d8c2SCharles.Forsyth 
9374a4d8c2SCharles.Forsyth 	} ARGEND
9474a4d8c2SCharles.Forsyth 
9574a4d8c2SCharles.Forsyth 	if(doinc)
9674a4d8c2SCharles.Forsyth 		domod = doloc = 0;
9774a4d8c2SCharles.Forsyth 
9874a4d8c2SCharles.Forsyth 	linit();
9974a4d8c2SCharles.Forsyth 
10074a4d8c2SCharles.Forsyth 	if(argc != 1) {
10174a4d8c2SCharles.Forsyth 		print("usage: c2l [-options] file\n");
10274a4d8c2SCharles.Forsyth 		errorexit();
10374a4d8c2SCharles.Forsyth 	}
10474a4d8c2SCharles.Forsyth 	if(argc > 1 && systemtype(Windows)){
10574a4d8c2SCharles.Forsyth 		print("can't compile multiple files on windows\n");
10674a4d8c2SCharles.Forsyth 		errorexit();
10774a4d8c2SCharles.Forsyth 	}
10874a4d8c2SCharles.Forsyth 	if(argc > 1 && !systemtype(Windows)) {
10974a4d8c2SCharles.Forsyth 		nproc = 1;
11074a4d8c2SCharles.Forsyth 		if(p = getenv("NPROC"))
11174a4d8c2SCharles.Forsyth 			nproc = atol(p);	/* */
11274a4d8c2SCharles.Forsyth 		c = 0;
11374a4d8c2SCharles.Forsyth 		nout = 0;
11474a4d8c2SCharles.Forsyth 		for(;;) {
11574a4d8c2SCharles.Forsyth 			while(nout < nproc && argc > 0) {
11674a4d8c2SCharles.Forsyth 				i = myfork();
11774a4d8c2SCharles.Forsyth 				if(i < 0) {
11874a4d8c2SCharles.Forsyth 					i = mywait(&status);
11974a4d8c2SCharles.Forsyth 					if(i < 0) {
12074a4d8c2SCharles.Forsyth 						print("cannot create a process\n");
12174a4d8c2SCharles.Forsyth 						errorexit();
12274a4d8c2SCharles.Forsyth 					}
12374a4d8c2SCharles.Forsyth 					if(status)
12474a4d8c2SCharles.Forsyth 						c++;
12574a4d8c2SCharles.Forsyth 					nout--;
12674a4d8c2SCharles.Forsyth 					continue;
12774a4d8c2SCharles.Forsyth 				}
12874a4d8c2SCharles.Forsyth 				if(i == 0) {
12974a4d8c2SCharles.Forsyth 					fprint(2, "%s:\n", *argv);
13074a4d8c2SCharles.Forsyth 					if (compile(*argv, defs, ndef))
13174a4d8c2SCharles.Forsyth 						errorexit();
13274a4d8c2SCharles.Forsyth 					exits(0);
13374a4d8c2SCharles.Forsyth 				}
13474a4d8c2SCharles.Forsyth 				nout++;
13574a4d8c2SCharles.Forsyth 				argc--;
13674a4d8c2SCharles.Forsyth 				argv++;
13774a4d8c2SCharles.Forsyth 			}
13874a4d8c2SCharles.Forsyth 			i = mywait(&status);
13974a4d8c2SCharles.Forsyth 			if(i < 0) {
14074a4d8c2SCharles.Forsyth 				if(c)
14174a4d8c2SCharles.Forsyth 					errorexit();
14274a4d8c2SCharles.Forsyth 				exits(0);
14374a4d8c2SCharles.Forsyth 			}
14474a4d8c2SCharles.Forsyth 			if(status)
14574a4d8c2SCharles.Forsyth 				c++;
14674a4d8c2SCharles.Forsyth 			nout--;
14774a4d8c2SCharles.Forsyth 		}
14874a4d8c2SCharles.Forsyth 	}
14974a4d8c2SCharles.Forsyth 
15074a4d8c2SCharles.Forsyth 	if(argc == 0)
15174a4d8c2SCharles.Forsyth 		c = compile("stdin", defs, ndef);
15274a4d8c2SCharles.Forsyth 	else
15374a4d8c2SCharles.Forsyth 		c = compile(argv[0], defs, ndef);
15474a4d8c2SCharles.Forsyth 
15574a4d8c2SCharles.Forsyth 	if(c)
15674a4d8c2SCharles.Forsyth 		errorexit();
15774a4d8c2SCharles.Forsyth 	exits(0);
15874a4d8c2SCharles.Forsyth }
15974a4d8c2SCharles.Forsyth 
16074a4d8c2SCharles.Forsyth int
compile(char * file,char ** defs,int ndef)16174a4d8c2SCharles.Forsyth compile(char *file, char **defs, int ndef)
16274a4d8c2SCharles.Forsyth {
16374a4d8c2SCharles.Forsyth 	char ofile[200], incfile[20];
16474a4d8c2SCharles.Forsyth 	char *p, *av[100], opt[256];
16574a4d8c2SCharles.Forsyth 	int i, c, fd[2];
16674a4d8c2SCharles.Forsyth 
16774a4d8c2SCharles.Forsyth 	strcpy(ofile, file);
16874a4d8c2SCharles.Forsyth 	p = utfrrune(ofile, pathchar());
16974a4d8c2SCharles.Forsyth 	if(p) {
17074a4d8c2SCharles.Forsyth 		*p++ = 0;
17174a4d8c2SCharles.Forsyth 		include[0] = strdup(ofile);
17274a4d8c2SCharles.Forsyth 	} else
17374a4d8c2SCharles.Forsyth 		p = ofile;
17474a4d8c2SCharles.Forsyth 
17574a4d8c2SCharles.Forsyth 	USED(p);
17674a4d8c2SCharles.Forsyth 	if(p = getenv("INCLUDE")) {
17774a4d8c2SCharles.Forsyth 		setinclude(p);
17874a4d8c2SCharles.Forsyth 	} else {
17974a4d8c2SCharles.Forsyth 		if(systemtype(Plan9)) {
18074a4d8c2SCharles.Forsyth 			sprint(incfile, "/%s/include", thestring);
18174a4d8c2SCharles.Forsyth 			setinclude(strdup(incfile));
18274a4d8c2SCharles.Forsyth 			setinclude("/sys/include");
18374a4d8c2SCharles.Forsyth 		}
18474a4d8c2SCharles.Forsyth 	}
18574a4d8c2SCharles.Forsyth 	newio();
18674a4d8c2SCharles.Forsyth 
18774a4d8c2SCharles.Forsyth 	/* Use an ANSI preprocessor */
18874a4d8c2SCharles.Forsyth 	if(ansip) {
18974a4d8c2SCharles.Forsyth 		if(systemtype(Windows)) {
19074a4d8c2SCharles.Forsyth 			diag(Z, "-p option not supported on windows");
19174a4d8c2SCharles.Forsyth 			errorexit();
19274a4d8c2SCharles.Forsyth 		}
19374a4d8c2SCharles.Forsyth 		if(mypipe(fd) < 0) {
19474a4d8c2SCharles.Forsyth 			diag(Z, "pipe failed");
19574a4d8c2SCharles.Forsyth 			errorexit();
19674a4d8c2SCharles.Forsyth 		}
19774a4d8c2SCharles.Forsyth 		switch(myfork()) {
19874a4d8c2SCharles.Forsyth 		case -1:
19974a4d8c2SCharles.Forsyth 			diag(Z, "fork failed");
20074a4d8c2SCharles.Forsyth 			errorexit();
20174a4d8c2SCharles.Forsyth 		case 0:
20274a4d8c2SCharles.Forsyth 			close(fd[0]);
20374a4d8c2SCharles.Forsyth 			mydup(fd[1], 1);
20474a4d8c2SCharles.Forsyth 			close(fd[1]);
20574a4d8c2SCharles.Forsyth 			av[0] = CPP;
20674a4d8c2SCharles.Forsyth 			i = 1;
20774a4d8c2SCharles.Forsyth 			for(c = 0; c < ndef; c++) {
20874a4d8c2SCharles.Forsyth 				sprint(opt, "-D%s", defs[c]);
20974a4d8c2SCharles.Forsyth 				av[i++] = strdup(opt);
21074a4d8c2SCharles.Forsyth 			}
21174a4d8c2SCharles.Forsyth 			for(c = 0; c < ninclude; c++) {
21274a4d8c2SCharles.Forsyth 				sprint(opt, "-I%s", include[c]);
21374a4d8c2SCharles.Forsyth 				av[i++] = strdup(opt);
21474a4d8c2SCharles.Forsyth 			}
21574a4d8c2SCharles.Forsyth 			if(strcmp(file, "stdin") != 0)
21674a4d8c2SCharles.Forsyth 				av[i++] = file;
21774a4d8c2SCharles.Forsyth 			av[i] = 0;
21874a4d8c2SCharles.Forsyth 			if(0) {
21974a4d8c2SCharles.Forsyth 				for(c = 0; c < i; c++)
22074a4d8c2SCharles.Forsyth 					fprint(2, "%s ", av[c]);
22174a4d8c2SCharles.Forsyth 				print("\n");
22274a4d8c2SCharles.Forsyth 			}
22374a4d8c2SCharles.Forsyth 			myexec(av[0], av);
22474a4d8c2SCharles.Forsyth 			fprint(2, "can't exec C preprocessor %s: %r\n", CPP);
22574a4d8c2SCharles.Forsyth 			errorexit();
22674a4d8c2SCharles.Forsyth 		default:
22774a4d8c2SCharles.Forsyth 			close(fd[1]);
22874a4d8c2SCharles.Forsyth 			newfile(file, fd[0]);
22974a4d8c2SCharles.Forsyth 			break;
23074a4d8c2SCharles.Forsyth 		}
23174a4d8c2SCharles.Forsyth 	} else {
23274a4d8c2SCharles.Forsyth 		if(strcmp(file, "stdin") == 0)
23374a4d8c2SCharles.Forsyth 			newfile(file, 0);
23474a4d8c2SCharles.Forsyth 		else
23574a4d8c2SCharles.Forsyth 			newfile(file, -1);
23674a4d8c2SCharles.Forsyth 	}
23774a4d8c2SCharles.Forsyth 
23874a4d8c2SCharles.Forsyth 	clbegin();
23974a4d8c2SCharles.Forsyth 	yyparse();
24074a4d8c2SCharles.Forsyth 	clend();
24174a4d8c2SCharles.Forsyth 	newsec(0);
24274a4d8c2SCharles.Forsyth 	return nerrors;
24374a4d8c2SCharles.Forsyth }
24474a4d8c2SCharles.Forsyth 
24574a4d8c2SCharles.Forsyth void
errorexit(void)24674a4d8c2SCharles.Forsyth errorexit(void)
24774a4d8c2SCharles.Forsyth {
24874a4d8c2SCharles.Forsyth 	exits("error");
24974a4d8c2SCharles.Forsyth }
25074a4d8c2SCharles.Forsyth 
25174a4d8c2SCharles.Forsyth void
pushio(void)25274a4d8c2SCharles.Forsyth pushio(void)
25374a4d8c2SCharles.Forsyth {
25474a4d8c2SCharles.Forsyth 	Io *i;
25574a4d8c2SCharles.Forsyth 
25674a4d8c2SCharles.Forsyth 	i = iostack;
25774a4d8c2SCharles.Forsyth 	if(i == I) {
25874a4d8c2SCharles.Forsyth 		yyerror("botch in pushio");
25974a4d8c2SCharles.Forsyth 		errorexit();
26074a4d8c2SCharles.Forsyth 	}
26174a4d8c2SCharles.Forsyth 	i->p = fi.p;
26274a4d8c2SCharles.Forsyth 	i->c = fi.c;
26374a4d8c2SCharles.Forsyth }
26474a4d8c2SCharles.Forsyth 
26574a4d8c2SCharles.Forsyth void
newio(void)26674a4d8c2SCharles.Forsyth newio(void)
26774a4d8c2SCharles.Forsyth {
26874a4d8c2SCharles.Forsyth 	Io *i;
269*45a20ab7Sforsyth 	static int pushdepth = 0;
27074a4d8c2SCharles.Forsyth 
27174a4d8c2SCharles.Forsyth 	i = iofree;
27274a4d8c2SCharles.Forsyth 	if(i == I) {
27374a4d8c2SCharles.Forsyth 		pushdepth++;
27474a4d8c2SCharles.Forsyth 		if(pushdepth > 1000) {
27574a4d8c2SCharles.Forsyth 			yyerror("macro/io expansion too deep");
27674a4d8c2SCharles.Forsyth 			errorexit();
27774a4d8c2SCharles.Forsyth 		}
27874a4d8c2SCharles.Forsyth 		i = alloc(sizeof(*i));
27974a4d8c2SCharles.Forsyth 	} else
28074a4d8c2SCharles.Forsyth 		iofree = i->link;
28174a4d8c2SCharles.Forsyth 	i->c = 0;
28274a4d8c2SCharles.Forsyth 	i->f = -1;
28374a4d8c2SCharles.Forsyth 	ionext = i;
28474a4d8c2SCharles.Forsyth }
28574a4d8c2SCharles.Forsyth 
28674a4d8c2SCharles.Forsyth void
newfile(char * s,int f)28774a4d8c2SCharles.Forsyth newfile(char *s, int f)
28874a4d8c2SCharles.Forsyth {
28974a4d8c2SCharles.Forsyth 	Io *i;
29074a4d8c2SCharles.Forsyth 
29174a4d8c2SCharles.Forsyth 	if(0)
29274a4d8c2SCharles.Forsyth 		print("%L: %s\n", lineno, s);
29374a4d8c2SCharles.Forsyth 
29474a4d8c2SCharles.Forsyth 	i = ionext;
29574a4d8c2SCharles.Forsyth 	i->link = iostack;
29674a4d8c2SCharles.Forsyth 	iostack = i;
29774a4d8c2SCharles.Forsyth 	i->f = f;
29874a4d8c2SCharles.Forsyth 	if(f < 0)
29974a4d8c2SCharles.Forsyth 		i->f = open(s, 0);
30074a4d8c2SCharles.Forsyth 	if(i->f < 0) {
30174a4d8c2SCharles.Forsyth 		yyerror("c2l: %r: %s", s);
30274a4d8c2SCharles.Forsyth 		errorexit();
30374a4d8c2SCharles.Forsyth 	}
30474a4d8c2SCharles.Forsyth 	fi.c = 0;
30574a4d8c2SCharles.Forsyth 	linehist(s, 0);
30674a4d8c2SCharles.Forsyth 	outpush(s);
30774a4d8c2SCharles.Forsyth }
30874a4d8c2SCharles.Forsyth 
30974a4d8c2SCharles.Forsyth Sym*
slookup(char * s)31074a4d8c2SCharles.Forsyth slookup(char *s)
31174a4d8c2SCharles.Forsyth {
31274a4d8c2SCharles.Forsyth 
31374a4d8c2SCharles.Forsyth 	strcpy(symb, s);
31474a4d8c2SCharles.Forsyth 	return lookup();
31574a4d8c2SCharles.Forsyth }
31674a4d8c2SCharles.Forsyth 
31774a4d8c2SCharles.Forsyth Sym*
lookup(void)31874a4d8c2SCharles.Forsyth lookup(void)
31974a4d8c2SCharles.Forsyth {
32074a4d8c2SCharles.Forsyth 	static Sym zsym;
32174a4d8c2SCharles.Forsyth 	Sym *s;
32274a4d8c2SCharles.Forsyth 	ulong h;
32374a4d8c2SCharles.Forsyth 	char *p;
32474a4d8c2SCharles.Forsyth 	int c, n;
32574a4d8c2SCharles.Forsyth 
32674a4d8c2SCharles.Forsyth 	h = 0;
32774a4d8c2SCharles.Forsyth 	for(p=symb; *p;) {
32874a4d8c2SCharles.Forsyth 		h = h * 3;
32974a4d8c2SCharles.Forsyth 		h += *p++;
33074a4d8c2SCharles.Forsyth 	}
33174a4d8c2SCharles.Forsyth 	n = (p - symb) + 1;
33274a4d8c2SCharles.Forsyth 	if((long)h < 0)
33374a4d8c2SCharles.Forsyth 		h = ~h;
33474a4d8c2SCharles.Forsyth 	h %= NHASH;
33574a4d8c2SCharles.Forsyth 	c = symb[0];
33674a4d8c2SCharles.Forsyth 	for(s = hash[h]; s != S; s = s->link) {
33774a4d8c2SCharles.Forsyth 		if(s->name[0] != c)
33874a4d8c2SCharles.Forsyth 			continue;
33974a4d8c2SCharles.Forsyth 		if(strcmp(s->name, symb) == 0)
34074a4d8c2SCharles.Forsyth 			return s;
34174a4d8c2SCharles.Forsyth 	}
34274a4d8c2SCharles.Forsyth 	s = alloc(sizeof(*s));
34374a4d8c2SCharles.Forsyth 	*s = zsym;
34474a4d8c2SCharles.Forsyth 	s->name = alloc(n);
34574a4d8c2SCharles.Forsyth 	memmove(s->name, symb, n);
34674a4d8c2SCharles.Forsyth 
34774a4d8c2SCharles.Forsyth 	strcpy(s->name, symb);
34874a4d8c2SCharles.Forsyth 	s->link = hash[h];
34974a4d8c2SCharles.Forsyth 	hash[h] = s;
35074a4d8c2SCharles.Forsyth 	syminit(s);
35174a4d8c2SCharles.Forsyth 
35274a4d8c2SCharles.Forsyth 	return s;
35374a4d8c2SCharles.Forsyth }
35474a4d8c2SCharles.Forsyth 
35574a4d8c2SCharles.Forsyth void
syminit(Sym * s)35674a4d8c2SCharles.Forsyth syminit(Sym *s)
35774a4d8c2SCharles.Forsyth {
35874a4d8c2SCharles.Forsyth 	s->lexical = LNAME;
35974a4d8c2SCharles.Forsyth 	s->type = T;
36074a4d8c2SCharles.Forsyth 	s->suetag = T;
36174a4d8c2SCharles.Forsyth 	s->class = CXXX;
36274a4d8c2SCharles.Forsyth 	s->lname = s->mod = nil;
36374a4d8c2SCharles.Forsyth 	s->lineno = lineno;
36474a4d8c2SCharles.Forsyth 	s->tenum = T;
36574a4d8c2SCharles.Forsyth }
36674a4d8c2SCharles.Forsyth 
36774a4d8c2SCharles.Forsyth #define	EOF	(-1)
36874a4d8c2SCharles.Forsyth #define	IGN	(-2)
36974a4d8c2SCharles.Forsyth #define	ESC	(1<<20)
37074a4d8c2SCharles.Forsyth #define	GETC()	((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff))
37174a4d8c2SCharles.Forsyth 
37274a4d8c2SCharles.Forsyth enum
37374a4d8c2SCharles.Forsyth {
37474a4d8c2SCharles.Forsyth 	Numdec		= 1<<0,
37574a4d8c2SCharles.Forsyth 	Numlong		= 1<<1,
37674a4d8c2SCharles.Forsyth 	Numuns		= 1<<2,
37774a4d8c2SCharles.Forsyth 	Numvlong	= 1<<3,
37874a4d8c2SCharles.Forsyth 	Numflt		= 1<<4,
37974a4d8c2SCharles.Forsyth };
38074a4d8c2SCharles.Forsyth 
38174a4d8c2SCharles.Forsyth static int ypeek = 0;
38274a4d8c2SCharles.Forsyth 
38374a4d8c2SCharles.Forsyth long
yylex(void)38474a4d8c2SCharles.Forsyth yylex(void)
38574a4d8c2SCharles.Forsyth {
38674a4d8c2SCharles.Forsyth 	vlong vv;
38774a4d8c2SCharles.Forsyth 	long c, c1;
38874a4d8c2SCharles.Forsyth 	char *cp;
38974a4d8c2SCharles.Forsyth 	Rune rune;
39074a4d8c2SCharles.Forsyth 	Sym *s;
39174a4d8c2SCharles.Forsyth 
39274a4d8c2SCharles.Forsyth 	if(peekc != IGN) {
39374a4d8c2SCharles.Forsyth 		c = peekc;
39474a4d8c2SCharles.Forsyth 		peekc = IGN;
39574a4d8c2SCharles.Forsyth 		goto l1;
39674a4d8c2SCharles.Forsyth 	}
39774a4d8c2SCharles.Forsyth l0:
39874a4d8c2SCharles.Forsyth 	c = GETC();
39974a4d8c2SCharles.Forsyth 
40074a4d8c2SCharles.Forsyth l1:
40174a4d8c2SCharles.Forsyth 	if(c >= Runeself) {
40274a4d8c2SCharles.Forsyth 		/*
40374a4d8c2SCharles.Forsyth 		 * extension --
40474a4d8c2SCharles.Forsyth 		 *	all multibyte runes are alpha
40574a4d8c2SCharles.Forsyth 		 */
40674a4d8c2SCharles.Forsyth 		cp = symb;
40774a4d8c2SCharles.Forsyth 		goto talph;
40874a4d8c2SCharles.Forsyth 	}
40974a4d8c2SCharles.Forsyth 	if(isspace(c)) {
41074a4d8c2SCharles.Forsyth 		if(c == '\n')
41174a4d8c2SCharles.Forsyth 			lineno++;
41274a4d8c2SCharles.Forsyth 		goto l0;
41374a4d8c2SCharles.Forsyth 	}
41474a4d8c2SCharles.Forsyth 	if(isalpha(c)) {
41574a4d8c2SCharles.Forsyth 		cp = symb;
41674a4d8c2SCharles.Forsyth 		if(c != 'L')
41774a4d8c2SCharles.Forsyth 			goto talph;
41874a4d8c2SCharles.Forsyth 		*cp++ = c;
41974a4d8c2SCharles.Forsyth 		c = GETC();
42074a4d8c2SCharles.Forsyth 		if(c == '\'') {
42174a4d8c2SCharles.Forsyth 			/* L'x' */
42274a4d8c2SCharles.Forsyth 			c = escchar('\'', 1, 0);
42374a4d8c2SCharles.Forsyth 			if(c == EOF)
42474a4d8c2SCharles.Forsyth 				c = '\'';
42574a4d8c2SCharles.Forsyth 			c1 = escchar('\'', 1, 0);
42674a4d8c2SCharles.Forsyth 			if(c1 != EOF) {
42774a4d8c2SCharles.Forsyth 				yyerror("missing '");
42874a4d8c2SCharles.Forsyth 				peekc = c1;
42974a4d8c2SCharles.Forsyth 			}
43074a4d8c2SCharles.Forsyth 			yylval.vval = convvtox(c, TUSHORT);
43174a4d8c2SCharles.Forsyth 			return LUCONST;
43274a4d8c2SCharles.Forsyth 		}
43374a4d8c2SCharles.Forsyth 		if(c == '"') {
43474a4d8c2SCharles.Forsyth 			goto caselq;
43574a4d8c2SCharles.Forsyth 		}
43674a4d8c2SCharles.Forsyth 		goto talph;
43774a4d8c2SCharles.Forsyth 	}
43874a4d8c2SCharles.Forsyth 	if(isdigit(c))
43974a4d8c2SCharles.Forsyth 		goto tnum;
44074a4d8c2SCharles.Forsyth 	switch(c)
44174a4d8c2SCharles.Forsyth 	{
44274a4d8c2SCharles.Forsyth 
44374a4d8c2SCharles.Forsyth 	case EOF:
44474a4d8c2SCharles.Forsyth 		peekc = EOF;
44574a4d8c2SCharles.Forsyth 		return -1;
44674a4d8c2SCharles.Forsyth 
44774a4d8c2SCharles.Forsyth 	case '_':
44874a4d8c2SCharles.Forsyth 		cp = symb;
44974a4d8c2SCharles.Forsyth 		goto talph;
45074a4d8c2SCharles.Forsyth 
45174a4d8c2SCharles.Forsyth 	case '#':
45274a4d8c2SCharles.Forsyth 		domacro();
45374a4d8c2SCharles.Forsyth 		goto l0;
45474a4d8c2SCharles.Forsyth 
45574a4d8c2SCharles.Forsyth 	case '.':
45674a4d8c2SCharles.Forsyth 		c1 = GETC();
45774a4d8c2SCharles.Forsyth 		if(isdigit(c1)) {
45874a4d8c2SCharles.Forsyth 			cp = symb;
45974a4d8c2SCharles.Forsyth 			*cp++ = c;
46074a4d8c2SCharles.Forsyth 			c = c1;
46174a4d8c2SCharles.Forsyth 			c1 = 0;
46274a4d8c2SCharles.Forsyth 			goto casedot;
46374a4d8c2SCharles.Forsyth 		}
46474a4d8c2SCharles.Forsyth 		break;
46574a4d8c2SCharles.Forsyth 
46674a4d8c2SCharles.Forsyth 	case '"':
46774a4d8c2SCharles.Forsyth 		strcpy(symb, "\"<string>\"");
46874a4d8c2SCharles.Forsyth 		cp = alloc(0);
46974a4d8c2SCharles.Forsyth 		c1 = 0;
47074a4d8c2SCharles.Forsyth 
47174a4d8c2SCharles.Forsyth 		/* "..." */
47274a4d8c2SCharles.Forsyth 		for(;;) {
47374a4d8c2SCharles.Forsyth 			c = escchar('"', 0, 1);
47474a4d8c2SCharles.Forsyth 			if(c == EOF)
47574a4d8c2SCharles.Forsyth 				break;
47674a4d8c2SCharles.Forsyth 			if(c & ESC) {
47774a4d8c2SCharles.Forsyth 				cp = allocn(cp, c1, 1);
47874a4d8c2SCharles.Forsyth 				cp[c1++] = c;
47974a4d8c2SCharles.Forsyth 			} else {
48074a4d8c2SCharles.Forsyth 				rune = c;
48174a4d8c2SCharles.Forsyth 				c = runelen(rune);
48274a4d8c2SCharles.Forsyth 				cp = allocn(cp, c1, c);
48374a4d8c2SCharles.Forsyth 				runetochar(cp+c1, &rune);
48474a4d8c2SCharles.Forsyth 				c1 += c;
48574a4d8c2SCharles.Forsyth 			}
48674a4d8c2SCharles.Forsyth 		}
48774a4d8c2SCharles.Forsyth 		yylval.sval.l = c1;
48874a4d8c2SCharles.Forsyth 		do {
48974a4d8c2SCharles.Forsyth 			cp = allocn(cp, c1, 1);
49074a4d8c2SCharles.Forsyth 			cp[c1++] = 0;
49174a4d8c2SCharles.Forsyth 		} while(c1 & MAXALIGN);
49274a4d8c2SCharles.Forsyth 		yylval.sval.s = cp;
49374a4d8c2SCharles.Forsyth 		return LSTRING;
49474a4d8c2SCharles.Forsyth 
49574a4d8c2SCharles.Forsyth 	caselq:
49674a4d8c2SCharles.Forsyth 		/* L"..." */
49774a4d8c2SCharles.Forsyth 		strcpy(symb, "\"L<string>\"");
49874a4d8c2SCharles.Forsyth 		cp = alloc(0);
49974a4d8c2SCharles.Forsyth 		c1 = 0;
50074a4d8c2SCharles.Forsyth 		for(;;) {
50174a4d8c2SCharles.Forsyth 			c = escchar('"', 1, 0);
50274a4d8c2SCharles.Forsyth 			if(c == EOF)
50374a4d8c2SCharles.Forsyth 				break;
50474a4d8c2SCharles.Forsyth 			cp = allocn(cp, c1, sizeof(ushort));
50574a4d8c2SCharles.Forsyth 			*(ushort*)(cp + c1) = c;
50674a4d8c2SCharles.Forsyth 			c1 += sizeof(ushort);
50774a4d8c2SCharles.Forsyth 		}
50874a4d8c2SCharles.Forsyth 		yylval.sval.l = c1;
50974a4d8c2SCharles.Forsyth 		do {
51074a4d8c2SCharles.Forsyth 			cp = allocn(cp, c1, sizeof(ushort));
51174a4d8c2SCharles.Forsyth 			*(ushort*)(cp + c1) = 0;
51274a4d8c2SCharles.Forsyth 			c1 += sizeof(ushort);
51374a4d8c2SCharles.Forsyth 		} while(c1 & MAXALIGN);
51474a4d8c2SCharles.Forsyth 		yylval.sval.s = cp;
51574a4d8c2SCharles.Forsyth 		return LLSTRING;
51674a4d8c2SCharles.Forsyth 
51774a4d8c2SCharles.Forsyth 	case '\'':
51874a4d8c2SCharles.Forsyth 		/* '.' */
51974a4d8c2SCharles.Forsyth 		c = escchar('\'', 0, 0);
52074a4d8c2SCharles.Forsyth 		if(c == EOF)
52174a4d8c2SCharles.Forsyth 			c = '\'';
52274a4d8c2SCharles.Forsyth 		c1 = escchar('\'', 0, 0);
52374a4d8c2SCharles.Forsyth 		if(c1 != EOF) {
52474a4d8c2SCharles.Forsyth 			yyerror("missing '");
52574a4d8c2SCharles.Forsyth 			peekc = c1;
52674a4d8c2SCharles.Forsyth 		}
52774a4d8c2SCharles.Forsyth 		vv = c;
52874a4d8c2SCharles.Forsyth 		yylval.vval = convvtox(vv, TUCHAR);
52974a4d8c2SCharles.Forsyth 		if(yylval.vval != vv)
53074a4d8c2SCharles.Forsyth 			yyerror("overflow in character constant: 0x%lx", c);
53174a4d8c2SCharles.Forsyth 		else
53274a4d8c2SCharles.Forsyth 		if(c & 0x80)
53374a4d8c2SCharles.Forsyth 			warn(Z, "sign-extended character constant");
53474a4d8c2SCharles.Forsyth 		yylval.vval = convvtox(vv, TCHAR);
53574a4d8c2SCharles.Forsyth 		return LCHARACTER;
53674a4d8c2SCharles.Forsyth 
53774a4d8c2SCharles.Forsyth 	case '/':
53874a4d8c2SCharles.Forsyth 		c1 = GETC();
53974a4d8c2SCharles.Forsyth 		if(c1 == '*') {
54074a4d8c2SCharles.Forsyth 			startcom(lineno);
54174a4d8c2SCharles.Forsyth 			for(;;) {
54274a4d8c2SCharles.Forsyth 				c = getr();
54374a4d8c2SCharles.Forsyth 				if(c == '*'){
54474a4d8c2SCharles.Forsyth 					while(c == '*') {
54574a4d8c2SCharles.Forsyth 						c = getr();
54674a4d8c2SCharles.Forsyth 						if(c == '/'){
54774a4d8c2SCharles.Forsyth 							endcom();
54874a4d8c2SCharles.Forsyth 							goto l0;
54974a4d8c2SCharles.Forsyth 						}
55074a4d8c2SCharles.Forsyth 						addcom('*');
55174a4d8c2SCharles.Forsyth 					}
55274a4d8c2SCharles.Forsyth 					addcom(c);
55374a4d8c2SCharles.Forsyth 				}
55474a4d8c2SCharles.Forsyth 				else
55574a4d8c2SCharles.Forsyth 					addcom(c);
55674a4d8c2SCharles.Forsyth 				if(c == EOF) {
55774a4d8c2SCharles.Forsyth 					yyerror("eof in comment");
55874a4d8c2SCharles.Forsyth 					errorexit();
55974a4d8c2SCharles.Forsyth 				}
56074a4d8c2SCharles.Forsyth 			}
56174a4d8c2SCharles.Forsyth 		}
56274a4d8c2SCharles.Forsyth 		if(c1 == '/') {
56374a4d8c2SCharles.Forsyth 			startcom(lineno);
56474a4d8c2SCharles.Forsyth 			for(;;) {
56574a4d8c2SCharles.Forsyth 				c = getr();
56674a4d8c2SCharles.Forsyth 				if(c == '\n'){
56774a4d8c2SCharles.Forsyth 					endcom();
56874a4d8c2SCharles.Forsyth 					goto l0;
56974a4d8c2SCharles.Forsyth 				}
57074a4d8c2SCharles.Forsyth 				addcom(c);
57174a4d8c2SCharles.Forsyth 				if(c == EOF) {
57274a4d8c2SCharles.Forsyth 					yyerror("eof in comment");
57374a4d8c2SCharles.Forsyth 					errorexit();
57474a4d8c2SCharles.Forsyth 				}
57574a4d8c2SCharles.Forsyth 			}
57674a4d8c2SCharles.Forsyth 		}
57774a4d8c2SCharles.Forsyth 		if(c1 == '=')
57874a4d8c2SCharles.Forsyth 			return LDVE;
57974a4d8c2SCharles.Forsyth 		break;
58074a4d8c2SCharles.Forsyth 
58174a4d8c2SCharles.Forsyth 	case '*':
58274a4d8c2SCharles.Forsyth 		c1 = GETC();
58374a4d8c2SCharles.Forsyth 		if(c1 == '=')
58474a4d8c2SCharles.Forsyth 			return LMLE;
58574a4d8c2SCharles.Forsyth 		break;
58674a4d8c2SCharles.Forsyth 
58774a4d8c2SCharles.Forsyth 	case '%':
58874a4d8c2SCharles.Forsyth 		c1 = GETC();
58974a4d8c2SCharles.Forsyth 		if(c1 == '=')
59074a4d8c2SCharles.Forsyth 			return LMDE;
59174a4d8c2SCharles.Forsyth 		break;
59274a4d8c2SCharles.Forsyth 
59374a4d8c2SCharles.Forsyth 	case '+':
59474a4d8c2SCharles.Forsyth 		c1 = GETC();
59574a4d8c2SCharles.Forsyth 		if(c1 == '+')
59674a4d8c2SCharles.Forsyth 			return LPP;
59774a4d8c2SCharles.Forsyth 		if(c1 == '=')
59874a4d8c2SCharles.Forsyth 			return LPE;
59974a4d8c2SCharles.Forsyth 		break;
60074a4d8c2SCharles.Forsyth 
60174a4d8c2SCharles.Forsyth 	case '-':
60274a4d8c2SCharles.Forsyth 		c1 = GETC();
60374a4d8c2SCharles.Forsyth 		if(c1 == '-')
60474a4d8c2SCharles.Forsyth 			return LMM;
60574a4d8c2SCharles.Forsyth 		if(c1 == '=')
60674a4d8c2SCharles.Forsyth 			return LME;
60774a4d8c2SCharles.Forsyth 		if(c1 == '>')
60874a4d8c2SCharles.Forsyth 			return LMG;
60974a4d8c2SCharles.Forsyth 		break;
61074a4d8c2SCharles.Forsyth 
61174a4d8c2SCharles.Forsyth 	case '>':
61274a4d8c2SCharles.Forsyth 		c1 = GETC();
61374a4d8c2SCharles.Forsyth 		if(c1 == '>') {
61474a4d8c2SCharles.Forsyth 			c = LRSH;
61574a4d8c2SCharles.Forsyth 			c1 = GETC();
61674a4d8c2SCharles.Forsyth 			if(c1 == '=')
61774a4d8c2SCharles.Forsyth 				return LRSHE;
61874a4d8c2SCharles.Forsyth 			break;
61974a4d8c2SCharles.Forsyth 		}
62074a4d8c2SCharles.Forsyth 		if(c1 == '=')
62174a4d8c2SCharles.Forsyth 			return LGE;
62274a4d8c2SCharles.Forsyth 		break;
62374a4d8c2SCharles.Forsyth 
62474a4d8c2SCharles.Forsyth 	case '<':
62574a4d8c2SCharles.Forsyth 		c1 = GETC();
62674a4d8c2SCharles.Forsyth 		if(c1 == '<') {
62774a4d8c2SCharles.Forsyth 			c = LLSH;
62874a4d8c2SCharles.Forsyth 			c1 = GETC();
62974a4d8c2SCharles.Forsyth 			if(c1 == '=')
63074a4d8c2SCharles.Forsyth 				return LLSHE;
63174a4d8c2SCharles.Forsyth 			break;
63274a4d8c2SCharles.Forsyth 		}
63374a4d8c2SCharles.Forsyth 		if(c1 == '=')
63474a4d8c2SCharles.Forsyth 			return LLE;
63574a4d8c2SCharles.Forsyth 		break;
63674a4d8c2SCharles.Forsyth 
63774a4d8c2SCharles.Forsyth 	case '=':
63874a4d8c2SCharles.Forsyth 		c1 = GETC();
63974a4d8c2SCharles.Forsyth 		if(c1 == '=')
64074a4d8c2SCharles.Forsyth 			return LEQ;
64174a4d8c2SCharles.Forsyth 		break;
64274a4d8c2SCharles.Forsyth 
64374a4d8c2SCharles.Forsyth 	case '!':
64474a4d8c2SCharles.Forsyth 		c1 = GETC();
64574a4d8c2SCharles.Forsyth 		if(c1 == '=')
64674a4d8c2SCharles.Forsyth 			return LNE;
64774a4d8c2SCharles.Forsyth 		break;
64874a4d8c2SCharles.Forsyth 
64974a4d8c2SCharles.Forsyth 	case '&':
65074a4d8c2SCharles.Forsyth 		c1 = GETC();
65174a4d8c2SCharles.Forsyth 		if(c1 == '&')
65274a4d8c2SCharles.Forsyth 			return LANDAND;
65374a4d8c2SCharles.Forsyth 		if(c1 == '=')
65474a4d8c2SCharles.Forsyth 			return LANDE;
65574a4d8c2SCharles.Forsyth 		break;
65674a4d8c2SCharles.Forsyth 
65774a4d8c2SCharles.Forsyth 	case '|':
65874a4d8c2SCharles.Forsyth 		c1 = GETC();
65974a4d8c2SCharles.Forsyth 		if(c1 == '|')
66074a4d8c2SCharles.Forsyth 			return LOROR;
66174a4d8c2SCharles.Forsyth 		if(c1 == '=')
66274a4d8c2SCharles.Forsyth 			return LORE;
66374a4d8c2SCharles.Forsyth 		break;
66474a4d8c2SCharles.Forsyth 
66574a4d8c2SCharles.Forsyth 	case '^':
66674a4d8c2SCharles.Forsyth 		c1 = GETC();
66774a4d8c2SCharles.Forsyth 		if(c1 == '=')
66874a4d8c2SCharles.Forsyth 			return LXORE;
66974a4d8c2SCharles.Forsyth 		break;
67074a4d8c2SCharles.Forsyth 
67174a4d8c2SCharles.Forsyth 	default:
67274a4d8c2SCharles.Forsyth 		return c;
67374a4d8c2SCharles.Forsyth 	}
67474a4d8c2SCharles.Forsyth 	peekc = c1;
67574a4d8c2SCharles.Forsyth 	return c;
67674a4d8c2SCharles.Forsyth 
67774a4d8c2SCharles.Forsyth talph:
67874a4d8c2SCharles.Forsyth 	/*
67974a4d8c2SCharles.Forsyth 	 * cp is set to symb and some
68074a4d8c2SCharles.Forsyth 	 * prefix has been stored
68174a4d8c2SCharles.Forsyth 	 */
68274a4d8c2SCharles.Forsyth 	for(;;) {
68374a4d8c2SCharles.Forsyth 		if(c >= Runeself) {
68474a4d8c2SCharles.Forsyth 			for(c1=0;;) {
68574a4d8c2SCharles.Forsyth 				cp[c1++] = c;
68674a4d8c2SCharles.Forsyth 				if(fullrune(cp, c1))
68774a4d8c2SCharles.Forsyth 					break;
68874a4d8c2SCharles.Forsyth 				c = GETC();
68974a4d8c2SCharles.Forsyth 			}
69074a4d8c2SCharles.Forsyth 			cp += c1;
69174a4d8c2SCharles.Forsyth 			c = GETC();
69274a4d8c2SCharles.Forsyth 			continue;
69374a4d8c2SCharles.Forsyth 		}
69474a4d8c2SCharles.Forsyth 		if(!isalnum(c) && c != '_')
69574a4d8c2SCharles.Forsyth 			break;
69674a4d8c2SCharles.Forsyth 		*cp++ = c;
69774a4d8c2SCharles.Forsyth 		c = GETC();
69874a4d8c2SCharles.Forsyth 	}
69974a4d8c2SCharles.Forsyth 	*cp = 0;
70074a4d8c2SCharles.Forsyth 	if(0)
70174a4d8c2SCharles.Forsyth 		print("%L: %s\n", lineno, symb);
70274a4d8c2SCharles.Forsyth 	peekc = c;
70374a4d8c2SCharles.Forsyth 	s = lookup();
70474a4d8c2SCharles.Forsyth 	if(s->macro && !ypeek) {
70574a4d8c2SCharles.Forsyth 		newio();
70674a4d8c2SCharles.Forsyth 		cp = ionext->b;
70774a4d8c2SCharles.Forsyth 		macexpand(s, cp);
70874a4d8c2SCharles.Forsyth 		pushio();
70974a4d8c2SCharles.Forsyth 		ionext->link = iostack;
71074a4d8c2SCharles.Forsyth 		iostack = ionext;
71174a4d8c2SCharles.Forsyth 		fi.p = cp;
71274a4d8c2SCharles.Forsyth 		fi.c = strlen(cp);
71374a4d8c2SCharles.Forsyth 		if(peekc != IGN) {
71474a4d8c2SCharles.Forsyth 			cp[fi.c++] = peekc;
71574a4d8c2SCharles.Forsyth 			cp[fi.c] = 0;
71674a4d8c2SCharles.Forsyth 			peekc = IGN;
71774a4d8c2SCharles.Forsyth 		}
71874a4d8c2SCharles.Forsyth 		/* outpush(nil); */
71974a4d8c2SCharles.Forsyth 		goto l0;
72074a4d8c2SCharles.Forsyth 	}
72174a4d8c2SCharles.Forsyth 	yylval.sym = s;
72274a4d8c2SCharles.Forsyth 	if(s->class == CTYPEDEF) {
72374a4d8c2SCharles.Forsyth 		if(s->type && typesu[s->type->etype])
72474a4d8c2SCharles.Forsyth 			return LCTYPE;
72574a4d8c2SCharles.Forsyth 		return LSTYPE;
72674a4d8c2SCharles.Forsyth 	}
72774a4d8c2SCharles.Forsyth 	return s->lexical;
72874a4d8c2SCharles.Forsyth 
72974a4d8c2SCharles.Forsyth tnum:
73074a4d8c2SCharles.Forsyth 	lastnumbase = KDEC;
73174a4d8c2SCharles.Forsyth 	c1 = 0;
73274a4d8c2SCharles.Forsyth 	cp = symb;
73374a4d8c2SCharles.Forsyth 	if(c != '0') {
73474a4d8c2SCharles.Forsyth 		c1 |= Numdec;
73574a4d8c2SCharles.Forsyth 		for(;;) {
73674a4d8c2SCharles.Forsyth 			*cp++ = c;
73774a4d8c2SCharles.Forsyth 			c = GETC();
73874a4d8c2SCharles.Forsyth 			if(isdigit(c))
73974a4d8c2SCharles.Forsyth 				continue;
74074a4d8c2SCharles.Forsyth 			goto dc;
74174a4d8c2SCharles.Forsyth 		}
74274a4d8c2SCharles.Forsyth 	}
74374a4d8c2SCharles.Forsyth 	*cp++ = c;
74474a4d8c2SCharles.Forsyth 	c = GETC();
74574a4d8c2SCharles.Forsyth 	if(c == 'x' || c == 'X'){
74674a4d8c2SCharles.Forsyth 		lastnumbase = KHEX;
74774a4d8c2SCharles.Forsyth 		for(;;) {
74874a4d8c2SCharles.Forsyth 			*cp++ = c;
74974a4d8c2SCharles.Forsyth 			c = GETC();
75074a4d8c2SCharles.Forsyth 			if(isdigit(c))
75174a4d8c2SCharles.Forsyth 				continue;
75274a4d8c2SCharles.Forsyth 			if(c >= 'a' && c <= 'f')
75374a4d8c2SCharles.Forsyth 				continue;
75474a4d8c2SCharles.Forsyth 			if(c >= 'A' && c <= 'F')
75574a4d8c2SCharles.Forsyth 				continue;
75674a4d8c2SCharles.Forsyth 			if(cp == symb+2)
75774a4d8c2SCharles.Forsyth 				yyerror("malformed hex constant");
75874a4d8c2SCharles.Forsyth 			goto ncu;
75974a4d8c2SCharles.Forsyth 		}
76074a4d8c2SCharles.Forsyth 	}
76174a4d8c2SCharles.Forsyth 	else
76274a4d8c2SCharles.Forsyth 		lastnumbase = KOCT;
76374a4d8c2SCharles.Forsyth 	if(c < '0' || c > '7'){
76474a4d8c2SCharles.Forsyth 		lastnumbase = KDEC;
76574a4d8c2SCharles.Forsyth 		goto dc;
76674a4d8c2SCharles.Forsyth 	}
76774a4d8c2SCharles.Forsyth 	for(;;) {
76874a4d8c2SCharles.Forsyth 		if(c >= '0' && c <= '7') {
76974a4d8c2SCharles.Forsyth 			*cp++ = c;
77074a4d8c2SCharles.Forsyth 			c = GETC();
77174a4d8c2SCharles.Forsyth 			continue;
77274a4d8c2SCharles.Forsyth 		}
77374a4d8c2SCharles.Forsyth 		goto ncu;
77474a4d8c2SCharles.Forsyth 	}
77574a4d8c2SCharles.Forsyth 
77674a4d8c2SCharles.Forsyth dc:
77774a4d8c2SCharles.Forsyth 	if(c == '.')
77874a4d8c2SCharles.Forsyth 		goto casedot;
77974a4d8c2SCharles.Forsyth 	if(c == 'e' || c == 'E')
78074a4d8c2SCharles.Forsyth 		goto casee;
78174a4d8c2SCharles.Forsyth 
78274a4d8c2SCharles.Forsyth ncu:
78374a4d8c2SCharles.Forsyth 	if((c == 'U' || c == 'u') && !(c1 & Numuns)) {
78474a4d8c2SCharles.Forsyth 		c = GETC();
78574a4d8c2SCharles.Forsyth 		c1 |= Numuns;
78674a4d8c2SCharles.Forsyth 		goto ncu;
78774a4d8c2SCharles.Forsyth 	}
78874a4d8c2SCharles.Forsyth 	if((c == 'L' || c == 'l') && !(c1 & Numvlong)) {
78974a4d8c2SCharles.Forsyth 		c = GETC();
79074a4d8c2SCharles.Forsyth 		if(c1 & Numlong)
79174a4d8c2SCharles.Forsyth 			c1 |= Numvlong;
79274a4d8c2SCharles.Forsyth 		c1 |= Numlong;
79374a4d8c2SCharles.Forsyth 		goto ncu;
79474a4d8c2SCharles.Forsyth 	}
79574a4d8c2SCharles.Forsyth 	*cp = 0;
79674a4d8c2SCharles.Forsyth 	peekc = c;
79774a4d8c2SCharles.Forsyth 	if(mpatov(symb, &yylval.vval))
79874a4d8c2SCharles.Forsyth 		yyerror("overflow in constant");
79974a4d8c2SCharles.Forsyth 
80074a4d8c2SCharles.Forsyth 	vv = yylval.vval;
80174a4d8c2SCharles.Forsyth 	if(c1 & Numvlong) {
80274a4d8c2SCharles.Forsyth 		if(c1 & Numuns) {
80374a4d8c2SCharles.Forsyth 			c = LUVLCONST;
80474a4d8c2SCharles.Forsyth 			goto nret;
80574a4d8c2SCharles.Forsyth 		}
80674a4d8c2SCharles.Forsyth 		yylval.vval = convvtox(yylval.vval, TVLONG);
80774a4d8c2SCharles.Forsyth 		if(yylval.vval < 0) {
80874a4d8c2SCharles.Forsyth 			c = LUVLCONST;
80974a4d8c2SCharles.Forsyth 			goto nret;
81074a4d8c2SCharles.Forsyth 		}
81174a4d8c2SCharles.Forsyth 		c = LVLCONST;
81274a4d8c2SCharles.Forsyth 		goto nret;
81374a4d8c2SCharles.Forsyth 	}
81474a4d8c2SCharles.Forsyth 	if(c1 & Numlong) {
81574a4d8c2SCharles.Forsyth 		if(c1 & Numuns) {
81674a4d8c2SCharles.Forsyth 			c = LULCONST;
81774a4d8c2SCharles.Forsyth 			goto nret;
81874a4d8c2SCharles.Forsyth 		}
81974a4d8c2SCharles.Forsyth 		yylval.vval = convvtox(yylval.vval, TLONG);
82074a4d8c2SCharles.Forsyth 		if(yylval.vval < 0) {
82174a4d8c2SCharles.Forsyth 			c = LULCONST;
82274a4d8c2SCharles.Forsyth 			goto nret;
82374a4d8c2SCharles.Forsyth 		}
82474a4d8c2SCharles.Forsyth 		c = LLCONST;
82574a4d8c2SCharles.Forsyth 		goto nret;
82674a4d8c2SCharles.Forsyth 	}
82774a4d8c2SCharles.Forsyth 	if(c1 & Numuns) {
82874a4d8c2SCharles.Forsyth 		c = LUCONST;
82974a4d8c2SCharles.Forsyth 		goto nret;
83074a4d8c2SCharles.Forsyth 	}
83174a4d8c2SCharles.Forsyth 	yylval.vval = convvtox(yylval.vval, TINT);
83274a4d8c2SCharles.Forsyth 	if(yylval.vval < 0) {
83374a4d8c2SCharles.Forsyth 		c = LUCONST;
83474a4d8c2SCharles.Forsyth 		goto nret;
83574a4d8c2SCharles.Forsyth 	}
83674a4d8c2SCharles.Forsyth 	c = LCONST;
83774a4d8c2SCharles.Forsyth 	goto nret;
83874a4d8c2SCharles.Forsyth 
83974a4d8c2SCharles.Forsyth nret:
84074a4d8c2SCharles.Forsyth 	return c;
84174a4d8c2SCharles.Forsyth 
84274a4d8c2SCharles.Forsyth casedot:
84374a4d8c2SCharles.Forsyth 	for(;;) {
84474a4d8c2SCharles.Forsyth 		*cp++ = c;
84574a4d8c2SCharles.Forsyth 		c = GETC();
84674a4d8c2SCharles.Forsyth 		if(!isdigit(c))
84774a4d8c2SCharles.Forsyth 			break;
84874a4d8c2SCharles.Forsyth 	}
84974a4d8c2SCharles.Forsyth 	if(c != 'e' && c != 'E')
85074a4d8c2SCharles.Forsyth 		goto caseout;
85174a4d8c2SCharles.Forsyth 
85274a4d8c2SCharles.Forsyth casee:
85374a4d8c2SCharles.Forsyth 	*cp++ = 'e';
85474a4d8c2SCharles.Forsyth 	c = GETC();
85574a4d8c2SCharles.Forsyth 	if(c == '+' || c == '-') {
85674a4d8c2SCharles.Forsyth 		*cp++ = c;
85774a4d8c2SCharles.Forsyth 		c = GETC();
85874a4d8c2SCharles.Forsyth 	}
85974a4d8c2SCharles.Forsyth 	if(!isdigit(c))
86074a4d8c2SCharles.Forsyth 		yyerror("malformed fp constant exponent");
86174a4d8c2SCharles.Forsyth 	while(isdigit(c)) {
86274a4d8c2SCharles.Forsyth 		*cp++ = c;
86374a4d8c2SCharles.Forsyth 		c = GETC();
86474a4d8c2SCharles.Forsyth 	}
86574a4d8c2SCharles.Forsyth 
86674a4d8c2SCharles.Forsyth caseout:
86774a4d8c2SCharles.Forsyth 	if(c == 'L' || c == 'l') {
86874a4d8c2SCharles.Forsyth 		c = GETC();
86974a4d8c2SCharles.Forsyth 		c1 |= Numlong;
87074a4d8c2SCharles.Forsyth 	} else
87174a4d8c2SCharles.Forsyth 	if(c == 'F' || c == 'f') {
87274a4d8c2SCharles.Forsyth 		c = GETC();
87374a4d8c2SCharles.Forsyth 		c1 |= Numflt;
87474a4d8c2SCharles.Forsyth 	}
87574a4d8c2SCharles.Forsyth 	*cp = 0;
87674a4d8c2SCharles.Forsyth 	peekc = c;
87774a4d8c2SCharles.Forsyth 	if(mpatof(symb, &yylval.dval)) {
87874a4d8c2SCharles.Forsyth 		yyerror("overflow in float constant");
87974a4d8c2SCharles.Forsyth 		yylval.dval = 0;
88074a4d8c2SCharles.Forsyth 	}
88174a4d8c2SCharles.Forsyth 	if(c1 & Numflt)
88274a4d8c2SCharles.Forsyth 		return LFCONST;
88374a4d8c2SCharles.Forsyth 	return LDCONST;
88474a4d8c2SCharles.Forsyth }
88574a4d8c2SCharles.Forsyth 
88674a4d8c2SCharles.Forsyth int
getc(void)88774a4d8c2SCharles.Forsyth getc(void)
88874a4d8c2SCharles.Forsyth {
88974a4d8c2SCharles.Forsyth 	int c;
89074a4d8c2SCharles.Forsyth 
89174a4d8c2SCharles.Forsyth 	if(peekc != IGN) {
89274a4d8c2SCharles.Forsyth 		c = peekc;
89374a4d8c2SCharles.Forsyth 		peekc = IGN;
89474a4d8c2SCharles.Forsyth 	} else
89574a4d8c2SCharles.Forsyth 		c = GETC();
89674a4d8c2SCharles.Forsyth 	if(c == '\n')
89774a4d8c2SCharles.Forsyth 		lineno++;
89874a4d8c2SCharles.Forsyth 	if(c == EOF) {
89974a4d8c2SCharles.Forsyth 		yyerror("End of file");
90074a4d8c2SCharles.Forsyth 		errorexit();
90174a4d8c2SCharles.Forsyth 	}
90274a4d8c2SCharles.Forsyth 	return c;
90374a4d8c2SCharles.Forsyth }
90474a4d8c2SCharles.Forsyth 
90574a4d8c2SCharles.Forsyth long
getr(void)90674a4d8c2SCharles.Forsyth getr(void)
90774a4d8c2SCharles.Forsyth {
90874a4d8c2SCharles.Forsyth 	int c, i;
90974a4d8c2SCharles.Forsyth 	char str[UTFmax+1];
91074a4d8c2SCharles.Forsyth 	Rune rune;
91174a4d8c2SCharles.Forsyth 
91274a4d8c2SCharles.Forsyth 
91374a4d8c2SCharles.Forsyth 	c = getc();
91474a4d8c2SCharles.Forsyth 	if(c < Runeself)
91574a4d8c2SCharles.Forsyth 		return c;
91674a4d8c2SCharles.Forsyth 	i = 0;
91774a4d8c2SCharles.Forsyth 	str[i++] = c;
91874a4d8c2SCharles.Forsyth 
91974a4d8c2SCharles.Forsyth loop:
92074a4d8c2SCharles.Forsyth 	c = getc();
92174a4d8c2SCharles.Forsyth 	str[i++] = c;
92274a4d8c2SCharles.Forsyth 	if(!fullrune(str, i))
92374a4d8c2SCharles.Forsyth 		goto loop;
92474a4d8c2SCharles.Forsyth 	c = chartorune(&rune, str);
92574a4d8c2SCharles.Forsyth 	if(rune == Runeerror && c == 1) {
92674a4d8c2SCharles.Forsyth 		/* nearln = lineno; */
92774a4d8c2SCharles.Forsyth 		diag(Z, "illegal rune in string");
92874a4d8c2SCharles.Forsyth 		for(c=0; c<i; c++)
92974a4d8c2SCharles.Forsyth 			print(" %.2x", *(uchar*)(str+c));
93074a4d8c2SCharles.Forsyth 		print("\n");
93174a4d8c2SCharles.Forsyth 	}
93274a4d8c2SCharles.Forsyth 	return rune;
93374a4d8c2SCharles.Forsyth }
93474a4d8c2SCharles.Forsyth 
93574a4d8c2SCharles.Forsyth int
getnsc(void)93674a4d8c2SCharles.Forsyth getnsc(void)
93774a4d8c2SCharles.Forsyth {
93874a4d8c2SCharles.Forsyth 	int c;
93974a4d8c2SCharles.Forsyth 
94074a4d8c2SCharles.Forsyth 	if(peekc != IGN) {
94174a4d8c2SCharles.Forsyth 		c = peekc;
94274a4d8c2SCharles.Forsyth 		peekc = IGN;
94374a4d8c2SCharles.Forsyth 	} else
94474a4d8c2SCharles.Forsyth 		c = GETC();
94574a4d8c2SCharles.Forsyth 	for(;;) {
94674a4d8c2SCharles.Forsyth 		if(!isspace(c))
94774a4d8c2SCharles.Forsyth 			return c;
94874a4d8c2SCharles.Forsyth 		if(c == '\n') {
94974a4d8c2SCharles.Forsyth 			lineno++;
95074a4d8c2SCharles.Forsyth 			return c;
95174a4d8c2SCharles.Forsyth 		}
95274a4d8c2SCharles.Forsyth 		c = GETC();
95374a4d8c2SCharles.Forsyth 	}
954d67b7dadSforsyth 	/* not reached */
95574a4d8c2SCharles.Forsyth }
95674a4d8c2SCharles.Forsyth 
95774a4d8c2SCharles.Forsyth void
unget(int c)95874a4d8c2SCharles.Forsyth unget(int c)
95974a4d8c2SCharles.Forsyth {
96074a4d8c2SCharles.Forsyth 
96174a4d8c2SCharles.Forsyth 	peekc = c;
96274a4d8c2SCharles.Forsyth 	if(c == '\n')
96374a4d8c2SCharles.Forsyth 		lineno--;
96474a4d8c2SCharles.Forsyth }
96574a4d8c2SCharles.Forsyth 
96674a4d8c2SCharles.Forsyth long
escchar(long e,int longflg,int escflg)96774a4d8c2SCharles.Forsyth escchar(long e, int longflg, int escflg)
96874a4d8c2SCharles.Forsyth {
96974a4d8c2SCharles.Forsyth 	long c, l;
97074a4d8c2SCharles.Forsyth 	int i;
97174a4d8c2SCharles.Forsyth 
97274a4d8c2SCharles.Forsyth loop:
97374a4d8c2SCharles.Forsyth 	c = getr();
97474a4d8c2SCharles.Forsyth 	if(c == '\n') {
97574a4d8c2SCharles.Forsyth 		yyerror("newline in string");
97674a4d8c2SCharles.Forsyth 		return EOF;
97774a4d8c2SCharles.Forsyth 	}
97874a4d8c2SCharles.Forsyth 	if(c != '\\') {
97974a4d8c2SCharles.Forsyth 		if(c == e)
98074a4d8c2SCharles.Forsyth 			c = EOF;
98174a4d8c2SCharles.Forsyth 		return c;
98274a4d8c2SCharles.Forsyth 	}
98374a4d8c2SCharles.Forsyth 	c = getr();
98474a4d8c2SCharles.Forsyth 	if(c == 'x') {
98574a4d8c2SCharles.Forsyth 		/*
98674a4d8c2SCharles.Forsyth 		 * note this is not ansi,
98774a4d8c2SCharles.Forsyth 		 * supposed to only accept 2 hex
98874a4d8c2SCharles.Forsyth 		 */
98974a4d8c2SCharles.Forsyth 		i = 2;
99074a4d8c2SCharles.Forsyth 		if(longflg)
99174a4d8c2SCharles.Forsyth 			i = 4;
99274a4d8c2SCharles.Forsyth 		l = 0;
99374a4d8c2SCharles.Forsyth 		for(; i>0; i--) {
99474a4d8c2SCharles.Forsyth 			c = getc();
99574a4d8c2SCharles.Forsyth 			if(c >= '0' && c <= '9') {
99674a4d8c2SCharles.Forsyth 				l = l*16 + c-'0';
99774a4d8c2SCharles.Forsyth 				continue;
99874a4d8c2SCharles.Forsyth 			}
99974a4d8c2SCharles.Forsyth 			if(c >= 'a' && c <= 'f') {
100074a4d8c2SCharles.Forsyth 				l = l*16 + c-'a' + 10;
100174a4d8c2SCharles.Forsyth 				continue;
100274a4d8c2SCharles.Forsyth 			}
100374a4d8c2SCharles.Forsyth 			if(c >= 'A' && c <= 'F') {
100474a4d8c2SCharles.Forsyth 				l = l*16 + c-'A' + 10;
100574a4d8c2SCharles.Forsyth 				continue;
100674a4d8c2SCharles.Forsyth 			}
100774a4d8c2SCharles.Forsyth 			unget(c);
100874a4d8c2SCharles.Forsyth 			break;
100974a4d8c2SCharles.Forsyth 		}
101074a4d8c2SCharles.Forsyth 		if(escflg)
101174a4d8c2SCharles.Forsyth 			l |= ESC;
101274a4d8c2SCharles.Forsyth 		return l;
101374a4d8c2SCharles.Forsyth 	}
101474a4d8c2SCharles.Forsyth 	if(c >= '0' && c <= '7') {
101574a4d8c2SCharles.Forsyth 		/*
101674a4d8c2SCharles.Forsyth 		 * note this is not ansi,
101774a4d8c2SCharles.Forsyth 		 * supposed to only accept 3 oct
101874a4d8c2SCharles.Forsyth 		 */
101974a4d8c2SCharles.Forsyth 		i = 2;
102074a4d8c2SCharles.Forsyth 		if(longflg)
102174a4d8c2SCharles.Forsyth 			i = 5;
102274a4d8c2SCharles.Forsyth 		l = c - '0';
102374a4d8c2SCharles.Forsyth 		for(; i>0; i--) {
102474a4d8c2SCharles.Forsyth 			c = getc();
102574a4d8c2SCharles.Forsyth 			if(c >= '0' && c <= '7') {
102674a4d8c2SCharles.Forsyth 				l = l*8 + c-'0';
102774a4d8c2SCharles.Forsyth 				continue;
102874a4d8c2SCharles.Forsyth 			}
102974a4d8c2SCharles.Forsyth 			unget(c);
103074a4d8c2SCharles.Forsyth 		}
103174a4d8c2SCharles.Forsyth 		if(escflg)
103274a4d8c2SCharles.Forsyth 			l |= ESC;
103374a4d8c2SCharles.Forsyth 		return l;
103474a4d8c2SCharles.Forsyth 	}
103574a4d8c2SCharles.Forsyth 	switch(c)
103674a4d8c2SCharles.Forsyth 	{
103774a4d8c2SCharles.Forsyth 	case '\n':	goto loop;
103874a4d8c2SCharles.Forsyth 	case 'n':	return '\n';
103974a4d8c2SCharles.Forsyth 	case 't':	return '\t';
104074a4d8c2SCharles.Forsyth 	case 'b':	return '\b';
104174a4d8c2SCharles.Forsyth 	case 'r':	return '\r';
104274a4d8c2SCharles.Forsyth 	case 'f':	return '\f';
104374a4d8c2SCharles.Forsyth 	case 'a':	return '\a';
104474a4d8c2SCharles.Forsyth 	case 'v':	return '\v';
104574a4d8c2SCharles.Forsyth 	}
104674a4d8c2SCharles.Forsyth 	return c;
104774a4d8c2SCharles.Forsyth }
104874a4d8c2SCharles.Forsyth 
104974a4d8c2SCharles.Forsyth struct
105074a4d8c2SCharles.Forsyth {
105174a4d8c2SCharles.Forsyth 	char	*name;
105274a4d8c2SCharles.Forsyth 	ushort	lexical;
105374a4d8c2SCharles.Forsyth 	ushort	type;
105474a4d8c2SCharles.Forsyth } itab[] =
105574a4d8c2SCharles.Forsyth {
105674a4d8c2SCharles.Forsyth 	"auto",		LAUTO,		0,
105774a4d8c2SCharles.Forsyth 	"break",	LBREAK,		0,
105874a4d8c2SCharles.Forsyth 	"case",		LCASE,		0,
105974a4d8c2SCharles.Forsyth 	"char",		LCHAR,		TCHAR,
106074a4d8c2SCharles.Forsyth 	"const",	LCONSTNT,	0,
106174a4d8c2SCharles.Forsyth 	"continue",	LCONTINUE,	0,
106274a4d8c2SCharles.Forsyth 	"default",	LDEFAULT,	0,
106374a4d8c2SCharles.Forsyth 	"do",		LDO,		0,
106474a4d8c2SCharles.Forsyth 	"double",	LDOUBLE,	TDOUBLE,
106574a4d8c2SCharles.Forsyth 	"else",		LELSE,		0,
106674a4d8c2SCharles.Forsyth 	"enum",		LENUM,		0,
106774a4d8c2SCharles.Forsyth 	"extern",	LEXTERN,	0,
106874a4d8c2SCharles.Forsyth 	"float",	LFLOAT,		TFLOAT,
106974a4d8c2SCharles.Forsyth 	"for",		LFOR,		0,
107074a4d8c2SCharles.Forsyth 	"goto",		LGOTO,		0,
107174a4d8c2SCharles.Forsyth 	"if",		LIF,		0,
107274a4d8c2SCharles.Forsyth 	"int",		LINT,		TINT,
107374a4d8c2SCharles.Forsyth 	"long",		LLONG,		TLONG,
107474a4d8c2SCharles.Forsyth 	"register",	LREGISTER,	0,
107574a4d8c2SCharles.Forsyth 	"return",	LRETURN,	0,
107674a4d8c2SCharles.Forsyth 	"SET",		LSET,		0,
107774a4d8c2SCharles.Forsyth 	"short",	LSHORT,		TSHORT,
107874a4d8c2SCharles.Forsyth 	"signed",	LSIGNED,	0,
107974a4d8c2SCharles.Forsyth 	"signof",	LSIGNOF,	0,
108074a4d8c2SCharles.Forsyth 	"sizeof",	LSIZEOF,	0,
108174a4d8c2SCharles.Forsyth 	"static",	LSTATIC,	0,
108274a4d8c2SCharles.Forsyth 	"struct",	LSTRUCT,	0,
108374a4d8c2SCharles.Forsyth 	"switch",	LSWITCH,	0,
108474a4d8c2SCharles.Forsyth 	"typedef",	LTYPEDEF,	0,
108574a4d8c2SCharles.Forsyth 	"union",	LUNION,		0,
108674a4d8c2SCharles.Forsyth 	"unsigned",	LUNSIGNED,	0,
108774a4d8c2SCharles.Forsyth 	"USED",		LUSED,		0,
108874a4d8c2SCharles.Forsyth 	"void",		LVOID,		TVOID,
108974a4d8c2SCharles.Forsyth 	"volatile",	LVOLATILE,	0,
109074a4d8c2SCharles.Forsyth 	"while",	LWHILE,		0,
109174a4d8c2SCharles.Forsyth 	"__int64",	LVLONG,	TVLONG,			/* for windows */
109274a4d8c2SCharles.Forsyth 	0
109374a4d8c2SCharles.Forsyth };
109474a4d8c2SCharles.Forsyth 
109574a4d8c2SCharles.Forsyth static char *litab[] =
109674a4d8c2SCharles.Forsyth {
109774a4d8c2SCharles.Forsyth 	"adt",
109874a4d8c2SCharles.Forsyth 	"alt",
109974a4d8c2SCharles.Forsyth 	"array",
110074a4d8c2SCharles.Forsyth 	"big",
110174a4d8c2SCharles.Forsyth 	"break",
110274a4d8c2SCharles.Forsyth 	"byte",
110374a4d8c2SCharles.Forsyth 	"case",
110474a4d8c2SCharles.Forsyth 	"chan",
110574a4d8c2SCharles.Forsyth 	"con",
110674a4d8c2SCharles.Forsyth 	"continue",
110774a4d8c2SCharles.Forsyth 	"cyclic",
110874a4d8c2SCharles.Forsyth 	"do",
110974a4d8c2SCharles.Forsyth 	"else",
111074a4d8c2SCharles.Forsyth 	"exit",
111174a4d8c2SCharles.Forsyth 	"fn",
111274a4d8c2SCharles.Forsyth 	"for",
111374a4d8c2SCharles.Forsyth 	"hd",
111474a4d8c2SCharles.Forsyth 	"if",
111574a4d8c2SCharles.Forsyth 	"implement",
111674a4d8c2SCharles.Forsyth 	"import",
111774a4d8c2SCharles.Forsyth 	"include",
111874a4d8c2SCharles.Forsyth 	"int",
111974a4d8c2SCharles.Forsyth 	"len",
112074a4d8c2SCharles.Forsyth 	"list",
112174a4d8c2SCharles.Forsyth 	"load",
112274a4d8c2SCharles.Forsyth 	"module",
112374a4d8c2SCharles.Forsyth 	"nil",
112474a4d8c2SCharles.Forsyth 	"of",
112574a4d8c2SCharles.Forsyth 	"or",
112674a4d8c2SCharles.Forsyth 	"pick",
112774a4d8c2SCharles.Forsyth 	"real",
112874a4d8c2SCharles.Forsyth 	"ref",
112974a4d8c2SCharles.Forsyth 	"return",
113074a4d8c2SCharles.Forsyth 	"self",
113174a4d8c2SCharles.Forsyth 	"spawn",
113274a4d8c2SCharles.Forsyth 	"string",
113374a4d8c2SCharles.Forsyth 	"tagof",
113474a4d8c2SCharles.Forsyth 	"tl",
113574a4d8c2SCharles.Forsyth 	"to",
113674a4d8c2SCharles.Forsyth 	"type",
113774a4d8c2SCharles.Forsyth 	"while",
113874a4d8c2SCharles.Forsyth 	0,
113974a4d8c2SCharles.Forsyth };
114074a4d8c2SCharles.Forsyth 
114174a4d8c2SCharles.Forsyth void
cinit(void)114274a4d8c2SCharles.Forsyth cinit(void)
114374a4d8c2SCharles.Forsyth {
114474a4d8c2SCharles.Forsyth 	Sym *s;
114574a4d8c2SCharles.Forsyth 	int i;
114674a4d8c2SCharles.Forsyth 	Type *t;
114774a4d8c2SCharles.Forsyth 
114874a4d8c2SCharles.Forsyth 	nerrors = 0;
114974a4d8c2SCharles.Forsyth 	lineno = 1;
115074a4d8c2SCharles.Forsyth 	iostack = I;
115174a4d8c2SCharles.Forsyth 	iofree = I;
115274a4d8c2SCharles.Forsyth 	peekc = IGN;
115374a4d8c2SCharles.Forsyth 	nhunk = 0;
115474a4d8c2SCharles.Forsyth 
115574a4d8c2SCharles.Forsyth 	types[TXXX] = T;
115674a4d8c2SCharles.Forsyth 	types[TCHAR] = typ(TCHAR, T);
115774a4d8c2SCharles.Forsyth 	types[TUCHAR] = typ(TUCHAR, T);
115874a4d8c2SCharles.Forsyth 	types[TSHORT] = typ(TSHORT, T);
115974a4d8c2SCharles.Forsyth 	types[TUSHORT] = typ(TUSHORT, T);
116074a4d8c2SCharles.Forsyth 	types[TINT] = typ(TINT, T);
116174a4d8c2SCharles.Forsyth 	types[TUINT] = typ(TUINT, T);
116274a4d8c2SCharles.Forsyth 	types[TLONG] = typ(TLONG, T);
116374a4d8c2SCharles.Forsyth 	types[TULONG] = typ(TULONG, T);
116474a4d8c2SCharles.Forsyth 	types[TVLONG] = typ(TVLONG, T);
116574a4d8c2SCharles.Forsyth 	types[TUVLONG] = typ(TUVLONG, T);
116674a4d8c2SCharles.Forsyth 	types[TFLOAT] = typ(TFLOAT, T);
116774a4d8c2SCharles.Forsyth 	types[TDOUBLE] = typ(TDOUBLE, T);
116874a4d8c2SCharles.Forsyth 	types[TVOID] = typ(TVOID, T);
116974a4d8c2SCharles.Forsyth 	types[TENUM] = typ(TENUM, T);
117074a4d8c2SCharles.Forsyth 	types[TFUNC] = typ(TFUNC, types[TINT]);
117174a4d8c2SCharles.Forsyth 	types[TIND] = typ(TIND, types[TVOID]);
117274a4d8c2SCharles.Forsyth 	stringtype = typ(TSTRING, T);
117374a4d8c2SCharles.Forsyth 	fdtype = typ(TSTRUCT, typ(TFD, T));
117474a4d8c2SCharles.Forsyth 	fdtype->width = 4;
117574a4d8c2SCharles.Forsyth 	pfdtype = typ(TIND, fdtype);
117674a4d8c2SCharles.Forsyth 
117774a4d8c2SCharles.Forsyth 	for(i=0; i<NHASH; i++)
117874a4d8c2SCharles.Forsyth 		hash[i] = S;
117974a4d8c2SCharles.Forsyth 	for(i=0; itab[i].name; i++) {
118074a4d8c2SCharles.Forsyth 		s = slookup(itab[i].name);
118174a4d8c2SCharles.Forsyth 		s->lexical = itab[i].lexical;
118274a4d8c2SCharles.Forsyth 		if(itab[i].type != 0)
118374a4d8c2SCharles.Forsyth 			s->type = types[itab[i].type];
118474a4d8c2SCharles.Forsyth 	}
118574a4d8c2SCharles.Forsyth 	for(i=0; litab[i]; i++){
118674a4d8c2SCharles.Forsyth 		s = slookup(litab[i]);
118774a4d8c2SCharles.Forsyth 		s->lkw = 1;
118874a4d8c2SCharles.Forsyth 	}
118974a4d8c2SCharles.Forsyth 	blockno = 0;
119074a4d8c2SCharles.Forsyth 	autobn = 0;
119174a4d8c2SCharles.Forsyth 	autoffset = 0;
119274a4d8c2SCharles.Forsyth 
119374a4d8c2SCharles.Forsyth 	t = typ(TARRAY, types[TCHAR]);
119474a4d8c2SCharles.Forsyth 	t->width = 0;
119574a4d8c2SCharles.Forsyth 	symstring = slookup(".string");
119674a4d8c2SCharles.Forsyth 	symstring->class = CSTATIC;
119774a4d8c2SCharles.Forsyth 	symstring->type = t;
119874a4d8c2SCharles.Forsyth 
119974a4d8c2SCharles.Forsyth 	t = typ(TARRAY, types[TCHAR]);
120074a4d8c2SCharles.Forsyth 	t->width = 0;
120174a4d8c2SCharles.Forsyth 
120274a4d8c2SCharles.Forsyth 	nodproto = new(OPROTO, Z, Z);
120374a4d8c2SCharles.Forsyth 	dclstack = D;
120474a4d8c2SCharles.Forsyth 
120574a4d8c2SCharles.Forsyth 	pathname = allocn(pathname, 0, 100);
120674a4d8c2SCharles.Forsyth 	if(mygetwd(pathname, 99) == 0) {
120774a4d8c2SCharles.Forsyth 		pathname = allocn(pathname, 100, 900);
120874a4d8c2SCharles.Forsyth 		if(mygetwd(pathname, 999) == 0)
1209*45a20ab7Sforsyth 			strcpy(pathname, "/?");
121074a4d8c2SCharles.Forsyth 	}
121174a4d8c2SCharles.Forsyth 
121274a4d8c2SCharles.Forsyth 	fmtinstall('f', gfltconv);
121374a4d8c2SCharles.Forsyth 	fmtinstall('F', gfltconv);
121474a4d8c2SCharles.Forsyth 	fmtinstall('g', gfltconv);
121574a4d8c2SCharles.Forsyth 	fmtinstall('G', gfltconv);
121674a4d8c2SCharles.Forsyth 	fmtinstall('e', gfltconv);
121774a4d8c2SCharles.Forsyth 	fmtinstall('E', gfltconv);
121874a4d8c2SCharles.Forsyth 
121974a4d8c2SCharles.Forsyth 	fmtinstall('O', Oconv);
122074a4d8c2SCharles.Forsyth 	fmtinstall('T', Tconv);
122174a4d8c2SCharles.Forsyth 	fmtinstall('F', FNconv);
122274a4d8c2SCharles.Forsyth 	fmtinstall('L', Lconv);
122374a4d8c2SCharles.Forsyth 	fmtinstall('Q', Qconv);
122474a4d8c2SCharles.Forsyth 	fmtinstall('|', VBconv);
122574a4d8c2SCharles.Forsyth }
122674a4d8c2SCharles.Forsyth 
122774a4d8c2SCharles.Forsyth int
filbuf(void)122874a4d8c2SCharles.Forsyth filbuf(void)
122974a4d8c2SCharles.Forsyth {
123074a4d8c2SCharles.Forsyth 	Io *i;
123174a4d8c2SCharles.Forsyth 
123274a4d8c2SCharles.Forsyth loop:
123374a4d8c2SCharles.Forsyth 	i = iostack;
123474a4d8c2SCharles.Forsyth 	if(i == I)
123574a4d8c2SCharles.Forsyth 		return EOF;
123674a4d8c2SCharles.Forsyth 	if(i->f < 0)
123774a4d8c2SCharles.Forsyth 		goto pop;
123874a4d8c2SCharles.Forsyth 	fi.c = read(i->f, i->b, BUFSIZ) - 1;
123974a4d8c2SCharles.Forsyth 	if(fi.c < 0) {
124074a4d8c2SCharles.Forsyth 		close(i->f);
124174a4d8c2SCharles.Forsyth 		linehist(0, 0);
124274a4d8c2SCharles.Forsyth 		goto pop;
124374a4d8c2SCharles.Forsyth 	}
124474a4d8c2SCharles.Forsyth 	fi.p = i->b + 1;
124574a4d8c2SCharles.Forsyth 	return i->b[0] & 0xff;
124674a4d8c2SCharles.Forsyth 
124774a4d8c2SCharles.Forsyth pop:
124874a4d8c2SCharles.Forsyth 	if(i->f >= 0)
124974a4d8c2SCharles.Forsyth 		outpop(lineno);
125074a4d8c2SCharles.Forsyth 	iostack = i->link;
125174a4d8c2SCharles.Forsyth 	i->link = iofree;
125274a4d8c2SCharles.Forsyth 	iofree = i;
125374a4d8c2SCharles.Forsyth 	i = iostack;
125474a4d8c2SCharles.Forsyth 	if(i == I)
125574a4d8c2SCharles.Forsyth 		return EOF;
125674a4d8c2SCharles.Forsyth 	fi.p = i->p;
125774a4d8c2SCharles.Forsyth 	fi.c = i->c;
125874a4d8c2SCharles.Forsyth 	if(--fi.c < 0)
125974a4d8c2SCharles.Forsyth 		goto loop;
126074a4d8c2SCharles.Forsyth 	return *fi.p++ & 0xff;
126174a4d8c2SCharles.Forsyth }
126274a4d8c2SCharles.Forsyth 
126374a4d8c2SCharles.Forsyth int
Oconv(Fmt * fp)126474a4d8c2SCharles.Forsyth Oconv(Fmt *fp)
126574a4d8c2SCharles.Forsyth {
126674a4d8c2SCharles.Forsyth 	int a;
126774a4d8c2SCharles.Forsyth 	char s[STRINGSZ];
126874a4d8c2SCharles.Forsyth 
126974a4d8c2SCharles.Forsyth 	a = va_arg(fp->args, int);
127074a4d8c2SCharles.Forsyth 	if(a < OXXX || a > OEND) {
127174a4d8c2SCharles.Forsyth 		sprint(s, "***badO %d***", a);
127274a4d8c2SCharles.Forsyth 		fmtstrcpy(fp, s);
127374a4d8c2SCharles.Forsyth 	} else
127474a4d8c2SCharles.Forsyth 		fmtstrcpy(fp, onames[a]);
127574a4d8c2SCharles.Forsyth 	return 0;
127674a4d8c2SCharles.Forsyth }
127774a4d8c2SCharles.Forsyth 
127874a4d8c2SCharles.Forsyth int
Lconv(Fmt * fp)127974a4d8c2SCharles.Forsyth Lconv(Fmt *fp)
128074a4d8c2SCharles.Forsyth {
128174a4d8c2SCharles.Forsyth 	char str[STRINGSZ], s[STRINGSZ];
128274a4d8c2SCharles.Forsyth 	Hist *h;
128374a4d8c2SCharles.Forsyth 	struct
128474a4d8c2SCharles.Forsyth 	{
128574a4d8c2SCharles.Forsyth 		Hist*	incl;	/* start of this include file */
128674a4d8c2SCharles.Forsyth 		long	idel;	/* delta line number to apply to include */
128774a4d8c2SCharles.Forsyth 		Hist*	line;	/* start of this #line directive */
128874a4d8c2SCharles.Forsyth 		long	ldel;	/* delta line number to apply to #line */
128974a4d8c2SCharles.Forsyth 	} a[HISTSZ];
129074a4d8c2SCharles.Forsyth 	long l, d;
129174a4d8c2SCharles.Forsyth 	int i, n;
129274a4d8c2SCharles.Forsyth 
129374a4d8c2SCharles.Forsyth 	l = va_arg(fp->args, long);
129474a4d8c2SCharles.Forsyth 	n = 0;
129574a4d8c2SCharles.Forsyth 	for(h = hist; h != H; h = h->link) {
129674a4d8c2SCharles.Forsyth 		if(l < h->line)
129774a4d8c2SCharles.Forsyth 			break;
129874a4d8c2SCharles.Forsyth 		if(h->name) {
129974a4d8c2SCharles.Forsyth 			if(h->offset != 0) {		/* #line directive, not #pragma */
130074a4d8c2SCharles.Forsyth 				if(n > 0 && n < HISTSZ && h->offset >= 0) {
130174a4d8c2SCharles.Forsyth 					a[n-1].line = h;
130274a4d8c2SCharles.Forsyth 					a[n-1].ldel = h->line - h->offset + 1;
130374a4d8c2SCharles.Forsyth 				}
130474a4d8c2SCharles.Forsyth 			} else {
130574a4d8c2SCharles.Forsyth 				if(n < HISTSZ) {	/* beginning of file */
130674a4d8c2SCharles.Forsyth 					a[n].incl = h;
130774a4d8c2SCharles.Forsyth 					a[n].idel = h->line;
130874a4d8c2SCharles.Forsyth 					a[n].line = 0;
130974a4d8c2SCharles.Forsyth 				}
131074a4d8c2SCharles.Forsyth 				n++;
131174a4d8c2SCharles.Forsyth 			}
131274a4d8c2SCharles.Forsyth 			continue;
131374a4d8c2SCharles.Forsyth 		}
131474a4d8c2SCharles.Forsyth 		n--;
131574a4d8c2SCharles.Forsyth 		if(n > 0 && n < HISTSZ) {
131674a4d8c2SCharles.Forsyth 			d = h->line - a[n].incl->line;
131774a4d8c2SCharles.Forsyth 			a[n-1].ldel += d;
131874a4d8c2SCharles.Forsyth 			a[n-1].idel += d;
131974a4d8c2SCharles.Forsyth 		}
132074a4d8c2SCharles.Forsyth 	}
132174a4d8c2SCharles.Forsyth 	if(n > HISTSZ)
132274a4d8c2SCharles.Forsyth 		n = HISTSZ;
132374a4d8c2SCharles.Forsyth 	str[0] = 0;
132474a4d8c2SCharles.Forsyth 	for(i=n-1; i>=0; i--) {
132574a4d8c2SCharles.Forsyth 		if(i != n-1) {
132674a4d8c2SCharles.Forsyth 			if(fp->flags & ~(FmtWidth|FmtPrec))	/* BUG ROB - was f3 */
132774a4d8c2SCharles.Forsyth 				break;
132874a4d8c2SCharles.Forsyth 			strcat(str, " ");
132974a4d8c2SCharles.Forsyth 		}
133074a4d8c2SCharles.Forsyth 		if(a[i].line)
133174a4d8c2SCharles.Forsyth 			snprint(s, STRINGSZ, "%s:%ld[%s:%ld]",
133274a4d8c2SCharles.Forsyth 				a[i].line->name, l-a[i].ldel+1,
133374a4d8c2SCharles.Forsyth 				a[i].incl->name, l-a[i].idel+1);
133474a4d8c2SCharles.Forsyth 		else
133574a4d8c2SCharles.Forsyth 			snprint(s, STRINGSZ, "%s:%ld",
133674a4d8c2SCharles.Forsyth 				a[i].incl->name, l-a[i].idel+1);
133774a4d8c2SCharles.Forsyth 		if(strlen(s)+strlen(str) >= STRINGSZ-10)
133874a4d8c2SCharles.Forsyth 			break;
133974a4d8c2SCharles.Forsyth 		strcat(str, s);
134074a4d8c2SCharles.Forsyth 		l = a[i].incl->line - 1;	/* now print out start of this file */
134174a4d8c2SCharles.Forsyth 	}
134274a4d8c2SCharles.Forsyth 	if(n == 0)
134374a4d8c2SCharles.Forsyth 		strcat(str, "<eof>");
134474a4d8c2SCharles.Forsyth 	fmtstrcpy(fp, str);
134574a4d8c2SCharles.Forsyth 	return 0;
134674a4d8c2SCharles.Forsyth }
134774a4d8c2SCharles.Forsyth 
134874a4d8c2SCharles.Forsyth int
Tconv(Fmt * fp)134974a4d8c2SCharles.Forsyth Tconv(Fmt *fp)
135074a4d8c2SCharles.Forsyth {
135174a4d8c2SCharles.Forsyth 	char str[STRINGSZ+20], s[STRINGSZ+20];
135274a4d8c2SCharles.Forsyth 	Type *t, *t1;
135374a4d8c2SCharles.Forsyth 	int et;
135474a4d8c2SCharles.Forsyth 	long n;
135574a4d8c2SCharles.Forsyth 
135674a4d8c2SCharles.Forsyth 	str[0] = 0;
135774a4d8c2SCharles.Forsyth 	for(t = va_arg(fp->args, Type*); t != T; t = t->link) {
135874a4d8c2SCharles.Forsyth 		et = t->etype;
135974a4d8c2SCharles.Forsyth 		if(str[0])
136074a4d8c2SCharles.Forsyth 			strcat(str, " ");
136174a4d8c2SCharles.Forsyth 		if(t->garb) {
136274a4d8c2SCharles.Forsyth 			sprint(s, "%s ", gnames[t->garb]);
136374a4d8c2SCharles.Forsyth 			if(strlen(str) + strlen(s) < STRINGSZ)
136474a4d8c2SCharles.Forsyth 				strcat(str, s);
136574a4d8c2SCharles.Forsyth 		}
136674a4d8c2SCharles.Forsyth 		sprint(s, "%s", tnames[et]);
136774a4d8c2SCharles.Forsyth 		if(strlen(str) + strlen(s) < STRINGSZ)
136874a4d8c2SCharles.Forsyth 			strcat(str, s);
136974a4d8c2SCharles.Forsyth 		if(et == TFUNC && (t1 = t->down)) {
137074a4d8c2SCharles.Forsyth 			sprint(s, "(%T", t1);
137174a4d8c2SCharles.Forsyth 			if(strlen(str) + strlen(s) < STRINGSZ)
137274a4d8c2SCharles.Forsyth 				strcat(str, s);
137374a4d8c2SCharles.Forsyth 			while(t1 = t1->down) {
137474a4d8c2SCharles.Forsyth 				sprint(s, ", %T", t1);
137574a4d8c2SCharles.Forsyth 				if(strlen(str) + strlen(s) < STRINGSZ)
137674a4d8c2SCharles.Forsyth 					strcat(str, s);
137774a4d8c2SCharles.Forsyth 			}
137874a4d8c2SCharles.Forsyth 			if(strlen(str) + strlen(s) < STRINGSZ)
137974a4d8c2SCharles.Forsyth 				strcat(str, ")");
138074a4d8c2SCharles.Forsyth 		}
138174a4d8c2SCharles.Forsyth 		if(et == TARRAY) {
138274a4d8c2SCharles.Forsyth 			n = t->width;
138374a4d8c2SCharles.Forsyth 			if(t->link && t->link->width)
138474a4d8c2SCharles.Forsyth 				n /= t->link->width;
138574a4d8c2SCharles.Forsyth 			sprint(s, "[%ld]", n);
138674a4d8c2SCharles.Forsyth 			if(strlen(str) + strlen(s) < STRINGSZ)
138774a4d8c2SCharles.Forsyth 				strcat(str, s);
138874a4d8c2SCharles.Forsyth 		}
138974a4d8c2SCharles.Forsyth 		if(t->nbits) {
139074a4d8c2SCharles.Forsyth 			sprint(s, " %d:%d", t->shift, t->nbits);
139174a4d8c2SCharles.Forsyth 			if(strlen(str) + strlen(s) < STRINGSZ)
139274a4d8c2SCharles.Forsyth 				strcat(str, s);
139374a4d8c2SCharles.Forsyth 		}
139474a4d8c2SCharles.Forsyth 		if(typesu[et]) {
139574a4d8c2SCharles.Forsyth 			if(t->tag) {
139674a4d8c2SCharles.Forsyth 				strcat(str, " ");
139774a4d8c2SCharles.Forsyth 				if(strlen(str) + strlen(t->tag->name) < STRINGSZ)
139874a4d8c2SCharles.Forsyth 					strcat(str, t->tag->name);
139974a4d8c2SCharles.Forsyth 			} else
140074a4d8c2SCharles.Forsyth 				strcat(str, " {}");
140174a4d8c2SCharles.Forsyth 			break;
140274a4d8c2SCharles.Forsyth 		}
140374a4d8c2SCharles.Forsyth 	}
140474a4d8c2SCharles.Forsyth 	fmtstrcpy(fp, str);
140574a4d8c2SCharles.Forsyth 	return 0;
140674a4d8c2SCharles.Forsyth }
140774a4d8c2SCharles.Forsyth 
140874a4d8c2SCharles.Forsyth int
FNconv(Fmt * fp)140974a4d8c2SCharles.Forsyth FNconv(Fmt *fp)
141074a4d8c2SCharles.Forsyth {
141174a4d8c2SCharles.Forsyth 	char *str;
141274a4d8c2SCharles.Forsyth 	Node *n;
141374a4d8c2SCharles.Forsyth 
141474a4d8c2SCharles.Forsyth 	n = va_arg(fp->args, Node*);
141574a4d8c2SCharles.Forsyth 	str = "<indirect>";
141674a4d8c2SCharles.Forsyth 	if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM))
141774a4d8c2SCharles.Forsyth 		str = n->sym->name;
141874a4d8c2SCharles.Forsyth 	fmtstrcpy(fp, str);
141974a4d8c2SCharles.Forsyth 	return 0;
142074a4d8c2SCharles.Forsyth }
142174a4d8c2SCharles.Forsyth 
142274a4d8c2SCharles.Forsyth int
Qconv(Fmt * fp)142374a4d8c2SCharles.Forsyth Qconv(Fmt *fp)
142474a4d8c2SCharles.Forsyth {
142574a4d8c2SCharles.Forsyth 	char str[STRINGSZ+20], *s;
142674a4d8c2SCharles.Forsyth 	long b;
142774a4d8c2SCharles.Forsyth 	int i;
142874a4d8c2SCharles.Forsyth 
142974a4d8c2SCharles.Forsyth 	str[0] = 0;
143074a4d8c2SCharles.Forsyth 	for(b = va_arg(fp->args, long); b;) {
143174a4d8c2SCharles.Forsyth 		i = bitno(b);
143274a4d8c2SCharles.Forsyth 		if(str[0])
143374a4d8c2SCharles.Forsyth 			strcat(str, " ");
143474a4d8c2SCharles.Forsyth 		s = qnames[i];
143574a4d8c2SCharles.Forsyth 		if(strlen(str) + strlen(s) >= STRINGSZ)
143674a4d8c2SCharles.Forsyth 			break;
143774a4d8c2SCharles.Forsyth 		strcat(str, s);
143874a4d8c2SCharles.Forsyth 		b &= ~(1L << i);
143974a4d8c2SCharles.Forsyth 	}
144074a4d8c2SCharles.Forsyth 	fmtstrcpy(fp, str);
144174a4d8c2SCharles.Forsyth 	return 0;
144274a4d8c2SCharles.Forsyth }
144374a4d8c2SCharles.Forsyth 
144474a4d8c2SCharles.Forsyth int
VBconv(Fmt * fp)144574a4d8c2SCharles.Forsyth VBconv(Fmt *fp)
144674a4d8c2SCharles.Forsyth {
144774a4d8c2SCharles.Forsyth 	char str[STRINGSZ];
144874a4d8c2SCharles.Forsyth 	int i, n, t, pc;
144974a4d8c2SCharles.Forsyth 
145074a4d8c2SCharles.Forsyth 	n = va_arg(fp->args, int);
145174a4d8c2SCharles.Forsyth 	pc = 0;	/*was printcol */
145274a4d8c2SCharles.Forsyth 	i = 0;
145374a4d8c2SCharles.Forsyth 	while(pc < n) {
145474a4d8c2SCharles.Forsyth 		t = (pc+8) & ~7;
145574a4d8c2SCharles.Forsyth 		if(t <= n) {
145674a4d8c2SCharles.Forsyth 			str[i++] = '\t';
145774a4d8c2SCharles.Forsyth 			pc = t;
145874a4d8c2SCharles.Forsyth 			continue;
145974a4d8c2SCharles.Forsyth 		}
146074a4d8c2SCharles.Forsyth 		str[i++] = ' ';
146174a4d8c2SCharles.Forsyth 		pc++;
146274a4d8c2SCharles.Forsyth 	}
146374a4d8c2SCharles.Forsyth 	str[i] = 0;
146474a4d8c2SCharles.Forsyth 	fmtstrcpy(fp, str);
146574a4d8c2SCharles.Forsyth 	return 0;
146674a4d8c2SCharles.Forsyth }
146774a4d8c2SCharles.Forsyth 
146874a4d8c2SCharles.Forsyth /*
146974a4d8c2SCharles.Forsyth  * real allocs
147074a4d8c2SCharles.Forsyth  */
147174a4d8c2SCharles.Forsyth void*
alloc(long n)147274a4d8c2SCharles.Forsyth alloc(long n)
147374a4d8c2SCharles.Forsyth {
147474a4d8c2SCharles.Forsyth 	void *p;
147574a4d8c2SCharles.Forsyth 
147674a4d8c2SCharles.Forsyth 	while((ulong)hunk & MAXALIGN) {
147774a4d8c2SCharles.Forsyth 		hunk++;
147874a4d8c2SCharles.Forsyth 		nhunk--;
147974a4d8c2SCharles.Forsyth 	}
148074a4d8c2SCharles.Forsyth 	while(nhunk < n)
148174a4d8c2SCharles.Forsyth 		gethunk();
148274a4d8c2SCharles.Forsyth 	p = hunk;
148374a4d8c2SCharles.Forsyth 	nhunk -= n;
148474a4d8c2SCharles.Forsyth 	hunk += n;
148574a4d8c2SCharles.Forsyth 	return p;
148674a4d8c2SCharles.Forsyth }
148774a4d8c2SCharles.Forsyth 
148874a4d8c2SCharles.Forsyth void*
allocn(void * p,long on,long n)148974a4d8c2SCharles.Forsyth allocn(void *p, long on, long n)
149074a4d8c2SCharles.Forsyth {
149174a4d8c2SCharles.Forsyth 	void *q;
149274a4d8c2SCharles.Forsyth 
149374a4d8c2SCharles.Forsyth 	q = (uchar*)p + on;
149474a4d8c2SCharles.Forsyth 	if(q != hunk || nhunk < n) {
149574a4d8c2SCharles.Forsyth 		while(nhunk < on+n)
149674a4d8c2SCharles.Forsyth 			gethunk();
149774a4d8c2SCharles.Forsyth 		memmove(hunk, p, on);
149874a4d8c2SCharles.Forsyth 		p = hunk;
149974a4d8c2SCharles.Forsyth 		hunk += on;
150074a4d8c2SCharles.Forsyth 		nhunk -= on;
150174a4d8c2SCharles.Forsyth 	}
150274a4d8c2SCharles.Forsyth 	hunk += n;
150374a4d8c2SCharles.Forsyth 	nhunk -= n;
150474a4d8c2SCharles.Forsyth 	return p;
150574a4d8c2SCharles.Forsyth }
150674a4d8c2SCharles.Forsyth 
150774a4d8c2SCharles.Forsyth void
setinclude(char * p)150874a4d8c2SCharles.Forsyth setinclude(char *p)
150974a4d8c2SCharles.Forsyth {
151074a4d8c2SCharles.Forsyth 	int i;
151174a4d8c2SCharles.Forsyth 	char *e;
151274a4d8c2SCharles.Forsyth 
151374a4d8c2SCharles.Forsyth 	while(*p != 0) {
151474a4d8c2SCharles.Forsyth 		e = strchr(p, ' ');
151574a4d8c2SCharles.Forsyth 		if(e != 0)
151674a4d8c2SCharles.Forsyth 			*e = '\0';
151774a4d8c2SCharles.Forsyth 
151874a4d8c2SCharles.Forsyth 		for(i=1; i < ninclude; i++)
151974a4d8c2SCharles.Forsyth 			if(strcmp(p, include[i]) == 0)
152074a4d8c2SCharles.Forsyth 				break;
152174a4d8c2SCharles.Forsyth 
152274a4d8c2SCharles.Forsyth 		if(i >= ninclude)
152374a4d8c2SCharles.Forsyth 			include[ninclude++] = p;
152474a4d8c2SCharles.Forsyth 
152574a4d8c2SCharles.Forsyth 		if(ninclude > nelem(include)) {
152674a4d8c2SCharles.Forsyth 			diag(Z, "ninclude too small %d", nelem(include));
152774a4d8c2SCharles.Forsyth 			exits("ninclude");
152874a4d8c2SCharles.Forsyth 		}
152974a4d8c2SCharles.Forsyth 
153074a4d8c2SCharles.Forsyth 		if(e == 0)
153174a4d8c2SCharles.Forsyth 			break;
153274a4d8c2SCharles.Forsyth 		p = e+1;
153374a4d8c2SCharles.Forsyth 	}
153474a4d8c2SCharles.Forsyth }
153574a4d8c2SCharles.Forsyth 
153674a4d8c2SCharles.Forsyth static void
doio(char * s)153774a4d8c2SCharles.Forsyth doio(char *s)
153874a4d8c2SCharles.Forsyth {
153974a4d8c2SCharles.Forsyth 	char *cp;
154074a4d8c2SCharles.Forsyth 
154174a4d8c2SCharles.Forsyth 	newio();
154274a4d8c2SCharles.Forsyth 	cp = ionext->b;
154374a4d8c2SCharles.Forsyth 	strcpy(cp, s);
154474a4d8c2SCharles.Forsyth 	pushio();
154574a4d8c2SCharles.Forsyth 	ionext->link = iostack;
154674a4d8c2SCharles.Forsyth 	iostack = ionext;
154774a4d8c2SCharles.Forsyth 	fi.p = cp;
154874a4d8c2SCharles.Forsyth 	fi.c = strlen(cp);
154974a4d8c2SCharles.Forsyth 	if(peekc != IGN) {
155074a4d8c2SCharles.Forsyth 		cp[fi.c++] = peekc;
155174a4d8c2SCharles.Forsyth 		cp[fi.c] = 0;
155274a4d8c2SCharles.Forsyth 		peekc = IGN;
155374a4d8c2SCharles.Forsyth 	}
155474a4d8c2SCharles.Forsyth }
155574a4d8c2SCharles.Forsyth 
155674a4d8c2SCharles.Forsyth static void
undoio(void)155774a4d8c2SCharles.Forsyth undoio(void)
155874a4d8c2SCharles.Forsyth {
155974a4d8c2SCharles.Forsyth 	Io *i;
156074a4d8c2SCharles.Forsyth 
156174a4d8c2SCharles.Forsyth 	i = iostack;
156274a4d8c2SCharles.Forsyth 	iostack = i->link;
156374a4d8c2SCharles.Forsyth 	i->link = iofree;
156474a4d8c2SCharles.Forsyth 	iofree = i;
156574a4d8c2SCharles.Forsyth 	i = iostack;
156674a4d8c2SCharles.Forsyth 	fi.p = i->p;
156774a4d8c2SCharles.Forsyth 	fi.c = i->c;
156874a4d8c2SCharles.Forsyth }
156974a4d8c2SCharles.Forsyth 
157074a4d8c2SCharles.Forsyth /* rm // comment from a string */
157174a4d8c2SCharles.Forsyth static void
slashslash(char * s)157274a4d8c2SCharles.Forsyth slashslash(char *s)
157374a4d8c2SCharles.Forsyth {
157474a4d8c2SCharles.Forsyth 	for( ; *s != '\0'; s++)
157574a4d8c2SCharles.Forsyth 		if(*s == '/' && s[1] == '/'){
157674a4d8c2SCharles.Forsyth 			*s = '\0';
157774a4d8c2SCharles.Forsyth 			return;
157874a4d8c2SCharles.Forsyth 		}
157974a4d8c2SCharles.Forsyth }
158074a4d8c2SCharles.Forsyth 
158174a4d8c2SCharles.Forsyth int
iscon(char * str)158274a4d8c2SCharles.Forsyth iscon(char *str)
158374a4d8c2SCharles.Forsyth {
158474a4d8c2SCharles.Forsyth 	int olineno, opeekc, con, tok, t;
158574a4d8c2SCharles.Forsyth 	Sym *s;
158674a4d8c2SCharles.Forsyth 	char buf[1024];
158774a4d8c2SCharles.Forsyth 
158874a4d8c2SCharles.Forsyth 	if(str == nil || *str == 0 || strlen(str)+16 > 1024)
158974a4d8c2SCharles.Forsyth 		return 0;
159074a4d8c2SCharles.Forsyth 	ypeek = 1;
159174a4d8c2SCharles.Forsyth 	olineno = lineno;
159274a4d8c2SCharles.Forsyth 	opeekc = peekc;
159374a4d8c2SCharles.Forsyth 	peekc = IGN;
159474a4d8c2SCharles.Forsyth 	strcpy(buf, str);
159574a4d8c2SCharles.Forsyth 	slashslash(buf);
159674a4d8c2SCharles.Forsyth 	strcat(buf, " break break");
159774a4d8c2SCharles.Forsyth 	doio(buf);
159874a4d8c2SCharles.Forsyth 	tok = 0;
159974a4d8c2SCharles.Forsyth 	con = 1;
160074a4d8c2SCharles.Forsyth 	while(con){
160174a4d8c2SCharles.Forsyth 		t = yylex();
160274a4d8c2SCharles.Forsyth 		if(t == LBREAK)
160374a4d8c2SCharles.Forsyth 			break;
160474a4d8c2SCharles.Forsyth 		switch(t){
160574a4d8c2SCharles.Forsyth 			case LSTRING:
160674a4d8c2SCharles.Forsyth 			case LLSTRING:
160774a4d8c2SCharles.Forsyth 				tok = 1;
160874a4d8c2SCharles.Forsyth 				free(yylval.sval.s);
160974a4d8c2SCharles.Forsyth 				break;
161074a4d8c2SCharles.Forsyth 			case LNAME:
161174a4d8c2SCharles.Forsyth 				tok = 1;
161274a4d8c2SCharles.Forsyth 				s = yylval.sym;
161374a4d8c2SCharles.Forsyth 				if(s->macro || s->type == T || s->type->etype != TENUM)
161474a4d8c2SCharles.Forsyth 					con = 0;
161574a4d8c2SCharles.Forsyth 				break;
161674a4d8c2SCharles.Forsyth 			case LCHARACTER:
161774a4d8c2SCharles.Forsyth 			case LCONST:
161874a4d8c2SCharles.Forsyth 			case LLCONST:
161974a4d8c2SCharles.Forsyth 			case LUCONST:
162074a4d8c2SCharles.Forsyth 			case LULCONST:
162174a4d8c2SCharles.Forsyth 			case LVLCONST:
162274a4d8c2SCharles.Forsyth 			case LUVLCONST:
162374a4d8c2SCharles.Forsyth 			case LFCONST:
162474a4d8c2SCharles.Forsyth 			case LDCONST:
162574a4d8c2SCharles.Forsyth 				tok = 1;
162674a4d8c2SCharles.Forsyth 				break;
162774a4d8c2SCharles.Forsyth 			case '+':
162874a4d8c2SCharles.Forsyth 			case '-':
162974a4d8c2SCharles.Forsyth 			case '*':
163074a4d8c2SCharles.Forsyth 			case '/':
163174a4d8c2SCharles.Forsyth 			case '%':
163274a4d8c2SCharles.Forsyth 			case LPP:
163374a4d8c2SCharles.Forsyth 			case LMM:
163474a4d8c2SCharles.Forsyth 			case '<':
163574a4d8c2SCharles.Forsyth 			case '>':
163674a4d8c2SCharles.Forsyth 			case LGE:
163774a4d8c2SCharles.Forsyth 			case LLE:
163874a4d8c2SCharles.Forsyth 			case LEQ:
163974a4d8c2SCharles.Forsyth 			case LNE:
164074a4d8c2SCharles.Forsyth 			case LLSH:
164174a4d8c2SCharles.Forsyth 			case LRSH:
164274a4d8c2SCharles.Forsyth 			case '!':
164374a4d8c2SCharles.Forsyth 			case '~':
164474a4d8c2SCharles.Forsyth 			case '&':
164574a4d8c2SCharles.Forsyth 			case '|':
164674a4d8c2SCharles.Forsyth 			case '^':
164774a4d8c2SCharles.Forsyth 			case '(':
164874a4d8c2SCharles.Forsyth 			case ')':
164974a4d8c2SCharles.Forsyth 				break;
165074a4d8c2SCharles.Forsyth 			default:
165174a4d8c2SCharles.Forsyth 				con = 0;
165274a4d8c2SCharles.Forsyth 				break;
165374a4d8c2SCharles.Forsyth 		}
165474a4d8c2SCharles.Forsyth 	}
165574a4d8c2SCharles.Forsyth 	undoio();
165674a4d8c2SCharles.Forsyth 	peekc = opeekc;
165774a4d8c2SCharles.Forsyth 	lineno = olineno;
165874a4d8c2SCharles.Forsyth 	ypeek = 0;
165974a4d8c2SCharles.Forsyth 	return con && tok;
166074a4d8c2SCharles.Forsyth }
166174a4d8c2SCharles.Forsyth 
166274a4d8c2SCharles.Forsyth void
doasenum(Sym * s)166374a4d8c2SCharles.Forsyth doasenum(Sym *s)
166474a4d8c2SCharles.Forsyth {
166574a4d8c2SCharles.Forsyth 	char *b, buf[1024];
166674a4d8c2SCharles.Forsyth 
166774a4d8c2SCharles.Forsyth 	b = s->macro;
166874a4d8c2SCharles.Forsyth 	s->macro = nil;
166974a4d8c2SCharles.Forsyth 	lineno--;
167074a4d8c2SCharles.Forsyth 	slashslash(b+1);
167174a4d8c2SCharles.Forsyth 	sprint(buf, "enum{ %s = %s };\n", s->name, b+1);
167274a4d8c2SCharles.Forsyth 	doio(buf);
167374a4d8c2SCharles.Forsyth 	/* outpush(nil); */
167474a4d8c2SCharles.Forsyth 	free(b);
167574a4d8c2SCharles.Forsyth }
1676