xref: /plan9-contrib/sys/src/cmd/acid/lex.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
1bd389b36SDavid du Colombier #include <u.h>
2bd389b36SDavid du Colombier #include <libc.h>
3bd389b36SDavid du Colombier #include <bio.h>
4bd389b36SDavid du Colombier #include <ctype.h>
5bd389b36SDavid du Colombier #include <mach.h>
6bd389b36SDavid du Colombier #define Extern extern
7bd389b36SDavid du Colombier #include "acid.h"
8bd389b36SDavid du Colombier #include "y.tab.h"
9bd389b36SDavid du Colombier 
10bd389b36SDavid du Colombier struct keywd
11bd389b36SDavid du Colombier {
12bd389b36SDavid du Colombier 	char	*name;
13bd389b36SDavid du Colombier 	int	terminal;
14bd389b36SDavid du Colombier }
15bd389b36SDavid du Colombier keywds[] =
16bd389b36SDavid du Colombier {
17bd389b36SDavid du Colombier 	"do",		Tdo,
18bd389b36SDavid du Colombier 	"if",		Tif,
19bd389b36SDavid du Colombier 	"then",		Tthen,
20bd389b36SDavid du Colombier 	"else",		Telse,
21bd389b36SDavid du Colombier 	"while",	Twhile,
22bd389b36SDavid du Colombier 	"loop",		Tloop,
23bd389b36SDavid du Colombier 	"head",		Thead,
24bd389b36SDavid du Colombier 	"tail",		Ttail,
25bd389b36SDavid du Colombier 	"append",	Tappend,
26bd389b36SDavid du Colombier 	"defn",		Tfn,
27bd389b36SDavid du Colombier 	"return",	Tret,
28bd389b36SDavid du Colombier 	"local",	Tlocal,
29bd389b36SDavid du Colombier 	"aggr",		Tcomplex,
30219b2ee8SDavid du Colombier 	"union",	Tcomplex,
31bd389b36SDavid du Colombier 	"adt",		Tcomplex,
32bd389b36SDavid du Colombier 	"complex",	Tcomplex,
33bd389b36SDavid du Colombier 	"delete",	Tdelete,
34bd389b36SDavid du Colombier 	"whatis",	Twhat,
35219b2ee8SDavid du Colombier 	"eval",		Teval,
360b459c2cSDavid du Colombier 	"builtin",	Tbuiltin,
37bd389b36SDavid du Colombier 	0,		0
38bd389b36SDavid du Colombier };
39bd389b36SDavid du Colombier 
40bd389b36SDavid du Colombier char cmap[256] =
41bd389b36SDavid du Colombier {
42bd389b36SDavid du Colombier 	['0']	'\0'+1,
43bd389b36SDavid du Colombier 	['n']	'\n'+1,
44bd389b36SDavid du Colombier 	['r']	'\r'+1,
45bd389b36SDavid du Colombier 	['t']	'\t'+1,
46bd389b36SDavid du Colombier 	['b']	'\b'+1,
47bd389b36SDavid du Colombier 	['f']	'\f'+1,
48bd389b36SDavid du Colombier 	['a']	'\a'+1,
49bd389b36SDavid du Colombier 	['v']	'\v'+1,
50bd389b36SDavid du Colombier 	['\\']	'\\'+1,
51bd389b36SDavid du Colombier 	['"']	'"'+1,
52bd389b36SDavid du Colombier };
53bd389b36SDavid du Colombier 
54bd389b36SDavid du Colombier void
kinit(void)55bd389b36SDavid du Colombier kinit(void)
56bd389b36SDavid du Colombier {
57bd389b36SDavid du Colombier 	int i;
58bd389b36SDavid du Colombier 
59bd389b36SDavid du Colombier 	for(i = 0; keywds[i].name; i++)
60bd389b36SDavid du Colombier 		enter(keywds[i].name, keywds[i].terminal);
61219b2ee8SDavid du Colombier }
62bd389b36SDavid du Colombier 
63219b2ee8SDavid du Colombier typedef struct IOstack IOstack;
64219b2ee8SDavid du Colombier struct IOstack
65219b2ee8SDavid du Colombier {
66219b2ee8SDavid du Colombier 	char	*name;
67219b2ee8SDavid du Colombier 	int	line;
68219b2ee8SDavid du Colombier 	char	*text;
69219b2ee8SDavid du Colombier 	char	*ip;
70219b2ee8SDavid du Colombier 	Biobuf	*fin;
71219b2ee8SDavid du Colombier 	IOstack	*prev;
72219b2ee8SDavid du Colombier };
73219b2ee8SDavid du Colombier IOstack *lexio;
74219b2ee8SDavid du Colombier 
75219b2ee8SDavid du Colombier void
pushfile(char * file)76219b2ee8SDavid du Colombier pushfile(char *file)
77219b2ee8SDavid du Colombier {
78219b2ee8SDavid du Colombier 	Biobuf *b;
79219b2ee8SDavid du Colombier 	IOstack *io;
80219b2ee8SDavid du Colombier 
81219b2ee8SDavid du Colombier 	if(file)
82219b2ee8SDavid du Colombier 		b = Bopen(file, OREAD);
83219b2ee8SDavid du Colombier 	else{
84219b2ee8SDavid du Colombier 		b = Bopen("/fd/0", OREAD);
85219b2ee8SDavid du Colombier 		file = "<stdin>";
86219b2ee8SDavid du Colombier 	}
87219b2ee8SDavid du Colombier 
88219b2ee8SDavid du Colombier 	if(b == 0)
89219b2ee8SDavid du Colombier 		error("pushfile: %s: %r", file);
90219b2ee8SDavid du Colombier 
91219b2ee8SDavid du Colombier 	io = malloc(sizeof(IOstack));
92219b2ee8SDavid du Colombier 	if(io == 0)
93219b2ee8SDavid du Colombier 		fatal("no memory");
94219b2ee8SDavid du Colombier 	io->name = strdup(file);
95219b2ee8SDavid du Colombier 	if(io->name == 0)
96219b2ee8SDavid du Colombier 		fatal("no memory");
97219b2ee8SDavid du Colombier 	io->line = line;
98219b2ee8SDavid du Colombier 	line = 1;
99219b2ee8SDavid du Colombier 	io->text = 0;
100219b2ee8SDavid du Colombier 	io->fin = b;
101219b2ee8SDavid du Colombier 	io->prev = lexio;
102219b2ee8SDavid du Colombier 	lexio = io;
103219b2ee8SDavid du Colombier }
104219b2ee8SDavid du Colombier 
105219b2ee8SDavid du Colombier void
pushstr(Node * s)106219b2ee8SDavid du Colombier pushstr(Node *s)
107219b2ee8SDavid du Colombier {
108219b2ee8SDavid du Colombier 	IOstack *io;
109219b2ee8SDavid du Colombier 
110219b2ee8SDavid du Colombier 	io = malloc(sizeof(IOstack));
111219b2ee8SDavid du Colombier 	if(io == 0)
112219b2ee8SDavid du Colombier 		fatal("no memory");
113219b2ee8SDavid du Colombier 	io->line = line;
114219b2ee8SDavid du Colombier 	line = 1;
115219b2ee8SDavid du Colombier 	io->name = strdup("<string>");
116219b2ee8SDavid du Colombier 	if(io->name == 0)
117219b2ee8SDavid du Colombier 		fatal("no memory");
118219b2ee8SDavid du Colombier 	io->line = line;
119219b2ee8SDavid du Colombier 	line = 1;
120219b2ee8SDavid du Colombier 	io->text = strdup(s->string->string);
121219b2ee8SDavid du Colombier 	if(io->text == 0)
122219b2ee8SDavid du Colombier 		fatal("no memory");
123219b2ee8SDavid du Colombier 	io->ip = io->text;
124219b2ee8SDavid du Colombier 	io->fin = 0;
125219b2ee8SDavid du Colombier 	io->prev = lexio;
126219b2ee8SDavid du Colombier 	lexio = io;
127219b2ee8SDavid du Colombier }
128219b2ee8SDavid du Colombier 
129219b2ee8SDavid du Colombier void
restartio(void)130219b2ee8SDavid du Colombier restartio(void)
131219b2ee8SDavid du Colombier {
132219b2ee8SDavid du Colombier 	Bflush(lexio->fin);
133219b2ee8SDavid du Colombier 	Binit(lexio->fin, 0, OREAD);
134219b2ee8SDavid du Colombier }
135219b2ee8SDavid du Colombier 
136219b2ee8SDavid du Colombier int
popio(void)137219b2ee8SDavid du Colombier popio(void)
138219b2ee8SDavid du Colombier {
139219b2ee8SDavid du Colombier 	IOstack *s;
140219b2ee8SDavid du Colombier 
141219b2ee8SDavid du Colombier 	if(lexio == 0)
142219b2ee8SDavid du Colombier 		return 0;
143219b2ee8SDavid du Colombier 
144219b2ee8SDavid du Colombier 	if(lexio->prev == 0){
145219b2ee8SDavid du Colombier 		if(lexio->fin)
146219b2ee8SDavid du Colombier 			restartio();
147219b2ee8SDavid du Colombier 		return 0;
148219b2ee8SDavid du Colombier 	}
149219b2ee8SDavid du Colombier 
150219b2ee8SDavid du Colombier 	if(lexio->fin)
151219b2ee8SDavid du Colombier 		Bterm(lexio->fin);
152219b2ee8SDavid du Colombier 	else
153219b2ee8SDavid du Colombier 		free(lexio->text);
154219b2ee8SDavid du Colombier 	free(lexio->name);
155219b2ee8SDavid du Colombier 	line = lexio->line;
156219b2ee8SDavid du Colombier 	s = lexio;
157219b2ee8SDavid du Colombier 	lexio = s->prev;
158219b2ee8SDavid du Colombier 	free(s);
159219b2ee8SDavid du Colombier 	return 1;
160219b2ee8SDavid du Colombier }
161219b2ee8SDavid du Colombier 
162219b2ee8SDavid du Colombier int
Lfmt(Fmt * f)1639a747e4fSDavid du Colombier Lfmt(Fmt *f)
164219b2ee8SDavid du Colombier {
165219b2ee8SDavid du Colombier 	int i;
166219b2ee8SDavid du Colombier 	char buf[1024];
167219b2ee8SDavid du Colombier 	IOstack *e;
168219b2ee8SDavid du Colombier 
169219b2ee8SDavid du Colombier 	e = lexio;
170219b2ee8SDavid du Colombier 	if(e) {
171*4de34a7eSDavid du Colombier 		i = snprint(buf, sizeof(buf), "%s:%d", e->name, line);
172219b2ee8SDavid du Colombier 		while(e->prev) {
173219b2ee8SDavid du Colombier 			e = e->prev;
174219b2ee8SDavid du Colombier 			if(initialising && e->prev == 0)
175219b2ee8SDavid du Colombier 				break;
176*4de34a7eSDavid du Colombier 			i += snprint(buf+i, sizeof(buf)-i, " [%s:%d]", e->name, e->line);
177219b2ee8SDavid du Colombier 		}
178219b2ee8SDavid du Colombier 	} else
179*4de34a7eSDavid du Colombier 		snprint(buf, sizeof(buf),  "no file:0");
1809a747e4fSDavid du Colombier 	fmtstrcpy(f, buf);
181219b2ee8SDavid du Colombier 	return 0;
182219b2ee8SDavid du Colombier }
183219b2ee8SDavid du Colombier 
184219b2ee8SDavid du Colombier void
unlexc(int s)185219b2ee8SDavid du Colombier unlexc(int s)
186219b2ee8SDavid du Colombier {
187219b2ee8SDavid du Colombier 	if(s == '\n')
188219b2ee8SDavid du Colombier 		line--;
189219b2ee8SDavid du Colombier 
190219b2ee8SDavid du Colombier 	if(lexio->fin)
191219b2ee8SDavid du Colombier 		Bungetc(lexio->fin);
192219b2ee8SDavid du Colombier 	else
193219b2ee8SDavid du Colombier 		lexio->ip--;
194219b2ee8SDavid du Colombier }
195219b2ee8SDavid du Colombier 
196219b2ee8SDavid du Colombier int
lexc(void)197219b2ee8SDavid du Colombier lexc(void)
198219b2ee8SDavid du Colombier {
199219b2ee8SDavid du Colombier 	int c;
200219b2ee8SDavid du Colombier 
201219b2ee8SDavid du Colombier 	if(lexio->fin) {
202219b2ee8SDavid du Colombier 		c = Bgetc(lexio->fin);
203219b2ee8SDavid du Colombier 		if(gotint)
204219b2ee8SDavid du Colombier 			error("interrupt");
205219b2ee8SDavid du Colombier 		return c;
206219b2ee8SDavid du Colombier 	}
207219b2ee8SDavid du Colombier 
208219b2ee8SDavid du Colombier 	c = *lexio->ip++;
209219b2ee8SDavid du Colombier 	if(c == 0)
210219b2ee8SDavid du Colombier 		return -1;
211219b2ee8SDavid du Colombier 	return c;
212bd389b36SDavid du Colombier }
213bd389b36SDavid du Colombier 
214bd389b36SDavid du Colombier int
escchar(char c)215bd389b36SDavid du Colombier escchar(char c)
216bd389b36SDavid du Colombier {
217bd389b36SDavid du Colombier 	int n;
218bd389b36SDavid du Colombier 	char buf[Strsize];
219bd389b36SDavid du Colombier 
220bd389b36SDavid du Colombier 	if(c >= '0' && c <= '9') {
221bd389b36SDavid du Colombier 		n = 1;
222bd389b36SDavid du Colombier 		buf[0] = c;
223bd389b36SDavid du Colombier 		for(;;) {
224219b2ee8SDavid du Colombier 			c = lexc();
225bd389b36SDavid du Colombier 			if(c == Eof)
226bd389b36SDavid du Colombier 				error("%d: <eof> in escape sequence", line);
227bd389b36SDavid du Colombier 			if(strchr("0123456789xX", c) == 0) {
228219b2ee8SDavid du Colombier 				unlexc(c);
229bd389b36SDavid du Colombier 				break;
230bd389b36SDavid du Colombier 			}
231*4de34a7eSDavid du Colombier 			if(n >= Strsize)
232*4de34a7eSDavid du Colombier 				error("string escape too long");
233bd389b36SDavid du Colombier 			buf[n++] = c;
234bd389b36SDavid du Colombier 		}
235bd389b36SDavid du Colombier 		buf[n] = '\0';
236bd389b36SDavid du Colombier 		return strtol(buf, 0, 0);
237bd389b36SDavid du Colombier 	}
238bd389b36SDavid du Colombier 
239bd389b36SDavid du Colombier 	n = cmap[c];
240bd389b36SDavid du Colombier 	if(n == 0)
241bd389b36SDavid du Colombier 		return c;
242bd389b36SDavid du Colombier 	return n-1;
243bd389b36SDavid du Colombier }
244bd389b36SDavid du Colombier 
245bd389b36SDavid du Colombier void
eatstring(void)246bd389b36SDavid du Colombier eatstring(void)
247bd389b36SDavid du Colombier {
248bd389b36SDavid du Colombier 	int esc, c, cnt;
249bd389b36SDavid du Colombier 	char buf[Strsize];
250bd389b36SDavid du Colombier 
251bd389b36SDavid du Colombier 	esc = 0;
252bd389b36SDavid du Colombier 	for(cnt = 0;;) {
253219b2ee8SDavid du Colombier 		c = lexc();
254bd389b36SDavid du Colombier 		switch(c) {
255bd389b36SDavid du Colombier 		case Eof:
256bd389b36SDavid du Colombier 			error("%d: <eof> in string constant", line);
257bd389b36SDavid du Colombier 
258bd389b36SDavid du Colombier 		case '\n':
259bd389b36SDavid du Colombier 			error("newline in string constant");
260bd389b36SDavid du Colombier 			goto done;
261bd389b36SDavid du Colombier 
262bd389b36SDavid du Colombier 		case '\\':
2639a747e4fSDavid du Colombier 			if(esc)
2649a747e4fSDavid du Colombier 				goto Default;
265bd389b36SDavid du Colombier 			esc = 1;
266bd389b36SDavid du Colombier 			break;
267bd389b36SDavid du Colombier 
268bd389b36SDavid du Colombier 		case '"':
269bd389b36SDavid du Colombier 			if(esc == 0)
270bd389b36SDavid du Colombier 				goto done;
271bd389b36SDavid du Colombier 
272bd389b36SDavid du Colombier 			/* Fall through */
273bd389b36SDavid du Colombier 		default:
2749a747e4fSDavid du Colombier 		Default:
275bd389b36SDavid du Colombier 			if(esc) {
276bd389b36SDavid du Colombier 				c = escchar(c);
277bd389b36SDavid du Colombier 				esc = 0;
278bd389b36SDavid du Colombier 			}
279bd389b36SDavid du Colombier 			buf[cnt++] = c;
280bd389b36SDavid du Colombier 			break;
281bd389b36SDavid du Colombier 		}
282219b2ee8SDavid du Colombier 		if(cnt >= Strsize)
283219b2ee8SDavid du Colombier 			error("string token too long");
284bd389b36SDavid du Colombier 	}
285bd389b36SDavid du Colombier done:
286bd389b36SDavid du Colombier 	buf[cnt] = '\0';
287bd389b36SDavid du Colombier 	yylval.string = strnode(buf);
288bd389b36SDavid du Colombier }
289bd389b36SDavid du Colombier 
290bd389b36SDavid du Colombier void
eatnl(void)291bd389b36SDavid du Colombier eatnl(void)
292bd389b36SDavid du Colombier {
293bd389b36SDavid du Colombier 	int c;
294bd389b36SDavid du Colombier 
295bd389b36SDavid du Colombier 	line++;
296bd389b36SDavid du Colombier 	for(;;) {
297219b2ee8SDavid du Colombier 		c = lexc();
298bd389b36SDavid du Colombier 		if(c == Eof)
299bd389b36SDavid du Colombier 			error("eof in comment");
300bd389b36SDavid du Colombier 		if(c == '\n')
301bd389b36SDavid du Colombier 			return;
302bd389b36SDavid du Colombier 	}
303bd389b36SDavid du Colombier }
304bd389b36SDavid du Colombier 
305bd389b36SDavid du Colombier int
yylex(void)306bd389b36SDavid du Colombier yylex(void)
307bd389b36SDavid du Colombier {
308bd389b36SDavid du Colombier 	int c;
309219b2ee8SDavid du Colombier 	extern char vfmt[];
310bd389b36SDavid du Colombier 
311bd389b36SDavid du Colombier loop:
312bd389b36SDavid du Colombier 	Bflush(bout);
313219b2ee8SDavid du Colombier 	c = lexc();
314bd389b36SDavid du Colombier 	switch(c) {
315bd389b36SDavid du Colombier 	case Eof:
316bd389b36SDavid du Colombier 		if(gotint) {
317bd389b36SDavid du Colombier 			gotint = 0;
318bd389b36SDavid du Colombier 			stacked = 0;
319bd389b36SDavid du Colombier 			Bprint(bout, "\nacid: ");
320bd389b36SDavid du Colombier 			goto loop;
321bd389b36SDavid du Colombier 		}
322bd389b36SDavid du Colombier 		return Eof;
323bd389b36SDavid du Colombier 
324bd389b36SDavid du Colombier 	case '"':
325bd389b36SDavid du Colombier 		eatstring();
326bd389b36SDavid du Colombier 		return Tstring;
327bd389b36SDavid du Colombier 
328bd389b36SDavid du Colombier 	case ' ':
329bd389b36SDavid du Colombier 	case '\t':
330bd389b36SDavid du Colombier 		goto loop;
331bd389b36SDavid du Colombier 
332bd389b36SDavid du Colombier 	case '\n':
333bd389b36SDavid du Colombier 		line++;
334bd389b36SDavid du Colombier 		if(interactive == 0)
335bd389b36SDavid du Colombier 			goto loop;
336bd389b36SDavid du Colombier 		if(stacked) {
337bd389b36SDavid du Colombier 			print("\t");
338bd389b36SDavid du Colombier 			goto loop;
339bd389b36SDavid du Colombier 		}
340bd389b36SDavid du Colombier 		return ';';
341bd389b36SDavid du Colombier 
342bd389b36SDavid du Colombier 	case '.':
343219b2ee8SDavid du Colombier 		c = lexc();
344219b2ee8SDavid du Colombier 		unlexc(c);
345bd389b36SDavid du Colombier 		if(isdigit(c))
346bd389b36SDavid du Colombier 			return numsym('.');
347bd389b36SDavid du Colombier 
348bd389b36SDavid du Colombier 		return '.';
349bd389b36SDavid du Colombier 
350bd389b36SDavid du Colombier 	case '(':
351bd389b36SDavid du Colombier 	case ')':
352bd389b36SDavid du Colombier 	case '[':
353bd389b36SDavid du Colombier 	case ']':
354bd389b36SDavid du Colombier 	case ';':
355bd389b36SDavid du Colombier 	case ':':
356bd389b36SDavid du Colombier 	case ',':
357bd389b36SDavid du Colombier 	case '~':
358bd389b36SDavid du Colombier 	case '?':
359bd389b36SDavid du Colombier 	case '*':
360bd389b36SDavid du Colombier 	case '@':
361bd389b36SDavid du Colombier 	case '^':
362bd389b36SDavid du Colombier 	case '%':
363bd389b36SDavid du Colombier 		return c;
364bd389b36SDavid du Colombier 	case '{':
365bd389b36SDavid du Colombier 		stacked++;
366bd389b36SDavid du Colombier 		return c;
367bd389b36SDavid du Colombier 	case '}':
368bd389b36SDavid du Colombier 		stacked--;
369bd389b36SDavid du Colombier 		return c;
370bd389b36SDavid du Colombier 
371219b2ee8SDavid du Colombier 	case '\\':
372219b2ee8SDavid du Colombier 		c = lexc();
373219b2ee8SDavid du Colombier 		if(strchr(vfmt, c) == 0) {
374219b2ee8SDavid du Colombier 			unlexc(c);
375219b2ee8SDavid du Colombier 			return '\\';
376219b2ee8SDavid du Colombier 		}
377219b2ee8SDavid du Colombier 		yylval.ival = c;
378219b2ee8SDavid du Colombier 		return Tfmt;
379219b2ee8SDavid du Colombier 
380bd389b36SDavid du Colombier 	case '!':
381219b2ee8SDavid du Colombier 		c = lexc();
382bd389b36SDavid du Colombier 		if(c == '=')
383bd389b36SDavid du Colombier 			return Tneq;
384219b2ee8SDavid du Colombier 		unlexc(c);
385bd389b36SDavid du Colombier 		return '!';
386bd389b36SDavid du Colombier 
387bd389b36SDavid du Colombier 	case '+':
388219b2ee8SDavid du Colombier 		c = lexc();
389bd389b36SDavid du Colombier 		if(c == '+')
390bd389b36SDavid du Colombier 			return Tinc;
391219b2ee8SDavid du Colombier 		unlexc(c);
392bd389b36SDavid du Colombier 		return '+';
393bd389b36SDavid du Colombier 
394bd389b36SDavid du Colombier 	case '/':
395219b2ee8SDavid du Colombier 		c = lexc();
396bd389b36SDavid du Colombier 		if(c == '/') {
397bd389b36SDavid du Colombier 			eatnl();
398bd389b36SDavid du Colombier 			goto loop;
399bd389b36SDavid du Colombier 		}
400219b2ee8SDavid du Colombier 		unlexc(c);
401bd389b36SDavid du Colombier 		return '/';
402bd389b36SDavid du Colombier 
403bd389b36SDavid du Colombier 	case '\'':
404219b2ee8SDavid du Colombier 		c = lexc();
405bd389b36SDavid du Colombier 		if(c == '\\')
406219b2ee8SDavid du Colombier 			yylval.ival = escchar(lexc());
407bd389b36SDavid du Colombier 		else
408bd389b36SDavid du Colombier 			yylval.ival = c;
409219b2ee8SDavid du Colombier 		c = lexc();
410bd389b36SDavid du Colombier 		if(c != '\'') {
411bd389b36SDavid du Colombier 			error("missing '");
412219b2ee8SDavid du Colombier 			unlexc(c);
413bd389b36SDavid du Colombier 		}
414bd389b36SDavid du Colombier 		return Tconst;
415bd389b36SDavid du Colombier 
416bd389b36SDavid du Colombier 	case '&':
417219b2ee8SDavid du Colombier 		c = lexc();
418bd389b36SDavid du Colombier 		if(c == '&')
419bd389b36SDavid du Colombier 			return Tandand;
420219b2ee8SDavid du Colombier 		unlexc(c);
421bd389b36SDavid du Colombier 		return '&';
422bd389b36SDavid du Colombier 
423bd389b36SDavid du Colombier 	case '=':
424219b2ee8SDavid du Colombier 		c = lexc();
425bd389b36SDavid du Colombier 		if(c == '=')
426bd389b36SDavid du Colombier 			return Teq;
427219b2ee8SDavid du Colombier 		unlexc(c);
428bd389b36SDavid du Colombier 		return '=';
429bd389b36SDavid du Colombier 
430bd389b36SDavid du Colombier 	case '|':
431219b2ee8SDavid du Colombier 		c = lexc();
432bd389b36SDavid du Colombier 		if(c == '|')
433bd389b36SDavid du Colombier 			return Toror;
434219b2ee8SDavid du Colombier 		unlexc(c);
435bd389b36SDavid du Colombier 		return '|';
436bd389b36SDavid du Colombier 
437bd389b36SDavid du Colombier 	case '<':
438219b2ee8SDavid du Colombier 		c = lexc();
439bd389b36SDavid du Colombier 		if(c == '=')
440bd389b36SDavid du Colombier 			return Tleq;
441bd389b36SDavid du Colombier 		if(c == '<')
442bd389b36SDavid du Colombier 			return Tlsh;
443219b2ee8SDavid du Colombier 		unlexc(c);
444bd389b36SDavid du Colombier 		return '<';
445bd389b36SDavid du Colombier 
446bd389b36SDavid du Colombier 	case '>':
447219b2ee8SDavid du Colombier 		c = lexc();
448bd389b36SDavid du Colombier 		if(c == '=')
449bd389b36SDavid du Colombier 			return Tgeq;
450bd389b36SDavid du Colombier 		if(c == '>')
451bd389b36SDavid du Colombier 			return Trsh;
452219b2ee8SDavid du Colombier 		unlexc(c);
453bd389b36SDavid du Colombier 		return '>';
454bd389b36SDavid du Colombier 
455bd389b36SDavid du Colombier 	case '-':
456219b2ee8SDavid du Colombier 		c = lexc();
457219b2ee8SDavid du Colombier 
458bd389b36SDavid du Colombier 		if(c == '>')
459bd389b36SDavid du Colombier 			return Tindir;
460219b2ee8SDavid du Colombier 
461bd389b36SDavid du Colombier 		if(c == '-')
462bd389b36SDavid du Colombier 			return Tdec;
463219b2ee8SDavid du Colombier 		unlexc(c);
464bd389b36SDavid du Colombier 		return '-';
465bd389b36SDavid du Colombier 
466bd389b36SDavid du Colombier 	default:
467bd389b36SDavid du Colombier 		return numsym(c);
468bd389b36SDavid du Colombier 	}
469bd389b36SDavid du Colombier }
470bd389b36SDavid du Colombier 
471bd389b36SDavid du Colombier int
numsym(char first)472bd389b36SDavid du Colombier numsym(char first)
473bd389b36SDavid du Colombier {
474219b2ee8SDavid du Colombier 	int c, isbin, isfloat, ishex;
475bd389b36SDavid du Colombier 	char *sel, *p;
476bd389b36SDavid du Colombier 	Lsym *s;
477bd389b36SDavid du Colombier 
478bd389b36SDavid du Colombier 	symbol[0] = first;
479bd389b36SDavid du Colombier 	p = symbol;
480bd389b36SDavid du Colombier 
481bd389b36SDavid du Colombier 	ishex = 0;
482219b2ee8SDavid du Colombier 	isbin = 0;
483bd389b36SDavid du Colombier 	isfloat = 0;
484bd389b36SDavid du Colombier 	if(first == '.')
485bd389b36SDavid du Colombier 		isfloat = 1;
486bd389b36SDavid du Colombier 
487bd389b36SDavid du Colombier 	if(isdigit(*p++) || isfloat) {
488bd389b36SDavid du Colombier 		for(;;) {
489219b2ee8SDavid du Colombier 			c = lexc();
490bd389b36SDavid du Colombier 			if(c < 0)
491bd389b36SDavid du Colombier 				error("%d: <eof> eating symbols", line);
492bd389b36SDavid du Colombier 
493bd389b36SDavid du Colombier 			if(c == '\n')
494bd389b36SDavid du Colombier 				line++;
495219b2ee8SDavid du Colombier 			sel = "01234567890.xb";
496bd389b36SDavid du Colombier 			if(ishex)
497bd389b36SDavid du Colombier 				sel = "01234567890abcdefABCDEF";
498219b2ee8SDavid du Colombier 			else if(isbin)
499219b2ee8SDavid du Colombier 				sel = "01";
5007dd7cddfSDavid du Colombier 			else if(isfloat)
5017dd7cddfSDavid du Colombier 				sel = "01234567890eE-+";
502bd389b36SDavid du Colombier 
503bd389b36SDavid du Colombier 			if(strchr(sel, c) == 0) {
504219b2ee8SDavid du Colombier 				unlexc(c);
505bd389b36SDavid du Colombier 				break;
506bd389b36SDavid du Colombier 			}
507bd389b36SDavid du Colombier 			if(c == '.')
508bd389b36SDavid du Colombier 				isfloat = 1;
509219b2ee8SDavid du Colombier 			if(!isbin && c == 'x')
510bd389b36SDavid du Colombier 				ishex = 1;
511219b2ee8SDavid du Colombier 			if(!ishex && c == 'b')
512219b2ee8SDavid du Colombier 				isbin = 1;
513bd389b36SDavid du Colombier 			*p++ = c;
514bd389b36SDavid du Colombier 		}
515bd389b36SDavid du Colombier 		*p = '\0';
516bd389b36SDavid du Colombier 		if(isfloat) {
517bd389b36SDavid du Colombier 			yylval.fval = atof(symbol);
518bd389b36SDavid du Colombier 			return Tfconst;
519bd389b36SDavid du Colombier 		}
520bd389b36SDavid du Colombier 
521219b2ee8SDavid du Colombier 		if(isbin)
522*4de34a7eSDavid du Colombier 			yylval.ival = strtoull(symbol+2, 0, 2);
523219b2ee8SDavid du Colombier 		else
524*4de34a7eSDavid du Colombier 			yylval.ival = strtoull(symbol, 0, 0);
525bd389b36SDavid du Colombier 		return Tconst;
526bd389b36SDavid du Colombier 	}
527bd389b36SDavid du Colombier 
528bd389b36SDavid du Colombier 	for(;;) {
529219b2ee8SDavid du Colombier 		c = lexc();
530bd389b36SDavid du Colombier 		if(c < 0)
531bd389b36SDavid du Colombier 			error("%d <eof> eating symbols", line);
532bd389b36SDavid du Colombier 		if(c == '\n')
533bd389b36SDavid du Colombier 			line++;
5349a747e4fSDavid du Colombier 		if(c != '_' && c != '$' && c <= '~' && !isalnum(c)) {	/* checking against ~ lets UTF names through */
535219b2ee8SDavid du Colombier 			unlexc(c);
536bd389b36SDavid du Colombier 			break;
537bd389b36SDavid du Colombier 		}
538bd389b36SDavid du Colombier 		*p++ = c;
539bd389b36SDavid du Colombier 	}
540bd389b36SDavid du Colombier 
541bd389b36SDavid du Colombier 	*p = '\0';
542bd389b36SDavid du Colombier 
543bd389b36SDavid du Colombier 	s = look(symbol);
544bd389b36SDavid du Colombier 	if(s == 0)
545bd389b36SDavid du Colombier 		s = enter(symbol, Tid);
546bd389b36SDavid du Colombier 
547bd389b36SDavid du Colombier 	yylval.sym = s;
548bd389b36SDavid du Colombier 	return s->lexval;
549bd389b36SDavid du Colombier }
550bd389b36SDavid du Colombier 
551bd389b36SDavid du Colombier Lsym*
enter(char * name,int t)552bd389b36SDavid du Colombier enter(char *name, int t)
553bd389b36SDavid du Colombier {
554bd389b36SDavid du Colombier 	Lsym *s;
555*4de34a7eSDavid du Colombier 	uint h;
556bd389b36SDavid du Colombier 	char *p;
557bd389b36SDavid du Colombier 	Value *v;
558bd389b36SDavid du Colombier 
559bd389b36SDavid du Colombier 	h = 0;
560bd389b36SDavid du Colombier 	for(p = name; *p; p++)
561bd389b36SDavid du Colombier 		h = h*3 + *p;
562bd389b36SDavid du Colombier 	h %= Hashsize;
563bd389b36SDavid du Colombier 
564bd389b36SDavid du Colombier 	s = gmalloc(sizeof(Lsym));
565bd389b36SDavid du Colombier 	memset(s, 0, sizeof(Lsym));
566bd389b36SDavid du Colombier 	s->name = strdup(name);
567bd389b36SDavid du Colombier 
568bd389b36SDavid du Colombier 	s->hash = hash[h];
569bd389b36SDavid du Colombier 	hash[h] = s;
570bd389b36SDavid du Colombier 	s->lexval = t;
571bd389b36SDavid du Colombier 
572bd389b36SDavid du Colombier 	v = gmalloc(sizeof(Value));
573bd389b36SDavid du Colombier 	s->v = v;
574bd389b36SDavid du Colombier 
575bd389b36SDavid du Colombier 	v->fmt = 'X';
576bd389b36SDavid du Colombier 	v->type = TINT;
577bd389b36SDavid du Colombier 	memset(v, 0, sizeof(Value));
578bd389b36SDavid du Colombier 
579bd389b36SDavid du Colombier 	return s;
580bd389b36SDavid du Colombier }
581bd389b36SDavid du Colombier 
582bd389b36SDavid du Colombier Lsym*
look(char * name)583bd389b36SDavid du Colombier look(char *name)
584bd389b36SDavid du Colombier {
585bd389b36SDavid du Colombier 	Lsym *s;
586*4de34a7eSDavid du Colombier 	uint h;
587bd389b36SDavid du Colombier 	char *p;
588bd389b36SDavid du Colombier 
589bd389b36SDavid du Colombier 	h = 0;
590bd389b36SDavid du Colombier 	for(p = name; *p; p++)
591bd389b36SDavid du Colombier 		h = h*3 + *p;
592bd389b36SDavid du Colombier 	h %= Hashsize;
593bd389b36SDavid du Colombier 
594bd389b36SDavid du Colombier 	for(s = hash[h]; s; s = s->hash)
595bd389b36SDavid du Colombier 		if(strcmp(name, s->name) == 0)
596bd389b36SDavid du Colombier 			return s;
597bd389b36SDavid du Colombier 	return 0;
598bd389b36SDavid du Colombier }
599bd389b36SDavid du Colombier 
600bd389b36SDavid du Colombier Lsym*
mkvar(char * s)601bd389b36SDavid du Colombier mkvar(char *s)
602bd389b36SDavid du Colombier {
603bd389b36SDavid du Colombier 	Lsym *l;
604bd389b36SDavid du Colombier 
605bd389b36SDavid du Colombier 	l = look(s);
606bd389b36SDavid du Colombier 	if(l == 0)
607bd389b36SDavid du Colombier 		l = enter(s, Tid);
608bd389b36SDavid du Colombier 	return l;
609bd389b36SDavid du Colombier }
610