xref: /plan9/sys/src/cmd/cc/lex.c (revision 6bbfed0d85c6d7248503ef0614d0f1e40438b735)
13e12c5d1SDavid du Colombier #include	"cc.h"
23e12c5d1SDavid du Colombier #include	"y.tab.h"
33e12c5d1SDavid du Colombier 
47dd7cddfSDavid du Colombier #ifndef	CPP
57dd7cddfSDavid du Colombier #define	CPP	"/bin/cpp"
67dd7cddfSDavid du Colombier #endif
77dd7cddfSDavid du Colombier 
83e12c5d1SDavid du Colombier /*
93e12c5d1SDavid du Colombier  * known debug flags
10219b2ee8SDavid du Colombier  *	-a		acid declaration output
11219b2ee8SDavid du Colombier  *	-A		!B
1291178603SDavid du Colombier  *	-B		non ANSI
13219b2ee8SDavid du Colombier  *	-d		print declarations
1491178603SDavid du Colombier  *	-D name		define
157dd7cddfSDavid du Colombier  *	-F		format specification check
1691178603SDavid du Colombier  *	-i		print initialization
1791178603SDavid du Colombier  *	-I path		include
1891178603SDavid du Colombier  *	-l		generate little-endian code
1991178603SDavid du Colombier  *	-L		print every NAME symbol
2091178603SDavid du Colombier  *	-M		constant multiplication
21219b2ee8SDavid du Colombier  *	-m		print add/sub/mul trees
227dd7cddfSDavid du Colombier  *	-n		print acid to file (%.c=%.acid) (with -a or -aa)
2391178603SDavid du Colombier  *	-o file		output file
247dd7cddfSDavid du Colombier  *	-p		use standard cpp ANSI preprocessor (not on windows)
2591178603SDavid du Colombier  *	-r		print registerization
2691178603SDavid du Colombier  *	-s		print structure offsets (with -a or -aa)
27eed6406fSDavid du Colombier  *	-S		print assembly
2891178603SDavid du Colombier  *	-t		print type trees
297dd7cddfSDavid du Colombier  *	-V		enable void* conversion warnings
3091178603SDavid du Colombier  *	-v		verbose printing
3191178603SDavid du Colombier  *	-w		print warnings
3291178603SDavid du Colombier  *	-X		abort on error
338deabd96SDavid du Colombier  *	-.		Inhibit search for includes in source directory
343e12c5d1SDavid du Colombier  */
353e12c5d1SDavid du Colombier 
363e12c5d1SDavid du Colombier void
main(int argc,char * argv[])373e12c5d1SDavid du Colombier main(int argc, char *argv[])
383e12c5d1SDavid du Colombier {
39*6bbfed0dSDavid du Colombier 	char **defs, **np, *p;
40*6bbfed0dSDavid du Colombier 	int nproc, nout, status, i, c, ndef, maxdef;
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 	memset(debug, 0, sizeof(debug));
437dd7cddfSDavid du Colombier 	tinit();
443e12c5d1SDavid du Colombier 	cinit();
453e12c5d1SDavid du Colombier 	ginit();
467dd7cddfSDavid du Colombier 	arginit();
473e12c5d1SDavid du Colombier 
48e288d156SDavid du Colombier 	profileflg = 1;	/* #pragma can turn it off */
497dd7cddfSDavid du Colombier 	tufield = simplet((1L<<tfield->etype) | BUNSIGNED);
50*6bbfed0dSDavid du Colombier 	maxdef = 0;
517dd7cddfSDavid du Colombier 	ndef = 0;
523e12c5d1SDavid du Colombier 	outfile = 0;
53*6bbfed0dSDavid du Colombier 	defs = nil;
54*6bbfed0dSDavid du Colombier 	setinclude(".");
553e12c5d1SDavid du Colombier 	ARGBEGIN {
563e12c5d1SDavid du Colombier 	default:
573e12c5d1SDavid du Colombier 		c = ARGC();
583e12c5d1SDavid du Colombier 		if(c >= 0 && c < sizeof(debug))
593e12c5d1SDavid du Colombier 			debug[c]++;
603e12c5d1SDavid du Colombier 		break;
613e12c5d1SDavid du Colombier 
6291178603SDavid du Colombier 	case 'l':			/* for little-endian mips */
6391178603SDavid du Colombier 		if(thechar != 'v'){
6491178603SDavid du Colombier 			print("can only use -l with vc");
6591178603SDavid du Colombier 			errorexit();
6691178603SDavid du Colombier 		}
6791178603SDavid du Colombier 		thechar = '0';
6891178603SDavid du Colombier 		thestring = "spim";
6991178603SDavid du Colombier 		break;
7091178603SDavid du Colombier 
713e12c5d1SDavid du Colombier 	case 'o':
723e12c5d1SDavid du Colombier 		outfile = ARGF();
733e12c5d1SDavid du Colombier 		break;
743e12c5d1SDavid du Colombier 
753e12c5d1SDavid du Colombier 	case 'D':
763e12c5d1SDavid du Colombier 		p = ARGF();
777dd7cddfSDavid du Colombier 		if(p) {
78*6bbfed0dSDavid du Colombier 			if(ndef >= maxdef){
79*6bbfed0dSDavid du Colombier 				maxdef += 50;
80*6bbfed0dSDavid du Colombier 				np = alloc(maxdef * sizeof *np);
81*6bbfed0dSDavid du Colombier 				if(defs != nil)
82*6bbfed0dSDavid du Colombier 					memmove(np, defs, (maxdef - 50) * sizeof *np);
83*6bbfed0dSDavid du Colombier 				defs = np;
84*6bbfed0dSDavid du Colombier 			}
857dd7cddfSDavid du Colombier 			defs[ndef++] = p;
863e12c5d1SDavid du Colombier 			dodefine(p);
877dd7cddfSDavid du Colombier 		}
883e12c5d1SDavid du Colombier 		break;
893e12c5d1SDavid du Colombier 
903e12c5d1SDavid du Colombier 	case 'I':
913e12c5d1SDavid du Colombier 		p = ARGF();
9282726826SDavid du Colombier 		if(p)
937dd7cddfSDavid du Colombier 			setinclude(p);
943e12c5d1SDavid du Colombier 		break;
953e12c5d1SDavid du Colombier 	} ARGEND
963e12c5d1SDavid du Colombier 	if(argc < 1 && outfile == 0) {
973e12c5d1SDavid du Colombier 		print("usage: %cc [-options] files\n", thechar);
983e12c5d1SDavid du Colombier 		errorexit();
993e12c5d1SDavid du Colombier 	}
1007dd7cddfSDavid du Colombier 	if(argc > 1 && systemtype(Windows)){
1017dd7cddfSDavid du Colombier 		print("can't compile multiple files on windows\n");
1027dd7cddfSDavid du Colombier 		errorexit();
1037dd7cddfSDavid du Colombier 	}
1047dd7cddfSDavid du Colombier 	if(argc > 1 && !systemtype(Windows)) {
1053e12c5d1SDavid du Colombier 		nproc = 1;
106aedc1c01SDavid du Colombier 		/*
107aedc1c01SDavid du Colombier 		 * if we're writing acid to standard output, don't compile
108aedc1c01SDavid du Colombier 		 * concurrently, to avoid interleaving output.
109aedc1c01SDavid du Colombier 		 */
110aedc1c01SDavid du Colombier 		if(((!debug['a'] && !debug['Z']) || debug['n']) &&
111aedc1c01SDavid du Colombier 		    (p = getenv("NPROC")) != nil)
1123e12c5d1SDavid du Colombier 			nproc = atol(p);	/* */
1133e12c5d1SDavid du Colombier 		c = 0;
1143e12c5d1SDavid du Colombier 		nout = 0;
1153e12c5d1SDavid du Colombier 		for(;;) {
1163e12c5d1SDavid du Colombier 			while(nout < nproc && argc > 0) {
1177dd7cddfSDavid du Colombier 				i = myfork();
1183e12c5d1SDavid du Colombier 				if(i < 0) {
1193e12c5d1SDavid du Colombier 					i = mywait(&status);
1203e12c5d1SDavid du Colombier 					if(i < 0) {
1213e12c5d1SDavid du Colombier 						print("cannot create a process\n");
1223e12c5d1SDavid du Colombier 						errorexit();
1233e12c5d1SDavid du Colombier 					}
1243e12c5d1SDavid du Colombier 					if(status)
1253e12c5d1SDavid du Colombier 						c++;
1263e12c5d1SDavid du Colombier 					nout--;
1273e12c5d1SDavid du Colombier 					continue;
1283e12c5d1SDavid du Colombier 				}
129219b2ee8SDavid du Colombier 				if(i == 0) {
1307dd7cddfSDavid du Colombier 					fprint(2, "%s:\n", *argv);
1317dd7cddfSDavid du Colombier 					if (compile(*argv, defs, ndef))
1327dd7cddfSDavid du Colombier 						errorexit();
1337dd7cddfSDavid du Colombier 					exits(0);
134219b2ee8SDavid du Colombier 				}
1353e12c5d1SDavid du Colombier 				nout++;
1363e12c5d1SDavid du Colombier 				argc--;
1373e12c5d1SDavid du Colombier 				argv++;
1383e12c5d1SDavid du Colombier 			}
1393e12c5d1SDavid du Colombier 			i = mywait(&status);
1403e12c5d1SDavid du Colombier 			if(i < 0) {
1413e12c5d1SDavid du Colombier 				if(c)
1423e12c5d1SDavid du Colombier 					errorexit();
1433e12c5d1SDavid du Colombier 				exits(0);
1443e12c5d1SDavid du Colombier 			}
1453e12c5d1SDavid du Colombier 			if(status)
1463e12c5d1SDavid du Colombier 				c++;
1473e12c5d1SDavid du Colombier 			nout--;
1483e12c5d1SDavid du Colombier 		}
1493e12c5d1SDavid du Colombier 	}
1503e12c5d1SDavid du Colombier 
1517dd7cddfSDavid du Colombier 	if(argc == 0)
1527dd7cddfSDavid du Colombier 		c = compile("stdin", defs, ndef);
1533e12c5d1SDavid du Colombier 	else
1547dd7cddfSDavid du Colombier 		c = compile(argv[0], defs, ndef);
1557dd7cddfSDavid du Colombier 
1567dd7cddfSDavid du Colombier 	if(c)
1577dd7cddfSDavid du Colombier 		errorexit();
1587dd7cddfSDavid du Colombier 	exits(0);
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier 
1617dd7cddfSDavid du Colombier int
compile(char * file,char ** defs,int ndef)1627dd7cddfSDavid du Colombier compile(char *file, char **defs, int ndef)
1637dd7cddfSDavid du Colombier {
164375daca8SDavid du Colombier 	char ofile[400], incfile[20];
165*6bbfed0dSDavid du Colombier 	char *p, **av, opt[256];
1667dd7cddfSDavid du Colombier 	int i, c, fd[2];
167aedc1c01SDavid du Colombier 	static int first = 1;
1687dd7cddfSDavid du Colombier 
1697dd7cddfSDavid du Colombier 	strcpy(ofile, file);
1707dd7cddfSDavid du Colombier 	p = utfrrune(ofile, pathchar());
1717dd7cddfSDavid du Colombier 	if(p) {
1723e12c5d1SDavid du Colombier 		*p++ = 0;
173810832d3SDavid du Colombier 		if(!debug['.'])
174375daca8SDavid du Colombier 			include[0] = strdup(ofile);
1753e12c5d1SDavid du Colombier 	} else
1763e12c5d1SDavid du Colombier 		p = ofile;
177314a20f0SDavid du Colombier 
1783e12c5d1SDavid du Colombier 	if(outfile == 0) {
1793e12c5d1SDavid du Colombier 		outfile = p;
1807dd7cddfSDavid du Colombier 		if(outfile) {
1813e12c5d1SDavid du Colombier 			if(p = utfrrune(outfile, '.'))
1823e12c5d1SDavid du Colombier 				if(p[1] == 'c' && p[2] == 0)
1833e12c5d1SDavid du Colombier 					p[0] = 0;
1843e12c5d1SDavid du Colombier 			p = utfrune(outfile, 0);
1857dd7cddfSDavid du Colombier 			if(debug['a'] && debug['n'])
1867dd7cddfSDavid du Colombier 				strcat(p, ".acid");
187fc375d71SDavid du Colombier 			else if(debug['Z'] && debug['n'])
18880ee5cbfSDavid du Colombier 				strcat(p, "_pickle.c");
1897dd7cddfSDavid du Colombier 			else {
1903e12c5d1SDavid du Colombier 				p[0] = '.';
1913e12c5d1SDavid du Colombier 				p[1] = thechar;
1923e12c5d1SDavid du Colombier 				p[2] = 0;
1933e12c5d1SDavid du Colombier 			}
1947dd7cddfSDavid du Colombier 		} else
1957dd7cddfSDavid du Colombier 			outfile = "/dev/null";
1963e12c5d1SDavid du Colombier 	}
1977dd7cddfSDavid du Colombier 
1983e12c5d1SDavid du Colombier 	if(p = getenv("INCLUDE")) {
1997dd7cddfSDavid du Colombier 		setinclude(p);
2003e12c5d1SDavid du Colombier 	} else {
2017dd7cddfSDavid du Colombier 		if(systemtype(Plan9)) {
2027dd7cddfSDavid du Colombier 			sprint(incfile, "/%s/include", thestring);
2037dd7cddfSDavid du Colombier 			setinclude(strdup(incfile));
2047dd7cddfSDavid du Colombier 			setinclude("/sys/include");
2053e12c5d1SDavid du Colombier 		}
2067dd7cddfSDavid du Colombier 	}
207aedc1c01SDavid du Colombier 	if (first)
208314a20f0SDavid du Colombier 		Binit(&diagbuf, 1, OWRITE);
209aedc1c01SDavid du Colombier 	/*
210aedc1c01SDavid du Colombier 	 * if we're writing acid to standard output, don't keep scratching
211aedc1c01SDavid du Colombier 	 * outbuf.
212aedc1c01SDavid du Colombier 	 */
213fc375d71SDavid du Colombier 	if((debug['a'] || debug['Z']) && !debug['n']) {
214aedc1c01SDavid du Colombier 		if (first) {
2153e12c5d1SDavid du Colombier 			outfile = 0;
216e059317eSDavid du Colombier 			Binit(&outbuf, dup(1, -1), OWRITE);
217e059317eSDavid du Colombier 			dup(2, 1);
218aedc1c01SDavid du Colombier 		}
219219b2ee8SDavid du Colombier 	} else {
220219b2ee8SDavid du Colombier 		c = mycreat(outfile, 0664);
221219b2ee8SDavid du Colombier 		if(c < 0) {
222314a20f0SDavid du Colombier 			diag(Z, "cannot open %s - %r", outfile);
223219b2ee8SDavid du Colombier 			outfile = 0;
224219b2ee8SDavid du Colombier 			errorexit();
225219b2ee8SDavid du Colombier 		}
226219b2ee8SDavid du Colombier 		Binit(&outbuf, c, OWRITE);
227219b2ee8SDavid du Colombier 	}
2283e12c5d1SDavid du Colombier 	newio();
229aedc1c01SDavid du Colombier 	first = 0;
2307dd7cddfSDavid du Colombier 
2317dd7cddfSDavid du Colombier 	/* Use an ANSI preprocessor */
2327dd7cddfSDavid du Colombier 	if(debug['p']) {
2337dd7cddfSDavid du Colombier 		if(systemtype(Windows)) {
2347dd7cddfSDavid du Colombier 			diag(Z, "-p option not supported on windows");
2357dd7cddfSDavid du Colombier 			errorexit();
2367dd7cddfSDavid du Colombier 		}
23780ee5cbfSDavid du Colombier 		if(myaccess(file) < 0) {
23880ee5cbfSDavid du Colombier 			diag(Z, "%s does not exist", file);
23980ee5cbfSDavid du Colombier 			errorexit();
24080ee5cbfSDavid du Colombier 		}
2417dd7cddfSDavid du Colombier 		if(mypipe(fd) < 0) {
2427dd7cddfSDavid du Colombier 			diag(Z, "pipe failed");
2437dd7cddfSDavid du Colombier 			errorexit();
2447dd7cddfSDavid du Colombier 		}
2457dd7cddfSDavid du Colombier 		switch(myfork()) {
2467dd7cddfSDavid du Colombier 		case -1:
2477dd7cddfSDavid du Colombier 			diag(Z, "fork failed");
2487dd7cddfSDavid du Colombier 			errorexit();
2497dd7cddfSDavid du Colombier 		case 0:
2507dd7cddfSDavid du Colombier 			close(fd[0]);
2517dd7cddfSDavid du Colombier 			mydup(fd[1], 1);
2527dd7cddfSDavid du Colombier 			close(fd[1]);
253*6bbfed0dSDavid du Colombier 			av = alloc((3 + ndef + ninclude + 2) * sizeof *av);
2547dd7cddfSDavid du Colombier 			av[0] = CPP;
2557dd7cddfSDavid du Colombier 			i = 1;
2567ee275a1SDavid du Colombier 			if(debug['.'])
2577ee275a1SDavid du Colombier 				av[i++] = strdup("-.");
2587ee275a1SDavid du Colombier 			/* 1999 ANSI C requires recognising // comments */
2597ee275a1SDavid du Colombier 			av[i++] = strdup("-+");
2607dd7cddfSDavid du Colombier 			for(c = 0; c < ndef; c++) {
2617dd7cddfSDavid du Colombier 				sprint(opt, "-D%s", defs[c]);
2627dd7cddfSDavid du Colombier 				av[i++] = strdup(opt);
2637dd7cddfSDavid du Colombier 			}
2647dd7cddfSDavid du Colombier 			for(c = 0; c < ninclude; c++) {
2657dd7cddfSDavid du Colombier 				sprint(opt, "-I%s", include[c]);
2667dd7cddfSDavid du Colombier 				av[i++] = strdup(opt);
2677dd7cddfSDavid du Colombier 			}
2687dd7cddfSDavid du Colombier 			if(strcmp(file, "stdin") != 0)
2697dd7cddfSDavid du Colombier 				av[i++] = file;
2707dd7cddfSDavid du Colombier 			av[i] = 0;
2717dd7cddfSDavid du Colombier 			if(debug['p'] > 1) {
2727dd7cddfSDavid du Colombier 				for(c = 0; c < i; c++)
2737dd7cddfSDavid du Colombier 					fprint(2, "%s ", av[c]);
2744de34a7eSDavid du Colombier 				fprint(2, "\n");
2757dd7cddfSDavid du Colombier 			}
2767dd7cddfSDavid du Colombier 			myexec(av[0], av);
2777dd7cddfSDavid du Colombier 			fprint(2, "can't exec C preprocessor %s: %r\n", CPP);
2787dd7cddfSDavid du Colombier 			errorexit();
2797dd7cddfSDavid du Colombier 		default:
2807dd7cddfSDavid du Colombier 			close(fd[1]);
2817dd7cddfSDavid du Colombier 			newfile(file, fd[0]);
2827dd7cddfSDavid du Colombier 			break;
2837dd7cddfSDavid du Colombier 		}
2847dd7cddfSDavid du Colombier 	} else {
2857dd7cddfSDavid du Colombier 		if(strcmp(file, "stdin") == 0)
2867dd7cddfSDavid du Colombier 			newfile(file, 0);
2873e12c5d1SDavid du Colombier 		else
2887dd7cddfSDavid du Colombier 			newfile(file, -1);
2897dd7cddfSDavid du Colombier 	}
2903e12c5d1SDavid du Colombier 	yyparse();
291fc375d71SDavid du Colombier 	if(!debug['a'] && !debug['Z'])
2923e12c5d1SDavid du Colombier 		gclean();
2937dd7cddfSDavid du Colombier 	return nerrors;
2943e12c5d1SDavid du Colombier }
2953e12c5d1SDavid du Colombier 
2963e12c5d1SDavid du Colombier void
errorexit(void)2973e12c5d1SDavid du Colombier errorexit(void)
2983e12c5d1SDavid du Colombier {
2993e12c5d1SDavid du Colombier 	if(outfile)
3003e12c5d1SDavid du Colombier 		remove(outfile);
3013e12c5d1SDavid du Colombier 	exits("error");
3023e12c5d1SDavid du Colombier }
3033e12c5d1SDavid du Colombier 
3043e12c5d1SDavid du Colombier void
pushio(void)3053e12c5d1SDavid du Colombier pushio(void)
3063e12c5d1SDavid du Colombier {
3073e12c5d1SDavid du Colombier 	Io *i;
3083e12c5d1SDavid du Colombier 
3093e12c5d1SDavid du Colombier 	i = iostack;
3103e12c5d1SDavid du Colombier 	if(i == I) {
3113e12c5d1SDavid du Colombier 		yyerror("botch in pushio");
3123e12c5d1SDavid du Colombier 		errorexit();
3133e12c5d1SDavid du Colombier 	}
3143e12c5d1SDavid du Colombier 	i->p = fi.p;
3153e12c5d1SDavid du Colombier 	i->c = fi.c;
3163e12c5d1SDavid du Colombier }
3173e12c5d1SDavid du Colombier 
3183e12c5d1SDavid du Colombier void
newio(void)3193e12c5d1SDavid du Colombier newio(void)
3203e12c5d1SDavid du Colombier {
3213e12c5d1SDavid du Colombier 	Io *i;
322375daca8SDavid du Colombier 	static int pushdepth = 0;
3233e12c5d1SDavid du Colombier 
3243e12c5d1SDavid du Colombier 	i = iofree;
3253e12c5d1SDavid du Colombier 	if(i == I) {
3263e12c5d1SDavid du Colombier 		pushdepth++;
3273e12c5d1SDavid du Colombier 		if(pushdepth > 1000) {
3283e12c5d1SDavid du Colombier 			yyerror("macro/io expansion too deep");
3293e12c5d1SDavid du Colombier 			errorexit();
3303e12c5d1SDavid du Colombier 		}
3317dd7cddfSDavid du Colombier 		i = alloc(sizeof(*i));
3323e12c5d1SDavid du Colombier 	} else
3333e12c5d1SDavid du Colombier 		iofree = i->link;
3343e12c5d1SDavid du Colombier 	i->c = 0;
3353e12c5d1SDavid du Colombier 	i->f = -1;
3363e12c5d1SDavid du Colombier 	ionext = i;
3373e12c5d1SDavid du Colombier }
3383e12c5d1SDavid du Colombier 
3393e12c5d1SDavid du Colombier void
newfile(char * s,int f)3403e12c5d1SDavid du Colombier newfile(char *s, int f)
3413e12c5d1SDavid du Colombier {
3423e12c5d1SDavid du Colombier 	Io *i;
3433e12c5d1SDavid du Colombier 
3447dd7cddfSDavid du Colombier 	if(debug['e'])
3457dd7cddfSDavid du Colombier 		print("%L: %s\n", lineno, s);
3467dd7cddfSDavid du Colombier 
3473e12c5d1SDavid du Colombier 	i = ionext;
3483e12c5d1SDavid du Colombier 	i->link = iostack;
3493e12c5d1SDavid du Colombier 	iostack = i;
3503e12c5d1SDavid du Colombier 	i->f = f;
3513e12c5d1SDavid du Colombier 	if(f < 0)
3523e12c5d1SDavid du Colombier 		i->f = open(s, 0);
3533e12c5d1SDavid du Colombier 	if(i->f < 0) {
3547dd7cddfSDavid du Colombier 		yyerror("%cc: %r: %s", thechar, s);
3553e12c5d1SDavid du Colombier 		errorexit();
3563e12c5d1SDavid du Colombier 	}
3573e12c5d1SDavid du Colombier 	fi.c = 0;
3583e12c5d1SDavid du Colombier 	linehist(s, 0);
3593e12c5d1SDavid du Colombier }
3603e12c5d1SDavid du Colombier 
3613e12c5d1SDavid du Colombier Sym*
slookup(char * s)3623e12c5d1SDavid du Colombier slookup(char *s)
3633e12c5d1SDavid du Colombier {
3643e12c5d1SDavid du Colombier 
3653e12c5d1SDavid du Colombier 	strcpy(symb, s);
3663e12c5d1SDavid du Colombier 	return lookup();
3673e12c5d1SDavid du Colombier }
3683e12c5d1SDavid du Colombier 
3693e12c5d1SDavid du Colombier Sym*
lookup(void)3703e12c5d1SDavid du Colombier lookup(void)
3713e12c5d1SDavid du Colombier {
3723e12c5d1SDavid du Colombier 	Sym *s;
3733e12c5d1SDavid du Colombier 	ulong h;
374219b2ee8SDavid du Colombier 	char *p;
375219b2ee8SDavid du Colombier 	int c, n;
3763e12c5d1SDavid du Colombier 
377219b2ee8SDavid du Colombier 	h = 0;
3783e12c5d1SDavid du Colombier 	for(p=symb; *p;) {
379219b2ee8SDavid du Colombier 		h = h * 3;
380219b2ee8SDavid du Colombier 		h += *p++;
3813e12c5d1SDavid du Colombier 	}
382219b2ee8SDavid du Colombier 	n = (p - symb) + 1;
383219b2ee8SDavid du Colombier 	if((long)h < 0)
384219b2ee8SDavid du Colombier 		h = ~h;
3853e12c5d1SDavid du Colombier 	h %= NHASH;
386219b2ee8SDavid du Colombier 	c = symb[0];
3873e12c5d1SDavid du Colombier 	for(s = hash[h]; s != S; s = s->link) {
388219b2ee8SDavid du Colombier 		if(s->name[0] != c)
3893e12c5d1SDavid du Colombier 			continue;
390219b2ee8SDavid du Colombier 		if(strcmp(s->name, symb) == 0)
3913e12c5d1SDavid du Colombier 			return s;
3923e12c5d1SDavid du Colombier 	}
3937dd7cddfSDavid du Colombier 	s = alloc(sizeof(*s));
3947dd7cddfSDavid du Colombier 	s->name = alloc(n);
395219b2ee8SDavid du Colombier 	memmove(s->name, symb, n);
396219b2ee8SDavid du Colombier 
3973e12c5d1SDavid du Colombier 	strcpy(s->name, symb);
3983e12c5d1SDavid du Colombier 	s->link = hash[h];
3993e12c5d1SDavid du Colombier 	hash[h] = s;
4003e12c5d1SDavid du Colombier 	syminit(s);
4013e12c5d1SDavid du Colombier 
4023e12c5d1SDavid du Colombier 	return s;
4033e12c5d1SDavid du Colombier }
4043e12c5d1SDavid du Colombier 
4053e12c5d1SDavid du Colombier void
syminit(Sym * s)4063e12c5d1SDavid du Colombier syminit(Sym *s)
4073e12c5d1SDavid du Colombier {
4083e12c5d1SDavid du Colombier 	s->lexical = LNAME;
4093e12c5d1SDavid du Colombier 	s->block = 0;
4103e12c5d1SDavid du Colombier 	s->offset = 0;
4113e12c5d1SDavid du Colombier 	s->type = T;
4123e12c5d1SDavid du Colombier 	s->suetag = T;
4133e12c5d1SDavid du Colombier 	s->class = CXXX;
4143e12c5d1SDavid du Colombier 	s->aused = 0;
415375daca8SDavid du Colombier 	s->sig = SIGNONE;
4163e12c5d1SDavid du Colombier }
4173e12c5d1SDavid du Colombier 
4183e12c5d1SDavid du Colombier #define	EOF	(-1)
4193e12c5d1SDavid du Colombier #define	IGN	(-2)
420905f70e7SDavid du Colombier #define	ESC	(Runemask+1)		/* Rune flag: a literal byte */
4213e12c5d1SDavid du Colombier #define	GETC()	((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff))
4223e12c5d1SDavid du Colombier 
4233e12c5d1SDavid du Colombier enum
4243e12c5d1SDavid du Colombier {
4253e12c5d1SDavid du Colombier 	Numdec		= 1<<0,
4263e12c5d1SDavid du Colombier 	Numlong		= 1<<1,
4273e12c5d1SDavid du Colombier 	Numuns		= 1<<2,
4283e12c5d1SDavid du Colombier 	Numvlong	= 1<<3,
4293e12c5d1SDavid du Colombier 	Numflt		= 1<<4,
4303e12c5d1SDavid du Colombier };
4313e12c5d1SDavid du Colombier 
4323e12c5d1SDavid du Colombier long
yylex(void)4333e12c5d1SDavid du Colombier yylex(void)
4343e12c5d1SDavid du Colombier {
435219b2ee8SDavid du Colombier 	vlong vv;
43622a127bbSDavid du Colombier 	long c, c1, t;
4373e12c5d1SDavid du Colombier 	char *cp;
4383e12c5d1SDavid du Colombier 	Rune rune;
4393e12c5d1SDavid du Colombier 	Sym *s;
4403e12c5d1SDavid du Colombier 
4413e12c5d1SDavid du Colombier 	if(peekc != IGN) {
4423e12c5d1SDavid du Colombier 		c = peekc;
4433e12c5d1SDavid du Colombier 		peekc = IGN;
4443e12c5d1SDavid du Colombier 		goto l1;
4453e12c5d1SDavid du Colombier 	}
4463e12c5d1SDavid du Colombier l0:
4473e12c5d1SDavid du Colombier 	c = GETC();
4483e12c5d1SDavid du Colombier 
4493e12c5d1SDavid du Colombier l1:
4503e12c5d1SDavid du Colombier 	if(c >= Runeself) {
4513e12c5d1SDavid du Colombier 		/*
4523e12c5d1SDavid du Colombier 		 * extension --
4533e12c5d1SDavid du Colombier 		 *	all multibyte runes are alpha
4543e12c5d1SDavid du Colombier 		 */
4553e12c5d1SDavid du Colombier 		cp = symb;
4563e12c5d1SDavid du Colombier 		goto talph;
4573e12c5d1SDavid du Colombier 	}
4583e12c5d1SDavid du Colombier 	if(isspace(c)) {
4593e12c5d1SDavid du Colombier 		if(c == '\n')
4603e12c5d1SDavid du Colombier 			lineno++;
4613e12c5d1SDavid du Colombier 		goto l0;
4623e12c5d1SDavid du Colombier 	}
4633e12c5d1SDavid du Colombier 	if(isalpha(c)) {
4643e12c5d1SDavid du Colombier 		cp = symb;
4653e12c5d1SDavid du Colombier 		if(c != 'L')
4663e12c5d1SDavid du Colombier 			goto talph;
4673e12c5d1SDavid du Colombier 		*cp++ = c;
4683e12c5d1SDavid du Colombier 		c = GETC();
4693e12c5d1SDavid du Colombier 		if(c == '\'') {
4703e12c5d1SDavid du Colombier 			/* L'x' */
4713e12c5d1SDavid du Colombier 			c = escchar('\'', 1, 0);
4723e12c5d1SDavid du Colombier 			if(c == EOF)
4733e12c5d1SDavid du Colombier 				c = '\'';
4743e12c5d1SDavid du Colombier 			c1 = escchar('\'', 1, 0);
4753e12c5d1SDavid du Colombier 			if(c1 != EOF) {
4763e12c5d1SDavid du Colombier 				yyerror("missing '");
4773e12c5d1SDavid du Colombier 				peekc = c1;
4783e12c5d1SDavid du Colombier 			}
47982726826SDavid du Colombier 			yylval.vval = convvtox(c, TRUNE);
4803e12c5d1SDavid du Colombier 			return LUCONST;
4813e12c5d1SDavid du Colombier 		}
4823e12c5d1SDavid du Colombier 		if(c == '"') {
4833e12c5d1SDavid du Colombier 			goto caselq;
4843e12c5d1SDavid du Colombier 		}
4853e12c5d1SDavid du Colombier 		goto talph;
4863e12c5d1SDavid du Colombier 	}
4873e12c5d1SDavid du Colombier 	if(isdigit(c))
4883e12c5d1SDavid du Colombier 		goto tnum;
4893e12c5d1SDavid du Colombier 	switch(c)
4903e12c5d1SDavid du Colombier 	{
4913e12c5d1SDavid du Colombier 
4923e12c5d1SDavid du Colombier 	case EOF:
4933e12c5d1SDavid du Colombier 		peekc = EOF;
4943e12c5d1SDavid du Colombier 		return -1;
4953e12c5d1SDavid du Colombier 
4963e12c5d1SDavid du Colombier 	case '_':
4973e12c5d1SDavid du Colombier 		cp = symb;
4983e12c5d1SDavid du Colombier 		goto talph;
4993e12c5d1SDavid du Colombier 
5003e12c5d1SDavid du Colombier 	case '#':
5013e12c5d1SDavid du Colombier 		domacro();
5023e12c5d1SDavid du Colombier 		goto l0;
5033e12c5d1SDavid du Colombier 
5043e12c5d1SDavid du Colombier 	case '.':
5053e12c5d1SDavid du Colombier 		c1 = GETC();
5063e12c5d1SDavid du Colombier 		if(isdigit(c1)) {
5073e12c5d1SDavid du Colombier 			cp = symb;
5083e12c5d1SDavid du Colombier 			*cp++ = c;
5093e12c5d1SDavid du Colombier 			c = c1;
5103e12c5d1SDavid du Colombier 			c1 = 0;
5113e12c5d1SDavid du Colombier 			goto casedot;
5123e12c5d1SDavid du Colombier 		}
5133e12c5d1SDavid du Colombier 		break;
5143e12c5d1SDavid du Colombier 
5153e12c5d1SDavid du Colombier 	case '"':
5167dd7cddfSDavid du Colombier 		strcpy(symb, "\"<string>\"");
5177dd7cddfSDavid du Colombier 		cp = alloc(0);
5183e12c5d1SDavid du Colombier 		c1 = 0;
5193e12c5d1SDavid du Colombier 
5203e12c5d1SDavid du Colombier 		/* "..." */
5213e12c5d1SDavid du Colombier 		for(;;) {
5223e12c5d1SDavid du Colombier 			c = escchar('"', 0, 1);
5233e12c5d1SDavid du Colombier 			if(c == EOF)
5243e12c5d1SDavid du Colombier 				break;
5253e12c5d1SDavid du Colombier 			if(c & ESC) {
5267dd7cddfSDavid du Colombier 				cp = allocn(cp, c1, 1);
5277dd7cddfSDavid du Colombier 				cp[c1++] = c;
5283e12c5d1SDavid du Colombier 			} else {
5293e12c5d1SDavid du Colombier 				rune = c;
5303e12c5d1SDavid du Colombier 				c = runelen(rune);
5317dd7cddfSDavid du Colombier 				cp = allocn(cp, c1, c);
5323e12c5d1SDavid du Colombier 				runetochar(cp+c1, &rune);
5333e12c5d1SDavid du Colombier 				c1 += c;
5343e12c5d1SDavid du Colombier 			}
5353e12c5d1SDavid du Colombier 		}
5367dd7cddfSDavid du Colombier 		yylval.sval.l = c1;
5373e12c5d1SDavid du Colombier 		do {
5387dd7cddfSDavid du Colombier 			cp = allocn(cp, c1, 1);
5393e12c5d1SDavid du Colombier 			cp[c1++] = 0;
5407dd7cddfSDavid du Colombier 		} while(c1 & MAXALIGN);
5417dd7cddfSDavid du Colombier 		yylval.sval.s = cp;
5423e12c5d1SDavid du Colombier 		return LSTRING;
5433e12c5d1SDavid du Colombier 
5443e12c5d1SDavid du Colombier 	caselq:
5453e12c5d1SDavid du Colombier 		/* L"..." */
5467dd7cddfSDavid du Colombier 		strcpy(symb, "\"L<string>\"");
5477dd7cddfSDavid du Colombier 		cp = alloc(0);
5487dd7cddfSDavid du Colombier 		c1 = 0;
5493e12c5d1SDavid du Colombier 		for(;;) {
5503e12c5d1SDavid du Colombier 			c = escchar('"', 1, 0);
5513e12c5d1SDavid du Colombier 			if(c == EOF)
5523e12c5d1SDavid du Colombier 				break;
55382726826SDavid du Colombier 			cp = allocn(cp, c1, sizeof(TRune));
55482726826SDavid du Colombier 			*(TRune*)(cp + c1) = c;
55582726826SDavid du Colombier 			c1 += sizeof(TRune);
5563e12c5d1SDavid du Colombier 		}
5577dd7cddfSDavid du Colombier 		yylval.sval.l = c1;
5583e12c5d1SDavid du Colombier 		do {
55982726826SDavid du Colombier 			cp = allocn(cp, c1, sizeof(TRune));
56082726826SDavid du Colombier 			*(TRune*)(cp + c1) = 0;
56182726826SDavid du Colombier 			c1 += sizeof(TRune);
5627dd7cddfSDavid du Colombier 		} while(c1 & MAXALIGN);
5637dd7cddfSDavid du Colombier 		yylval.sval.s = cp;
5643e12c5d1SDavid du Colombier 		return LLSTRING;
5653e12c5d1SDavid du Colombier 
5663e12c5d1SDavid du Colombier 	case '\'':
5673e12c5d1SDavid du Colombier 		/* '.' */
5683e12c5d1SDavid du Colombier 		c = escchar('\'', 0, 0);
5693e12c5d1SDavid du Colombier 		if(c == EOF)
5703e12c5d1SDavid du Colombier 			c = '\'';
5713e12c5d1SDavid du Colombier 		c1 = escchar('\'', 0, 0);
5723e12c5d1SDavid du Colombier 		if(c1 != EOF) {
5733e12c5d1SDavid du Colombier 			yyerror("missing '");
5743e12c5d1SDavid du Colombier 			peekc = c1;
5753e12c5d1SDavid du Colombier 		}
576219b2ee8SDavid du Colombier 		vv = c;
577219b2ee8SDavid du Colombier 		yylval.vval = convvtox(vv, TUCHAR);
578219b2ee8SDavid du Colombier 		if(yylval.vval != vv)
5797dd7cddfSDavid du Colombier 			yyerror("overflow in character constant: 0x%lx", c);
5807dd7cddfSDavid du Colombier 		else
58122a127bbSDavid du Colombier 		if(c & 0x80){
58222a127bbSDavid du Colombier 			nearln = lineno;
5837dd7cddfSDavid du Colombier 			warn(Z, "sign-extended character constant");
58422a127bbSDavid du Colombier 		}
585219b2ee8SDavid du Colombier 		yylval.vval = convvtox(vv, TCHAR);
5863e12c5d1SDavid du Colombier 		return LCONST;
5873e12c5d1SDavid du Colombier 
5883e12c5d1SDavid du Colombier 	case '/':
5893e12c5d1SDavid du Colombier 		c1 = GETC();
5903e12c5d1SDavid du Colombier 		if(c1 == '*') {
5913e12c5d1SDavid du Colombier 			for(;;) {
5923e12c5d1SDavid du Colombier 				c = getr();
5933e12c5d1SDavid du Colombier 				while(c == '*') {
5943e12c5d1SDavid du Colombier 					c = getr();
5953e12c5d1SDavid du Colombier 					if(c == '/')
5963e12c5d1SDavid du Colombier 						goto l0;
5973e12c5d1SDavid du Colombier 				}
5983e12c5d1SDavid du Colombier 				if(c == EOF) {
5993e12c5d1SDavid du Colombier 					yyerror("eof in comment");
6003e12c5d1SDavid du Colombier 					errorexit();
6013e12c5d1SDavid du Colombier 				}
6023e12c5d1SDavid du Colombier 			}
6033e12c5d1SDavid du Colombier 		}
604219b2ee8SDavid du Colombier 		if(c1 == '/') {
605219b2ee8SDavid du Colombier 			for(;;) {
606219b2ee8SDavid du Colombier 				c = getr();
607219b2ee8SDavid du Colombier 				if(c == '\n')
608219b2ee8SDavid du Colombier 					goto l0;
609219b2ee8SDavid du Colombier 				if(c == EOF) {
610219b2ee8SDavid du Colombier 					yyerror("eof in comment");
611219b2ee8SDavid du Colombier 					errorexit();
612219b2ee8SDavid du Colombier 				}
613219b2ee8SDavid du Colombier 			}
614219b2ee8SDavid du Colombier 		}
6153e12c5d1SDavid du Colombier 		if(c1 == '=')
6163e12c5d1SDavid du Colombier 			return LDVE;
6173e12c5d1SDavid du Colombier 		break;
6183e12c5d1SDavid du Colombier 
6193e12c5d1SDavid du Colombier 	case '*':
6203e12c5d1SDavid du Colombier 		c1 = GETC();
6213e12c5d1SDavid du Colombier 		if(c1 == '=')
6223e12c5d1SDavid du Colombier 			return LMLE;
6233e12c5d1SDavid du Colombier 		break;
6243e12c5d1SDavid du Colombier 
6253e12c5d1SDavid du Colombier 	case '%':
6263e12c5d1SDavid du Colombier 		c1 = GETC();
6273e12c5d1SDavid du Colombier 		if(c1 == '=')
6283e12c5d1SDavid du Colombier 			return LMDE;
6293e12c5d1SDavid du Colombier 		break;
6303e12c5d1SDavid du Colombier 
6313e12c5d1SDavid du Colombier 	case '+':
6323e12c5d1SDavid du Colombier 		c1 = GETC();
6333e12c5d1SDavid du Colombier 		if(c1 == '+')
6343e12c5d1SDavid du Colombier 			return LPP;
6353e12c5d1SDavid du Colombier 		if(c1 == '=')
6363e12c5d1SDavid du Colombier 			return LPE;
6373e12c5d1SDavid du Colombier 		break;
6383e12c5d1SDavid du Colombier 
6393e12c5d1SDavid du Colombier 	case '-':
6403e12c5d1SDavid du Colombier 		c1 = GETC();
6413e12c5d1SDavid du Colombier 		if(c1 == '-')
6423e12c5d1SDavid du Colombier 			return LMM;
6433e12c5d1SDavid du Colombier 		if(c1 == '=')
6443e12c5d1SDavid du Colombier 			return LME;
6453e12c5d1SDavid du Colombier 		if(c1 == '>')
6463e12c5d1SDavid du Colombier 			return LMG;
6473e12c5d1SDavid du Colombier 		break;
6483e12c5d1SDavid du Colombier 
6493e12c5d1SDavid du Colombier 	case '>':
6503e12c5d1SDavid du Colombier 		c1 = GETC();
6513e12c5d1SDavid du Colombier 		if(c1 == '>') {
6523e12c5d1SDavid du Colombier 			c = LRSH;
6533e12c5d1SDavid du Colombier 			c1 = GETC();
6543e12c5d1SDavid du Colombier 			if(c1 == '=')
6553e12c5d1SDavid du Colombier 				return LRSHE;
6563e12c5d1SDavid du Colombier 			break;
6573e12c5d1SDavid du Colombier 		}
6583e12c5d1SDavid du Colombier 		if(c1 == '=')
6593e12c5d1SDavid du Colombier 			return LGE;
6603e12c5d1SDavid du Colombier 		break;
6613e12c5d1SDavid du Colombier 
6623e12c5d1SDavid du Colombier 	case '<':
6633e12c5d1SDavid du Colombier 		c1 = GETC();
6643e12c5d1SDavid du Colombier 		if(c1 == '<') {
6653e12c5d1SDavid du Colombier 			c = LLSH;
6663e12c5d1SDavid du Colombier 			c1 = GETC();
6673e12c5d1SDavid du Colombier 			if(c1 == '=')
6683e12c5d1SDavid du Colombier 				return LLSHE;
6693e12c5d1SDavid du Colombier 			break;
6703e12c5d1SDavid du Colombier 		}
6713e12c5d1SDavid du Colombier 		if(c1 == '=')
6723e12c5d1SDavid du Colombier 			return LLE;
6733e12c5d1SDavid du Colombier 		break;
6743e12c5d1SDavid du Colombier 
6753e12c5d1SDavid du Colombier 	case '=':
6763e12c5d1SDavid du Colombier 		c1 = GETC();
6773e12c5d1SDavid du Colombier 		if(c1 == '=')
6783e12c5d1SDavid du Colombier 			return LEQ;
6793e12c5d1SDavid du Colombier 		break;
6803e12c5d1SDavid du Colombier 
6813e12c5d1SDavid du Colombier 	case '!':
6823e12c5d1SDavid du Colombier 		c1 = GETC();
6833e12c5d1SDavid du Colombier 		if(c1 == '=')
6843e12c5d1SDavid du Colombier 			return LNE;
6853e12c5d1SDavid du Colombier 		break;
6863e12c5d1SDavid du Colombier 
6873e12c5d1SDavid du Colombier 	case '&':
6883e12c5d1SDavid du Colombier 		c1 = GETC();
6893e12c5d1SDavid du Colombier 		if(c1 == '&')
6903e12c5d1SDavid du Colombier 			return LANDAND;
6913e12c5d1SDavid du Colombier 		if(c1 == '=')
6923e12c5d1SDavid du Colombier 			return LANDE;
6933e12c5d1SDavid du Colombier 		break;
6943e12c5d1SDavid du Colombier 
6953e12c5d1SDavid du Colombier 	case '|':
6963e12c5d1SDavid du Colombier 		c1 = GETC();
6973e12c5d1SDavid du Colombier 		if(c1 == '|')
6983e12c5d1SDavid du Colombier 			return LOROR;
6993e12c5d1SDavid du Colombier 		if(c1 == '=')
7003e12c5d1SDavid du Colombier 			return LORE;
7013e12c5d1SDavid du Colombier 		break;
7023e12c5d1SDavid du Colombier 
7033e12c5d1SDavid du Colombier 	case '^':
7043e12c5d1SDavid du Colombier 		c1 = GETC();
7053e12c5d1SDavid du Colombier 		if(c1 == '=')
7063e12c5d1SDavid du Colombier 			return LXORE;
7073e12c5d1SDavid du Colombier 		break;
7083e12c5d1SDavid du Colombier 
7093e12c5d1SDavid du Colombier 	default:
7103e12c5d1SDavid du Colombier 		return c;
7113e12c5d1SDavid du Colombier 	}
7123e12c5d1SDavid du Colombier 	peekc = c1;
7133e12c5d1SDavid du Colombier 	return c;
7143e12c5d1SDavid du Colombier 
7153e12c5d1SDavid du Colombier talph:
7163e12c5d1SDavid du Colombier 	/*
7173e12c5d1SDavid du Colombier 	 * cp is set to symb and some
7183e12c5d1SDavid du Colombier 	 * prefix has been stored
7193e12c5d1SDavid du Colombier 	 */
7203e12c5d1SDavid du Colombier 	for(;;) {
7213e12c5d1SDavid du Colombier 		if(c >= Runeself) {
7223e12c5d1SDavid du Colombier 			for(c1=0;;) {
7233e12c5d1SDavid du Colombier 				cp[c1++] = c;
7243e12c5d1SDavid du Colombier 				if(fullrune(cp, c1))
7253e12c5d1SDavid du Colombier 					break;
7263e12c5d1SDavid du Colombier 				c = GETC();
7273e12c5d1SDavid du Colombier 			}
7283e12c5d1SDavid du Colombier 			cp += c1;
7293e12c5d1SDavid du Colombier 			c = GETC();
7303e12c5d1SDavid du Colombier 			continue;
7313e12c5d1SDavid du Colombier 		}
7323e12c5d1SDavid du Colombier 		if(!isalnum(c) && c != '_')
7333e12c5d1SDavid du Colombier 			break;
7343e12c5d1SDavid du Colombier 		*cp++ = c;
7353e12c5d1SDavid du Colombier 		c = GETC();
7363e12c5d1SDavid du Colombier 	}
7373e12c5d1SDavid du Colombier 	*cp = 0;
7383e12c5d1SDavid du Colombier 	if(debug['L'])
739219b2ee8SDavid du Colombier 		print("%L: %s\n", lineno, symb);
7403e12c5d1SDavid du Colombier 	peekc = c;
7413e12c5d1SDavid du Colombier 	s = lookup();
7423e12c5d1SDavid du Colombier 	if(s->macro) {
7433e12c5d1SDavid du Colombier 		newio();
7443e12c5d1SDavid du Colombier 		cp = ionext->b;
7453e12c5d1SDavid du Colombier 		macexpand(s, cp);
7463e12c5d1SDavid du Colombier 		pushio();
7473e12c5d1SDavid du Colombier 		ionext->link = iostack;
7483e12c5d1SDavid du Colombier 		iostack = ionext;
7493e12c5d1SDavid du Colombier 		fi.p = cp;
7503e12c5d1SDavid du Colombier 		fi.c = strlen(cp);
7513e12c5d1SDavid du Colombier 		if(peekc != IGN) {
7523e12c5d1SDavid du Colombier 			cp[fi.c++] = peekc;
7533e12c5d1SDavid du Colombier 			cp[fi.c] = 0;
7543e12c5d1SDavid du Colombier 			peekc = IGN;
7553e12c5d1SDavid du Colombier 		}
7563e12c5d1SDavid du Colombier 		goto l0;
7573e12c5d1SDavid du Colombier 	}
7583e12c5d1SDavid du Colombier 	yylval.sym = s;
75980ee5cbfSDavid du Colombier 	if(s->class == CTYPEDEF || s->class == CTYPESTR)
76080ee5cbfSDavid du Colombier 		return LTYPE;
7613e12c5d1SDavid du Colombier 	return s->lexical;
7623e12c5d1SDavid du Colombier 
7633e12c5d1SDavid du Colombier tnum:
7643e12c5d1SDavid du Colombier 	c1 = 0;
7653e12c5d1SDavid du Colombier 	cp = symb;
7663e12c5d1SDavid du Colombier 	if(c != '0') {
7673e12c5d1SDavid du Colombier 		c1 |= Numdec;
7683e12c5d1SDavid du Colombier 		for(;;) {
7693e12c5d1SDavid du Colombier 			*cp++ = c;
7703e12c5d1SDavid du Colombier 			c = GETC();
7713e12c5d1SDavid du Colombier 			if(isdigit(c))
7723e12c5d1SDavid du Colombier 				continue;
7733e12c5d1SDavid du Colombier 			goto dc;
7743e12c5d1SDavid du Colombier 		}
7753e12c5d1SDavid du Colombier 	}
7763e12c5d1SDavid du Colombier 	*cp++ = c;
7773e12c5d1SDavid du Colombier 	c = GETC();
7783e12c5d1SDavid du Colombier 	if(c == 'x' || c == 'X')
7793e12c5d1SDavid du Colombier 		for(;;) {
7803e12c5d1SDavid du Colombier 			*cp++ = c;
7813e12c5d1SDavid du Colombier 			c = GETC();
7823e12c5d1SDavid du Colombier 			if(isdigit(c))
7833e12c5d1SDavid du Colombier 				continue;
7843e12c5d1SDavid du Colombier 			if(c >= 'a' && c <= 'f')
7853e12c5d1SDavid du Colombier 				continue;
7863e12c5d1SDavid du Colombier 			if(c >= 'A' && c <= 'F')
7873e12c5d1SDavid du Colombier 				continue;
7883e12c5d1SDavid du Colombier 			if(cp == symb+2)
7893e12c5d1SDavid du Colombier 				yyerror("malformed hex constant");
7903e12c5d1SDavid du Colombier 			goto ncu;
7913e12c5d1SDavid du Colombier 		}
7923e12c5d1SDavid du Colombier 	if(c < '0' || c > '7')
7933e12c5d1SDavid du Colombier 		goto dc;
7943e12c5d1SDavid du Colombier 	for(;;) {
7953e12c5d1SDavid du Colombier 		if(c >= '0' && c <= '7') {
7963e12c5d1SDavid du Colombier 			*cp++ = c;
7973e12c5d1SDavid du Colombier 			c = GETC();
7983e12c5d1SDavid du Colombier 			continue;
7993e12c5d1SDavid du Colombier 		}
8003e12c5d1SDavid du Colombier 		goto ncu;
8013e12c5d1SDavid du Colombier 	}
8023e12c5d1SDavid du Colombier 
8033e12c5d1SDavid du Colombier dc:
8043e12c5d1SDavid du Colombier 	if(c == '.')
8053e12c5d1SDavid du Colombier 		goto casedot;
8063e12c5d1SDavid du Colombier 	if(c == 'e' || c == 'E')
8073e12c5d1SDavid du Colombier 		goto casee;
8083e12c5d1SDavid du Colombier 
8093e12c5d1SDavid du Colombier ncu:
8107dd7cddfSDavid du Colombier 	if((c == 'U' || c == 'u') && !(c1 & Numuns)) {
8113e12c5d1SDavid du Colombier 		c = GETC();
8123e12c5d1SDavid du Colombier 		c1 |= Numuns;
8137dd7cddfSDavid du Colombier 		goto ncu;
8143e12c5d1SDavid du Colombier 	}
8157dd7cddfSDavid du Colombier 	if((c == 'L' || c == 'l') && !(c1 & Numvlong)) {
8163e12c5d1SDavid du Colombier 		c = GETC();
8177dd7cddfSDavid du Colombier 		if(c1 & Numlong)
8183e12c5d1SDavid du Colombier 			c1 |= Numvlong;
8197dd7cddfSDavid du Colombier 		c1 |= Numlong;
8207dd7cddfSDavid du Colombier 		goto ncu;
8213e12c5d1SDavid du Colombier 	}
8227dd7cddfSDavid du Colombier 	*cp = 0;
8233e12c5d1SDavid du Colombier 	peekc = c;
824219b2ee8SDavid du Colombier 	if(mpatov(symb, &yylval.vval))
825219b2ee8SDavid du Colombier 		yyerror("overflow in constant");
826219b2ee8SDavid du Colombier 
82722a127bbSDavid du Colombier 	vv = yylval.vval;
8283e12c5d1SDavid du Colombier 	if(c1 & Numvlong) {
82922a127bbSDavid du Colombier 		if((c1 & Numuns) || convvtox(vv, TVLONG) < 0) {
830219b2ee8SDavid du Colombier 			c = LUVLCONST;
83122a127bbSDavid du Colombier 			t = TUVLONG;
8323e12c5d1SDavid du Colombier 			goto nret;
8333e12c5d1SDavid du Colombier 		}
834219b2ee8SDavid du Colombier 		c = LVLCONST;
83522a127bbSDavid du Colombier 		t = TVLONG;
836219b2ee8SDavid du Colombier 		goto nret;
837219b2ee8SDavid du Colombier 	}
8383e12c5d1SDavid du Colombier 	if(c1 & Numlong) {
83922a127bbSDavid du Colombier 		if((c1 & Numuns) || convvtox(vv, TLONG) < 0) {
840219b2ee8SDavid du Colombier 			c = LULCONST;
84122a127bbSDavid du Colombier 			t = TULONG;
842219b2ee8SDavid du Colombier 			goto nret;
8433e12c5d1SDavid du Colombier 		}
844219b2ee8SDavid du Colombier 		c = LLCONST;
84522a127bbSDavid du Colombier 		t = TLONG;
8463e12c5d1SDavid du Colombier 		goto nret;
847219b2ee8SDavid du Colombier 	}
84822a127bbSDavid du Colombier 	if((c1 & Numuns) || convvtox(vv, TINT) < 0) {
849219b2ee8SDavid du Colombier 		c = LUCONST;
85022a127bbSDavid du Colombier 		t = TUINT;
8513e12c5d1SDavid du Colombier 		goto nret;
852219b2ee8SDavid du Colombier 	}
853219b2ee8SDavid du Colombier 	c = LCONST;
85422a127bbSDavid du Colombier 	t = TINT;
855219b2ee8SDavid du Colombier 	goto nret;
856219b2ee8SDavid du Colombier 
857219b2ee8SDavid du Colombier nret:
85822a127bbSDavid du Colombier 	yylval.vval = convvtox(vv, t);
85922a127bbSDavid du Colombier 	if(yylval.vval != vv){
86022a127bbSDavid du Colombier 		nearln = lineno;
86122a127bbSDavid du Colombier 		warn(Z, "truncated constant: %T %s", types[t], symb);
86222a127bbSDavid du Colombier 	}
863219b2ee8SDavid du Colombier 	return c;
8643e12c5d1SDavid du Colombier 
8653e12c5d1SDavid du Colombier casedot:
8663e12c5d1SDavid du Colombier 	for(;;) {
8673e12c5d1SDavid du Colombier 		*cp++ = c;
8683e12c5d1SDavid du Colombier 		c = GETC();
8693e12c5d1SDavid du Colombier 		if(!isdigit(c))
8703e12c5d1SDavid du Colombier 			break;
8713e12c5d1SDavid du Colombier 	}
8723e12c5d1SDavid du Colombier 	if(c != 'e' && c != 'E')
8733e12c5d1SDavid du Colombier 		goto caseout;
8743e12c5d1SDavid du Colombier 
8753e12c5d1SDavid du Colombier casee:
8763e12c5d1SDavid du Colombier 	*cp++ = 'e';
8773e12c5d1SDavid du Colombier 	c = GETC();
8783e12c5d1SDavid du Colombier 	if(c == '+' || c == '-') {
8793e12c5d1SDavid du Colombier 		*cp++ = c;
8803e12c5d1SDavid du Colombier 		c = GETC();
8813e12c5d1SDavid du Colombier 	}
8823e12c5d1SDavid du Colombier 	if(!isdigit(c))
8833e12c5d1SDavid du Colombier 		yyerror("malformed fp constant exponent");
8843e12c5d1SDavid du Colombier 	while(isdigit(c)) {
8853e12c5d1SDavid du Colombier 		*cp++ = c;
8863e12c5d1SDavid du Colombier 		c = GETC();
8873e12c5d1SDavid du Colombier 	}
8883e12c5d1SDavid du Colombier 
8893e12c5d1SDavid du Colombier caseout:
8903e12c5d1SDavid du Colombier 	if(c == 'L' || c == 'l') {
8913e12c5d1SDavid du Colombier 		c = GETC();
8923e12c5d1SDavid du Colombier 		c1 |= Numlong;
8933e12c5d1SDavid du Colombier 	} else
8943e12c5d1SDavid du Colombier 	if(c == 'F' || c == 'f') {
8953e12c5d1SDavid du Colombier 		c = GETC();
8963e12c5d1SDavid du Colombier 		c1 |= Numflt;
8973e12c5d1SDavid du Colombier 	}
8983e12c5d1SDavid du Colombier 	*cp = 0;
8993e12c5d1SDavid du Colombier 	peekc = c;
90059cc4ca5SDavid du Colombier 	yylval.dval = strtod(symb, nil);
90159cc4ca5SDavid du Colombier 	if(isInf(yylval.dval, 1) || isInf(yylval.dval, -1)) {
9023e12c5d1SDavid du Colombier 		yyerror("overflow in float constant");
9033e12c5d1SDavid du Colombier 		yylval.dval = 0;
9043e12c5d1SDavid du Colombier 	}
9053e12c5d1SDavid du Colombier 	if(c1 & Numflt)
9063e12c5d1SDavid du Colombier 		return LFCONST;
9073e12c5d1SDavid du Colombier 	return LDCONST;
9083e12c5d1SDavid du Colombier }
9093e12c5d1SDavid du Colombier 
91059cc4ca5SDavid du Colombier /*
91159cc4ca5SDavid du Colombier  * convert a string, s, to vlong in *v
91259cc4ca5SDavid du Colombier  * return conversion overflow.
91359cc4ca5SDavid du Colombier  * required syntax is [0[x]]d*
91459cc4ca5SDavid du Colombier  */
91559cc4ca5SDavid du Colombier int
mpatov(char * s,vlong * v)91659cc4ca5SDavid du Colombier mpatov(char *s, vlong *v)
91759cc4ca5SDavid du Colombier {
91859cc4ca5SDavid du Colombier 	vlong n, nn;
91959cc4ca5SDavid du Colombier 	int c;
92059cc4ca5SDavid du Colombier 
92159cc4ca5SDavid du Colombier 	n = 0;
92259cc4ca5SDavid du Colombier 	c = *s;
92359cc4ca5SDavid du Colombier 	if(c == '0')
92459cc4ca5SDavid du Colombier 		goto oct;
92559cc4ca5SDavid du Colombier 	while(c = *s++) {
92659cc4ca5SDavid du Colombier 		if(c >= '0' && c <= '9')
92759cc4ca5SDavid du Colombier 			nn = n*10 + c-'0';
92859cc4ca5SDavid du Colombier 		else
92959cc4ca5SDavid du Colombier 			goto bad;
93059cc4ca5SDavid du Colombier 		if(n < 0 && nn >= 0)
93159cc4ca5SDavid du Colombier 			goto bad;
93259cc4ca5SDavid du Colombier 		n = nn;
93359cc4ca5SDavid du Colombier 	}
93459cc4ca5SDavid du Colombier 	goto out;
93559cc4ca5SDavid du Colombier 
93659cc4ca5SDavid du Colombier oct:
93759cc4ca5SDavid du Colombier 	s++;
93859cc4ca5SDavid du Colombier 	c = *s;
93959cc4ca5SDavid du Colombier 	if(c == 'x' || c == 'X')
94059cc4ca5SDavid du Colombier 		goto hex;
94159cc4ca5SDavid du Colombier 	while(c = *s++) {
94259cc4ca5SDavid du Colombier 		if(c >= '0' || c <= '7')
94359cc4ca5SDavid du Colombier 			nn = n*8 + c-'0';
94459cc4ca5SDavid du Colombier 		else
94559cc4ca5SDavid du Colombier 			goto bad;
94659cc4ca5SDavid du Colombier 		if(n < 0 && nn >= 0)
94759cc4ca5SDavid du Colombier 			goto bad;
94859cc4ca5SDavid du Colombier 		n = nn;
94959cc4ca5SDavid du Colombier 	}
95059cc4ca5SDavid du Colombier 	goto out;
95159cc4ca5SDavid du Colombier 
95259cc4ca5SDavid du Colombier hex:
95359cc4ca5SDavid du Colombier 	s++;
95459cc4ca5SDavid du Colombier 	while(c = *s++) {
95559cc4ca5SDavid du Colombier 		if(c >= '0' && c <= '9')
95659cc4ca5SDavid du Colombier 			c += 0-'0';
95759cc4ca5SDavid du Colombier 		else
95859cc4ca5SDavid du Colombier 		if(c >= 'a' && c <= 'f')
95959cc4ca5SDavid du Colombier 			c += 10-'a';
96059cc4ca5SDavid du Colombier 		else
96159cc4ca5SDavid du Colombier 		if(c >= 'A' && c <= 'F')
96259cc4ca5SDavid du Colombier 			c += 10-'A';
96359cc4ca5SDavid du Colombier 		else
96459cc4ca5SDavid du Colombier 			goto bad;
96559cc4ca5SDavid du Colombier 		nn = n*16 + c;
96659cc4ca5SDavid du Colombier 		if(n < 0 && nn >= 0)
96759cc4ca5SDavid du Colombier 			goto bad;
96859cc4ca5SDavid du Colombier 		n = nn;
96959cc4ca5SDavid du Colombier 	}
97059cc4ca5SDavid du Colombier out:
97159cc4ca5SDavid du Colombier 	*v = n;
97259cc4ca5SDavid du Colombier 	return 0;
97359cc4ca5SDavid du Colombier 
97459cc4ca5SDavid du Colombier bad:
97559cc4ca5SDavid du Colombier 	*v = ~0;
97659cc4ca5SDavid du Colombier 	return 1;
97759cc4ca5SDavid du Colombier }
97859cc4ca5SDavid du Colombier 
9793e12c5d1SDavid du Colombier int
getc(void)9803e12c5d1SDavid du Colombier getc(void)
9813e12c5d1SDavid du Colombier {
9823e12c5d1SDavid du Colombier 	int c;
9833e12c5d1SDavid du Colombier 
9843e12c5d1SDavid du Colombier 	if(peekc != IGN) {
9853e12c5d1SDavid du Colombier 		c = peekc;
9863e12c5d1SDavid du Colombier 		peekc = IGN;
9873e12c5d1SDavid du Colombier 	} else
9883e12c5d1SDavid du Colombier 		c = GETC();
9893e12c5d1SDavid du Colombier 	if(c == '\n')
9903e12c5d1SDavid du Colombier 		lineno++;
9913e12c5d1SDavid du Colombier 	if(c == EOF) {
9923e12c5d1SDavid du Colombier 		yyerror("End of file");
9933e12c5d1SDavid du Colombier 		errorexit();
9943e12c5d1SDavid du Colombier 	}
9953e12c5d1SDavid du Colombier 	return c;
9963e12c5d1SDavid du Colombier }
9973e12c5d1SDavid du Colombier 
9983e12c5d1SDavid du Colombier long
getr(void)9993e12c5d1SDavid du Colombier getr(void)
10003e12c5d1SDavid du Colombier {
10013e12c5d1SDavid du Colombier 	int c, i;
10023e12c5d1SDavid du Colombier 	char str[UTFmax+1];
10033e12c5d1SDavid du Colombier 	Rune rune;
10043e12c5d1SDavid du Colombier 
10053e12c5d1SDavid du Colombier 
10063e12c5d1SDavid du Colombier 	c = getc();
10073e12c5d1SDavid du Colombier 	if(c < Runeself)
10083e12c5d1SDavid du Colombier 		return c;
10093e12c5d1SDavid du Colombier 	i = 0;
10103e12c5d1SDavid du Colombier 	str[i++] = c;
10113e12c5d1SDavid du Colombier 
10123e12c5d1SDavid du Colombier loop:
10133e12c5d1SDavid du Colombier 	c = getc();
10143e12c5d1SDavid du Colombier 	str[i++] = c;
10153e12c5d1SDavid du Colombier 	if(!fullrune(str, i))
10163e12c5d1SDavid du Colombier 		goto loop;
10173e12c5d1SDavid du Colombier 	c = chartorune(&rune, str);
10183e12c5d1SDavid du Colombier 	if(rune == Runeerror && c == 1) {
10193e12c5d1SDavid du Colombier 		nearln = lineno;
10203e12c5d1SDavid du Colombier 		diag(Z, "illegal rune in string");
10213e12c5d1SDavid du Colombier 		for(c=0; c<i; c++)
10223e12c5d1SDavid du Colombier 			print(" %.2x", *(uchar*)(str+c));
10233e12c5d1SDavid du Colombier 		print("\n");
10243e12c5d1SDavid du Colombier 	}
10253e12c5d1SDavid du Colombier 	return rune;
10263e12c5d1SDavid du Colombier }
10273e12c5d1SDavid du Colombier 
10283e12c5d1SDavid du Colombier int
getnsc(void)10293e12c5d1SDavid du Colombier getnsc(void)
10303e12c5d1SDavid du Colombier {
10313e12c5d1SDavid du Colombier 	int c;
10323e12c5d1SDavid du Colombier 
10333e12c5d1SDavid du Colombier 	if(peekc != IGN) {
10343e12c5d1SDavid du Colombier 		c = peekc;
10353e12c5d1SDavid du Colombier 		peekc = IGN;
10363e12c5d1SDavid du Colombier 	} else
10373e12c5d1SDavid du Colombier 		c = GETC();
10383e12c5d1SDavid du Colombier 	for(;;) {
103982726826SDavid du Colombier 		if(c >= Runeself || !isspace(c))
10403e12c5d1SDavid du Colombier 			return c;
10413e12c5d1SDavid du Colombier 		if(c == '\n') {
10423e12c5d1SDavid du Colombier 			lineno++;
10433e12c5d1SDavid du Colombier 			return c;
10443e12c5d1SDavid du Colombier 		}
10453e12c5d1SDavid du Colombier 		c = GETC();
10463e12c5d1SDavid du Colombier 	}
10473e12c5d1SDavid du Colombier }
10483e12c5d1SDavid du Colombier 
10493e12c5d1SDavid du Colombier void
unget(int c)10503e12c5d1SDavid du Colombier unget(int c)
10513e12c5d1SDavid du Colombier {
10523e12c5d1SDavid du Colombier 
10533e12c5d1SDavid du Colombier 	peekc = c;
10543e12c5d1SDavid du Colombier 	if(c == '\n')
10553e12c5d1SDavid du Colombier 		lineno--;
10563e12c5d1SDavid du Colombier }
10573e12c5d1SDavid du Colombier 
10583e12c5d1SDavid du Colombier long
escchar(long e,int longflg,int escflg)10593e12c5d1SDavid du Colombier escchar(long e, int longflg, int escflg)
10603e12c5d1SDavid du Colombier {
10613e12c5d1SDavid du Colombier 	long c, l;
10623e12c5d1SDavid du Colombier 	int i;
10633e12c5d1SDavid du Colombier 
10643e12c5d1SDavid du Colombier loop:
10653e12c5d1SDavid du Colombier 	c = getr();
10663e12c5d1SDavid du Colombier 	if(c == '\n') {
10673e12c5d1SDavid du Colombier 		yyerror("newline in string");
10683e12c5d1SDavid du Colombier 		return EOF;
10693e12c5d1SDavid du Colombier 	}
10703e12c5d1SDavid du Colombier 	if(c != '\\') {
10713e12c5d1SDavid du Colombier 		if(c == e)
10723e12c5d1SDavid du Colombier 			c = EOF;
10733e12c5d1SDavid du Colombier 		return c;
10743e12c5d1SDavid du Colombier 	}
10753e12c5d1SDavid du Colombier 	c = getr();
10763e12c5d1SDavid du Colombier 	if(c == 'x') {
10773e12c5d1SDavid du Colombier 		/*
10783e12c5d1SDavid du Colombier 		 * note this is not ansi,
10793e12c5d1SDavid du Colombier 		 * supposed to only accept 2 hex
10803e12c5d1SDavid du Colombier 		 */
10813e12c5d1SDavid du Colombier 		i = 2;
10823e12c5d1SDavid du Colombier 		if(longflg)
1083e94a8e9bSDavid du Colombier 			i = 6;
10843e12c5d1SDavid du Colombier 		l = 0;
10853e12c5d1SDavid du Colombier 		for(; i>0; i--) {
10863e12c5d1SDavid du Colombier 			c = getc();
1087219b2ee8SDavid du Colombier 			if(c >= '0' && c <= '9') {
10883e12c5d1SDavid du Colombier 				l = l*16 + c-'0';
10893e12c5d1SDavid du Colombier 				continue;
10903e12c5d1SDavid du Colombier 			}
10913e12c5d1SDavid du Colombier 			if(c >= 'a' && c <= 'f') {
10923e12c5d1SDavid du Colombier 				l = l*16 + c-'a' + 10;
10933e12c5d1SDavid du Colombier 				continue;
10943e12c5d1SDavid du Colombier 			}
10953e12c5d1SDavid du Colombier 			if(c >= 'A' && c <= 'F') {
10963e12c5d1SDavid du Colombier 				l = l*16 + c-'A' + 10;
10973e12c5d1SDavid du Colombier 				continue;
10983e12c5d1SDavid du Colombier 			}
10993e12c5d1SDavid du Colombier 			unget(c);
11003e12c5d1SDavid du Colombier 			break;
11013e12c5d1SDavid du Colombier 		}
11023e12c5d1SDavid du Colombier 		if(escflg)
11033e12c5d1SDavid du Colombier 			l |= ESC;
11043e12c5d1SDavid du Colombier 		return l;
11053e12c5d1SDavid du Colombier 	}
11063e12c5d1SDavid du Colombier 	if(c >= '0' && c <= '7') {
11073e12c5d1SDavid du Colombier 		/*
11083e12c5d1SDavid du Colombier 		 * note this is not ansi,
11093e12c5d1SDavid du Colombier 		 * supposed to only accept 3 oct
11103e12c5d1SDavid du Colombier 		 */
11113e12c5d1SDavid du Colombier 		i = 2;
11123e12c5d1SDavid du Colombier 		if(longflg)
1113e94a8e9bSDavid du Colombier 			i = 8;
11143e12c5d1SDavid du Colombier 		l = c - '0';
11153e12c5d1SDavid du Colombier 		for(; i>0; i--) {
11163e12c5d1SDavid du Colombier 			c = getc();
11173e12c5d1SDavid du Colombier 			if(c >= '0' && c <= '7') {
11183e12c5d1SDavid du Colombier 				l = l*8 + c-'0';
11193e12c5d1SDavid du Colombier 				continue;
11203e12c5d1SDavid du Colombier 			}
11213e12c5d1SDavid du Colombier 			unget(c);
11223e12c5d1SDavid du Colombier 		}
11233e12c5d1SDavid du Colombier 		if(escflg)
11243e12c5d1SDavid du Colombier 			l |= ESC;
11253e12c5d1SDavid du Colombier 		return l;
11263e12c5d1SDavid du Colombier 	}
11273e12c5d1SDavid du Colombier 	switch(c)
11283e12c5d1SDavid du Colombier 	{
11293e12c5d1SDavid du Colombier 	case '\n':	goto loop;
11303e12c5d1SDavid du Colombier 	case 'n':	return '\n';
11313e12c5d1SDavid du Colombier 	case 't':	return '\t';
11323e12c5d1SDavid du Colombier 	case 'b':	return '\b';
11333e12c5d1SDavid du Colombier 	case 'r':	return '\r';
11343e12c5d1SDavid du Colombier 	case 'f':	return '\f';
11353e12c5d1SDavid du Colombier 	case 'a':	return '\a';
11363e12c5d1SDavid du Colombier 	case 'v':	return '\v';
11373e12c5d1SDavid du Colombier 	}
11383e12c5d1SDavid du Colombier 	return c;
11393e12c5d1SDavid du Colombier }
11403e12c5d1SDavid du Colombier 
11413e12c5d1SDavid du Colombier struct
11423e12c5d1SDavid du Colombier {
11433e12c5d1SDavid du Colombier 	char	*name;
11443e12c5d1SDavid du Colombier 	ushort	lexical;
11457dd7cddfSDavid du Colombier 	ushort	type;
11463e12c5d1SDavid du Colombier } itab[] =
11473e12c5d1SDavid du Colombier {
11487dd7cddfSDavid du Colombier 	"auto",		LAUTO,		0,
11497dd7cddfSDavid du Colombier 	"break",	LBREAK,		0,
11507dd7cddfSDavid du Colombier 	"case",		LCASE,		0,
11517dd7cddfSDavid du Colombier 	"char",		LCHAR,		TCHAR,
11527dd7cddfSDavid du Colombier 	"const",	LCONSTNT,	0,
11537dd7cddfSDavid du Colombier 	"continue",	LCONTINUE,	0,
11547dd7cddfSDavid du Colombier 	"default",	LDEFAULT,	0,
11557dd7cddfSDavid du Colombier 	"do",		LDO,		0,
11567dd7cddfSDavid du Colombier 	"double",	LDOUBLE,	TDOUBLE,
11577dd7cddfSDavid du Colombier 	"else",		LELSE,		0,
11587dd7cddfSDavid du Colombier 	"enum",		LENUM,		0,
11597dd7cddfSDavid du Colombier 	"extern",	LEXTERN,	0,
11607dd7cddfSDavid du Colombier 	"float",	LFLOAT,		TFLOAT,
11617dd7cddfSDavid du Colombier 	"for",		LFOR,		0,
11627dd7cddfSDavid du Colombier 	"goto",		LGOTO,		0,
11637dd7cddfSDavid du Colombier 	"if",		LIF,		0,
11644bada075SDavid du Colombier 	"inline",	LINLINE,	0,
11657dd7cddfSDavid du Colombier 	"int",		LINT,		TINT,
11667dd7cddfSDavid du Colombier 	"long",		LLONG,		TLONG,
11677dd7cddfSDavid du Colombier 	"register",	LREGISTER,	0,
11684bada075SDavid du Colombier 	"restrict",	LRESTRICT,	0,
11697dd7cddfSDavid du Colombier 	"return",	LRETURN,	0,
11707dd7cddfSDavid du Colombier 	"SET",		LSET,		0,
11717dd7cddfSDavid du Colombier 	"short",	LSHORT,		TSHORT,
11727dd7cddfSDavid du Colombier 	"signed",	LSIGNED,	0,
11737dd7cddfSDavid du Colombier 	"signof",	LSIGNOF,	0,
11747dd7cddfSDavid du Colombier 	"sizeof",	LSIZEOF,	0,
11757dd7cddfSDavid du Colombier 	"static",	LSTATIC,	0,
11767dd7cddfSDavid du Colombier 	"struct",	LSTRUCT,	0,
11777dd7cddfSDavid du Colombier 	"switch",	LSWITCH,	0,
11787dd7cddfSDavid du Colombier 	"typedef",	LTYPEDEF,	0,
117980ee5cbfSDavid du Colombier 	"typestr",	LTYPESTR,	0,
11807dd7cddfSDavid du Colombier 	"union",	LUNION,		0,
11817dd7cddfSDavid du Colombier 	"unsigned",	LUNSIGNED,	0,
11827dd7cddfSDavid du Colombier 	"USED",		LUSED,		0,
11837dd7cddfSDavid du Colombier 	"void",		LVOID,		TVOID,
11847dd7cddfSDavid du Colombier 	"volatile",	LVOLATILE,	0,
11857dd7cddfSDavid du Colombier 	"while",	LWHILE,		0,
11863e12c5d1SDavid du Colombier 	0
11873e12c5d1SDavid du Colombier };
11883e12c5d1SDavid du Colombier 
11893e12c5d1SDavid du Colombier void
cinit(void)11903e12c5d1SDavid du Colombier cinit(void)
11913e12c5d1SDavid du Colombier {
11923e12c5d1SDavid du Colombier 	Sym *s;
11933e12c5d1SDavid du Colombier 	int i;
11943e12c5d1SDavid du Colombier 	Type *t;
11953e12c5d1SDavid du Colombier 
11963e12c5d1SDavid du Colombier 	nerrors = 0;
11973e12c5d1SDavid du Colombier 	lineno = 1;
11983e12c5d1SDavid du Colombier 	iostack = I;
11993e12c5d1SDavid du Colombier 	iofree = I;
12003e12c5d1SDavid du Colombier 	peekc = IGN;
12013e12c5d1SDavid du Colombier 	nhunk = 0;
12023e12c5d1SDavid du Colombier 
12033e12c5d1SDavid du Colombier 	types[TXXX] = T;
12043e12c5d1SDavid du Colombier 	types[TCHAR] = typ(TCHAR, T);
12053e12c5d1SDavid du Colombier 	types[TUCHAR] = typ(TUCHAR, T);
12063e12c5d1SDavid du Colombier 	types[TSHORT] = typ(TSHORT, T);
12073e12c5d1SDavid du Colombier 	types[TUSHORT] = typ(TUSHORT, T);
12087dd7cddfSDavid du Colombier 	types[TINT] = typ(TINT, T);
12097dd7cddfSDavid du Colombier 	types[TUINT] = typ(TUINT, T);
12103e12c5d1SDavid du Colombier 	types[TLONG] = typ(TLONG, T);
12113e12c5d1SDavid du Colombier 	types[TULONG] = typ(TULONG, T);
12123e12c5d1SDavid du Colombier 	types[TVLONG] = typ(TVLONG, T);
1213219b2ee8SDavid du Colombier 	types[TUVLONG] = typ(TUVLONG, T);
12143e12c5d1SDavid du Colombier 	types[TFLOAT] = typ(TFLOAT, T);
12153e12c5d1SDavid du Colombier 	types[TDOUBLE] = typ(TDOUBLE, T);
12163e12c5d1SDavid du Colombier 	types[TVOID] = typ(TVOID, T);
12173e12c5d1SDavid du Colombier 	types[TENUM] = typ(TENUM, T);
12187dd7cddfSDavid du Colombier 	types[TFUNC] = typ(TFUNC, types[TINT]);
12193e12c5d1SDavid du Colombier 	types[TIND] = typ(TIND, types[TVOID]);
12203e12c5d1SDavid du Colombier 
12217dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++)
12227dd7cddfSDavid du Colombier 		hash[i] = S;
12237dd7cddfSDavid du Colombier 	for(i=0; itab[i].name; i++) {
12247dd7cddfSDavid du Colombier 		s = slookup(itab[i].name);
12257dd7cddfSDavid du Colombier 		s->lexical = itab[i].lexical;
12267dd7cddfSDavid du Colombier 		if(itab[i].type != 0)
12277dd7cddfSDavid du Colombier 			s->type = types[itab[i].type];
12287dd7cddfSDavid du Colombier 	}
12297dd7cddfSDavid du Colombier 	blockno = 0;
12307dd7cddfSDavid du Colombier 	autobn = 0;
12317dd7cddfSDavid du Colombier 	autoffset = 0;
12323e12c5d1SDavid du Colombier 
12333e12c5d1SDavid du Colombier 	t = typ(TARRAY, types[TCHAR]);
12343e12c5d1SDavid du Colombier 	t->width = 0;
12353e12c5d1SDavid du Colombier 	symstring = slookup(".string");
12363e12c5d1SDavid du Colombier 	symstring->class = CSTATIC;
12373e12c5d1SDavid du Colombier 	symstring->type = t;
12383e12c5d1SDavid du Colombier 
12393e12c5d1SDavid du Colombier 	t = typ(TARRAY, types[TCHAR]);
12403e12c5d1SDavid du Colombier 	t->width = 0;
12413e12c5d1SDavid du Colombier 
12423e12c5d1SDavid du Colombier 	nodproto = new(OPROTO, Z, Z);
12433e12c5d1SDavid du Colombier 	dclstack = D;
12443e12c5d1SDavid du Colombier 
12457dd7cddfSDavid du Colombier 	pathname = allocn(pathname, 0, 100);
12467dd7cddfSDavid du Colombier 	if(mygetwd(pathname, 99) == 0) {
12477dd7cddfSDavid du Colombier 		pathname = allocn(pathname, 100, 900);
12487dd7cddfSDavid du Colombier 		if(mygetwd(pathname, 999) == 0)
1249219b2ee8SDavid du Colombier 			strcpy(pathname, "/???");
1250219b2ee8SDavid du Colombier 	}
1251219b2ee8SDavid du Colombier 
12523e12c5d1SDavid du Colombier 	fmtinstall('O', Oconv);
12533e12c5d1SDavid du Colombier 	fmtinstall('T', Tconv);
1254bd389b36SDavid du Colombier 	fmtinstall('F', FNconv);
12553e12c5d1SDavid du Colombier 	fmtinstall('L', Lconv);
12563e12c5d1SDavid du Colombier 	fmtinstall('Q', Qconv);
12573e12c5d1SDavid du Colombier 	fmtinstall('|', VBconv);
12583e12c5d1SDavid du Colombier }
12593e12c5d1SDavid du Colombier 
12603e12c5d1SDavid du Colombier int
filbuf(void)12613e12c5d1SDavid du Colombier filbuf(void)
12623e12c5d1SDavid du Colombier {
12633e12c5d1SDavid du Colombier 	Io *i;
12643e12c5d1SDavid du Colombier 
12653e12c5d1SDavid du Colombier loop:
12663e12c5d1SDavid du Colombier 	i = iostack;
12673e12c5d1SDavid du Colombier 	if(i == I)
12683e12c5d1SDavid du Colombier 		return EOF;
12693e12c5d1SDavid du Colombier 	if(i->f < 0)
12703e12c5d1SDavid du Colombier 		goto pop;
12713e12c5d1SDavid du Colombier 	fi.c = read(i->f, i->b, BUFSIZ) - 1;
12723e12c5d1SDavid du Colombier 	if(fi.c < 0) {
12733e12c5d1SDavid du Colombier 		close(i->f);
12743e12c5d1SDavid du Colombier 		linehist(0, 0);
12753e12c5d1SDavid du Colombier 		goto pop;
12763e12c5d1SDavid du Colombier 	}
12773e12c5d1SDavid du Colombier 	fi.p = i->b + 1;
12783e12c5d1SDavid du Colombier 	return i->b[0] & 0xff;
12793e12c5d1SDavid du Colombier 
12803e12c5d1SDavid du Colombier pop:
12813e12c5d1SDavid du Colombier 	iostack = i->link;
12823e12c5d1SDavid du Colombier 	i->link = iofree;
12833e12c5d1SDavid du Colombier 	iofree = i;
12843e12c5d1SDavid du Colombier 	i = iostack;
12853e12c5d1SDavid du Colombier 	if(i == I)
12863e12c5d1SDavid du Colombier 		return EOF;
12873e12c5d1SDavid du Colombier 	fi.p = i->p;
12883e12c5d1SDavid du Colombier 	fi.c = i->c;
12893e12c5d1SDavid du Colombier 	if(--fi.c < 0)
12903e12c5d1SDavid du Colombier 		goto loop;
12913e12c5d1SDavid du Colombier 	return *fi.p++ & 0xff;
12923e12c5d1SDavid du Colombier }
12933e12c5d1SDavid du Colombier 
12943e12c5d1SDavid du Colombier int
Oconv(Fmt * fp)12959a747e4fSDavid du Colombier Oconv(Fmt *fp)
12963e12c5d1SDavid du Colombier {
12973e12c5d1SDavid du Colombier 	int a;
12983e12c5d1SDavid du Colombier 
12999a747e4fSDavid du Colombier 	a = va_arg(fp->args, int);
13009a747e4fSDavid du Colombier 	if(a < OXXX || a > OEND)
13019a747e4fSDavid du Colombier 		return fmtprint(fp, "***badO %d***", a);
13029a747e4fSDavid du Colombier 
13039a747e4fSDavid du Colombier 	return fmtstrcpy(fp, onames[a]);
13043e12c5d1SDavid du Colombier }
13053e12c5d1SDavid du Colombier 
13063e12c5d1SDavid du Colombier int
Lconv(Fmt * fp)13079a747e4fSDavid du Colombier Lconv(Fmt *fp)
13083e12c5d1SDavid du Colombier {
13093e12c5d1SDavid du Colombier 	char str[STRINGSZ], s[STRINGSZ];
13103e12c5d1SDavid du Colombier 	Hist *h;
13113e12c5d1SDavid du Colombier 	struct
13123e12c5d1SDavid du Colombier 	{
13133e12c5d1SDavid du Colombier 		Hist*	incl;	/* start of this include file */
13143e12c5d1SDavid du Colombier 		long	idel;	/* delta line number to apply to include */
13153e12c5d1SDavid du Colombier 		Hist*	line;	/* start of this #line directive */
13163e12c5d1SDavid du Colombier 		long	ldel;	/* delta line number to apply to #line */
13173e12c5d1SDavid du Colombier 	} a[HISTSZ];
13183e12c5d1SDavid du Colombier 	long l, d;
13193e12c5d1SDavid du Colombier 	int i, n;
13203e12c5d1SDavid du Colombier 
13219a747e4fSDavid du Colombier 	l = va_arg(fp->args, long);
13223e12c5d1SDavid du Colombier 	n = 0;
13233e12c5d1SDavid du Colombier 	for(h = hist; h != H; h = h->link) {
13243e12c5d1SDavid du Colombier 		if(l < h->line)
13253e12c5d1SDavid du Colombier 			break;
13263e12c5d1SDavid du Colombier 		if(h->name) {
13273e12c5d1SDavid du Colombier 			if(h->offset != 0) {		/* #line directive, not #pragma */
13283e12c5d1SDavid du Colombier 				if(n > 0 && n < HISTSZ && h->offset >= 0) {
13293e12c5d1SDavid du Colombier 					a[n-1].line = h;
13303e12c5d1SDavid du Colombier 					a[n-1].ldel = h->line - h->offset + 1;
13313e12c5d1SDavid du Colombier 				}
13323e12c5d1SDavid du Colombier 			} else {
13333e12c5d1SDavid du Colombier 				if(n < HISTSZ) {	/* beginning of file */
13343e12c5d1SDavid du Colombier 					a[n].incl = h;
13353e12c5d1SDavid du Colombier 					a[n].idel = h->line;
13363e12c5d1SDavid du Colombier 					a[n].line = 0;
13373e12c5d1SDavid du Colombier 				}
13383e12c5d1SDavid du Colombier 				n++;
13393e12c5d1SDavid du Colombier 			}
13403e12c5d1SDavid du Colombier 			continue;
13413e12c5d1SDavid du Colombier 		}
13423e12c5d1SDavid du Colombier 		n--;
13433e12c5d1SDavid du Colombier 		if(n > 0 && n < HISTSZ) {
13443e12c5d1SDavid du Colombier 			d = h->line - a[n].incl->line;
13453e12c5d1SDavid du Colombier 			a[n-1].ldel += d;
13463e12c5d1SDavid du Colombier 			a[n-1].idel += d;
13473e12c5d1SDavid du Colombier 		}
13483e12c5d1SDavid du Colombier 	}
13493e12c5d1SDavid du Colombier 	if(n > HISTSZ)
13503e12c5d1SDavid du Colombier 		n = HISTSZ;
13513e12c5d1SDavid du Colombier 	str[0] = 0;
13523e12c5d1SDavid du Colombier 	for(i=n-1; i>=0; i--) {
13533e12c5d1SDavid du Colombier 		if(i != n-1) {
13549a747e4fSDavid du Colombier 			if(fp->flags & ~(FmtWidth|FmtPrec))	/* BUG ROB - was f3 */
13553e12c5d1SDavid du Colombier 				break;
13563e12c5d1SDavid du Colombier 			strcat(str, " ");
13573e12c5d1SDavid du Colombier 		}
13583e12c5d1SDavid du Colombier 		if(a[i].line)
1359219b2ee8SDavid du Colombier 			snprint(s, STRINGSZ, "%s:%ld[%s:%ld]",
13603e12c5d1SDavid du Colombier 				a[i].line->name, l-a[i].ldel+1,
13613e12c5d1SDavid du Colombier 				a[i].incl->name, l-a[i].idel+1);
13623e12c5d1SDavid du Colombier 		else
1363219b2ee8SDavid du Colombier 			snprint(s, STRINGSZ, "%s:%ld",
13643e12c5d1SDavid du Colombier 				a[i].incl->name, l-a[i].idel+1);
13653e12c5d1SDavid du Colombier 		if(strlen(s)+strlen(str) >= STRINGSZ-10)
13663e12c5d1SDavid du Colombier 			break;
13673e12c5d1SDavid du Colombier 		strcat(str, s);
13683e12c5d1SDavid du Colombier 		l = a[i].incl->line - 1;	/* now print out start of this file */
13693e12c5d1SDavid du Colombier 	}
13703e12c5d1SDavid du Colombier 	if(n == 0)
13713e12c5d1SDavid du Colombier 		strcat(str, "<eof>");
13729a747e4fSDavid du Colombier 	return fmtstrcpy(fp, str);
13733e12c5d1SDavid du Colombier }
13743e12c5d1SDavid du Colombier 
13753e12c5d1SDavid du Colombier int
Tconv(Fmt * fp)13769a747e4fSDavid du Colombier Tconv(Fmt *fp)
13773e12c5d1SDavid du Colombier {
1378219b2ee8SDavid du Colombier 	char str[STRINGSZ+20], s[STRINGSZ+20];
13793e12c5d1SDavid du Colombier 	Type *t, *t1;
13803e12c5d1SDavid du Colombier 	int et;
13817dd7cddfSDavid du Colombier 	long n;
13823e12c5d1SDavid du Colombier 
13833e12c5d1SDavid du Colombier 	str[0] = 0;
13849a747e4fSDavid du Colombier 	for(t = va_arg(fp->args, Type*); t != T; t = t->link) {
13853e12c5d1SDavid du Colombier 		et = t->etype;
13863e12c5d1SDavid du Colombier 		if(str[0])
13873e12c5d1SDavid du Colombier 			strcat(str, " ");
1388375daca8SDavid du Colombier 		if(t->garb&~GINCOMPLETE) {
1389375daca8SDavid du Colombier 			sprint(s, "%s ", gnames[t->garb&~GINCOMPLETE]);
13907dd7cddfSDavid du Colombier 			if(strlen(str) + strlen(s) < STRINGSZ)
13917dd7cddfSDavid du Colombier 				strcat(str, s);
13927dd7cddfSDavid du Colombier 		}
13933e12c5d1SDavid du Colombier 		sprint(s, "%s", tnames[et]);
13943e12c5d1SDavid du Colombier 		if(strlen(str) + strlen(s) < STRINGSZ)
13953e12c5d1SDavid du Colombier 			strcat(str, s);
13963e12c5d1SDavid du Colombier 		if(et == TFUNC && (t1 = t->down)) {
13973e12c5d1SDavid du Colombier 			sprint(s, "(%T", t1);
1398219b2ee8SDavid du Colombier 			if(strlen(str) + strlen(s) < STRINGSZ)
13993e12c5d1SDavid du Colombier 				strcat(str, s);
14003e12c5d1SDavid du Colombier 			while(t1 = t1->down) {
14013e12c5d1SDavid du Colombier 				sprint(s, ", %T", t1);
1402219b2ee8SDavid du Colombier 				if(strlen(str) + strlen(s) < STRINGSZ)
14033e12c5d1SDavid du Colombier 					strcat(str, s);
14043e12c5d1SDavid du Colombier 			}
1405219b2ee8SDavid du Colombier 			if(strlen(str) + strlen(s) < STRINGSZ)
14063e12c5d1SDavid du Colombier 				strcat(str, ")");
14073e12c5d1SDavid du Colombier 		}
14083e12c5d1SDavid du Colombier 		if(et == TARRAY) {
14097dd7cddfSDavid du Colombier 			n = t->width;
14107dd7cddfSDavid du Colombier 			if(t->link && t->link->width)
14117dd7cddfSDavid du Colombier 				n /= t->link->width;
14127dd7cddfSDavid du Colombier 			sprint(s, "[%ld]", n);
1413219b2ee8SDavid du Colombier 			if(strlen(str) + strlen(s) < STRINGSZ)
14143e12c5d1SDavid du Colombier 				strcat(str, s);
14153e12c5d1SDavid du Colombier 		}
14163e12c5d1SDavid du Colombier 		if(t->nbits) {
14173e12c5d1SDavid du Colombier 			sprint(s, " %d:%d", t->shift, t->nbits);
14183e12c5d1SDavid du Colombier 			if(strlen(str) + strlen(s) < STRINGSZ)
14193e12c5d1SDavid du Colombier 				strcat(str, s);
14203e12c5d1SDavid du Colombier 		}
14213e12c5d1SDavid du Colombier 		if(typesu[et]) {
14223e12c5d1SDavid du Colombier 			if(t->tag) {
14233e12c5d1SDavid du Colombier 				strcat(str, " ");
1424219b2ee8SDavid du Colombier 				if(strlen(str) + strlen(t->tag->name) < STRINGSZ)
14253e12c5d1SDavid du Colombier 					strcat(str, t->tag->name);
14263e12c5d1SDavid du Colombier 			} else
14273e12c5d1SDavid du Colombier 				strcat(str, " {}");
14283e12c5d1SDavid du Colombier 			break;
14293e12c5d1SDavid du Colombier 		}
14303e12c5d1SDavid du Colombier 	}
14319a747e4fSDavid du Colombier 	return fmtstrcpy(fp, str);
14323e12c5d1SDavid du Colombier }
14333e12c5d1SDavid du Colombier 
14343e12c5d1SDavid du Colombier int
FNconv(Fmt * fp)14359a747e4fSDavid du Colombier FNconv(Fmt *fp)
14363e12c5d1SDavid du Colombier {
1437219b2ee8SDavid du Colombier 	char *str;
14383e12c5d1SDavid du Colombier 	Node *n;
14393e12c5d1SDavid du Colombier 
14409a747e4fSDavid du Colombier 	n = va_arg(fp->args, Node*);
1441219b2ee8SDavid du Colombier 	str = "<indirect>";
1442219b2ee8SDavid du Colombier 	if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM))
1443219b2ee8SDavid du Colombier 		str = n->sym->name;
14449a747e4fSDavid du Colombier 	return fmtstrcpy(fp, str);
14453e12c5d1SDavid du Colombier }
14463e12c5d1SDavid du Colombier 
14473e12c5d1SDavid du Colombier int
Qconv(Fmt * fp)14489a747e4fSDavid du Colombier Qconv(Fmt *fp)
14493e12c5d1SDavid du Colombier {
1450219b2ee8SDavid du Colombier 	char str[STRINGSZ+20], *s;
14513e12c5d1SDavid du Colombier 	long b;
14523e12c5d1SDavid du Colombier 	int i;
14533e12c5d1SDavid du Colombier 
14543e12c5d1SDavid du Colombier 	str[0] = 0;
14559a747e4fSDavid du Colombier 	for(b = va_arg(fp->args, long); b;) {
14563e12c5d1SDavid du Colombier 		i = bitno(b);
14573e12c5d1SDavid du Colombier 		if(str[0])
14583e12c5d1SDavid du Colombier 			strcat(str, " ");
14593e12c5d1SDavid du Colombier 		s = qnames[i];
1460219b2ee8SDavid du Colombier 		if(strlen(str) + strlen(s) >= STRINGSZ)
14613e12c5d1SDavid du Colombier 			break;
14623e12c5d1SDavid du Colombier 		strcat(str, s);
14633e12c5d1SDavid du Colombier 		b &= ~(1L << i);
14643e12c5d1SDavid du Colombier 	}
14659a747e4fSDavid du Colombier 	return fmtstrcpy(fp, str);
14663e12c5d1SDavid du Colombier }
14673e12c5d1SDavid du Colombier 
14683e12c5d1SDavid du Colombier int
VBconv(Fmt * fp)14699a747e4fSDavid du Colombier VBconv(Fmt *fp)
14703e12c5d1SDavid du Colombier {
14713e12c5d1SDavid du Colombier 	char str[STRINGSZ];
14723e12c5d1SDavid du Colombier 	int i, n, t, pc;
14733e12c5d1SDavid du Colombier 
14749a747e4fSDavid du Colombier 	n = va_arg(fp->args, int);
14759a747e4fSDavid du Colombier 	pc = 0;	/* BUG: was printcol */
14763e12c5d1SDavid du Colombier 	i = 0;
14773e12c5d1SDavid du Colombier 	while(pc < n) {
14789a747e4fSDavid du Colombier 		t = (pc+4) & ~3;
14793e12c5d1SDavid du Colombier 		if(t <= n) {
14803e12c5d1SDavid du Colombier 			str[i++] = '\t';
14813e12c5d1SDavid du Colombier 			pc = t;
14823e12c5d1SDavid du Colombier 			continue;
14833e12c5d1SDavid du Colombier 		}
14843e12c5d1SDavid du Colombier 		str[i++] = ' ';
14853e12c5d1SDavid du Colombier 		pc++;
14863e12c5d1SDavid du Colombier 	}
14873e12c5d1SDavid du Colombier 	str[i] = 0;
14889a747e4fSDavid du Colombier 
14899a747e4fSDavid du Colombier 	return fmtstrcpy(fp, str);
14903e12c5d1SDavid du Colombier }
14913e12c5d1SDavid du Colombier 
14923e12c5d1SDavid du Colombier /*
14937dd7cddfSDavid du Colombier  * real allocs
14943e12c5d1SDavid du Colombier  */
14953e12c5d1SDavid du Colombier void*
alloc(long n)14967dd7cddfSDavid du Colombier alloc(long n)
14973e12c5d1SDavid du Colombier {
14983e12c5d1SDavid du Colombier 	void *p;
14993e12c5d1SDavid du Colombier 
15004de34a7eSDavid du Colombier 	while((uintptr)hunk & MAXALIGN) {
15017dd7cddfSDavid du Colombier 		hunk++;
15027dd7cddfSDavid du Colombier 		nhunk--;
15037dd7cddfSDavid du Colombier 	}
15043e12c5d1SDavid du Colombier 	while(nhunk < n)
15053e12c5d1SDavid du Colombier 		gethunk();
15063e12c5d1SDavid du Colombier 	p = hunk;
15073e12c5d1SDavid du Colombier 	nhunk -= n;
15083e12c5d1SDavid du Colombier 	hunk += n;
15093e12c5d1SDavid du Colombier 	return p;
15103e12c5d1SDavid du Colombier }
15113e12c5d1SDavid du Colombier 
15123e12c5d1SDavid du Colombier void*
allocn(void * p,long on,long n)15137dd7cddfSDavid du Colombier allocn(void *p, long on, long n)
15143e12c5d1SDavid du Colombier {
15157dd7cddfSDavid du Colombier 	void *q;
15163e12c5d1SDavid du Colombier 
15177dd7cddfSDavid du Colombier 	q = (uchar*)p + on;
15187dd7cddfSDavid du Colombier 	if(q != hunk || nhunk < n) {
15197dd7cddfSDavid du Colombier 		while(nhunk < on+n)
15207dd7cddfSDavid du Colombier 			gethunk();
15217dd7cddfSDavid du Colombier 		memmove(hunk, p, on);
15227dd7cddfSDavid du Colombier 		p = hunk;
15237dd7cddfSDavid du Colombier 		hunk += on;
15247dd7cddfSDavid du Colombier 		nhunk -= on;
15257dd7cddfSDavid du Colombier 	}
15267dd7cddfSDavid du Colombier 	hunk += n;
15277dd7cddfSDavid du Colombier 	nhunk -= n;
15283e12c5d1SDavid du Colombier 	return p;
15293e12c5d1SDavid du Colombier }
15303e12c5d1SDavid du Colombier 
15317dd7cddfSDavid du Colombier void
setinclude(char * p)15327dd7cddfSDavid du Colombier setinclude(char *p)
15333e12c5d1SDavid du Colombier {
15347dd7cddfSDavid du Colombier 	int i;
1535*6bbfed0dSDavid du Colombier 	char *e, **np;
15363e12c5d1SDavid du Colombier 
15377dd7cddfSDavid du Colombier 	while(*p != 0) {
15387dd7cddfSDavid du Colombier 		e = strchr(p, ' ');
15397dd7cddfSDavid du Colombier 		if(e != 0)
15407dd7cddfSDavid du Colombier 			*e = '\0';
15417dd7cddfSDavid du Colombier 
1542*6bbfed0dSDavid du Colombier 		for(i=0; i < ninclude; i++)
15437dd7cddfSDavid du Colombier 			if(strcmp(p, include[i]) == 0)
15447dd7cddfSDavid du Colombier 				break;
15457dd7cddfSDavid du Colombier 
1546*6bbfed0dSDavid du Colombier 		if(i >= ninclude){
1547*6bbfed0dSDavid du Colombier 			if(i >= maxinclude){
1548*6bbfed0dSDavid du Colombier 				maxinclude += 20;
1549*6bbfed0dSDavid du Colombier 				np = alloc(maxinclude * sizeof *np);
1550*6bbfed0dSDavid du Colombier 				if(include != nil)
1551*6bbfed0dSDavid du Colombier 					memmove(np, include, (maxinclude - 20) * sizeof *np);
1552*6bbfed0dSDavid du Colombier 				include = np;
1553*6bbfed0dSDavid du Colombier 			}
15547dd7cddfSDavid du Colombier 			include[ninclude++] = p;
15557dd7cddfSDavid du Colombier 		}
15567dd7cddfSDavid du Colombier 
15577dd7cddfSDavid du Colombier 		if(e == 0)
15587dd7cddfSDavid du Colombier 			break;
15597dd7cddfSDavid du Colombier 		p = e+1;
15607dd7cddfSDavid du Colombier 	}
15613e12c5d1SDavid du Colombier }
1562