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