1145519Sdarrenr/*	$FreeBSD: stable/11/contrib/ipfilter/tools/lexer.c 369245 2021-02-09 13:47:46Z git2svn $	*/
2145510Sdarrenr
3145510Sdarrenr/*
4255332Scy * Copyright (C) 2012 by Darren Reed.
5145510Sdarrenr *
6145510Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7145510Sdarrenr */
8145510Sdarrenr#include <ctype.h>
9145510Sdarrenr#include "ipf.h"
10145510Sdarrenr#ifdef	IPFILTER_SCAN
11145510Sdarrenr# include "netinet/ip_scan.h"
12145510Sdarrenr#endif
13145510Sdarrenr#include <sys/ioctl.h>
14145510Sdarrenr#include <syslog.h>
15145510Sdarrenr#ifdef	TEST_LEXER
16145510Sdarrenr# define	NO_YACC
17145510Sdarrenrunion	{
18145510Sdarrenr	int		num;
19145510Sdarrenr	char		*str;
20145510Sdarrenr	struct in_addr	ipa;
21145510Sdarrenr	i6addr_t	ip6;
22145510Sdarrenr} yylval;
23145510Sdarrenr#endif
24145510Sdarrenr#include "lexer.h"
25145510Sdarrenr#include "y.tab.h"
26145510Sdarrenr
27145510SdarrenrFILE *yyin;
28145510Sdarrenr
29145510Sdarrenr#define	ishex(c)	(ISDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || \
30145510Sdarrenr			 ((c) >= 'A' && (c) <= 'F'))
31145510Sdarrenr#define	TOOLONG		-3
32145510Sdarrenr
33145510Sdarrenrextern int	string_start;
34145510Sdarrenrextern int	string_end;
35145510Sdarrenrextern char	*string_val;
36145510Sdarrenrextern int	pos;
37145510Sdarrenrextern int	yydebug;
38145510Sdarrenr
39145510Sdarrenrchar		*yystr = NULL;
40145510Sdarrenrint		yytext[YYBUFSIZ+1];
41172776Sdarrenrchar		yychars[YYBUFSIZ+1];
42145510Sdarrenrint		yylineNum = 1;
43145510Sdarrenrint		yypos = 0;
44145510Sdarrenrint		yylast = -1;
45255332Scyint		yydictfixed = 0;
46145510Sdarrenrint		yyexpectaddr = 0;
47145510Sdarrenrint		yybreakondot = 0;
48145510Sdarrenrint		yyvarnext = 0;
49145510Sdarrenrint		yytokentype = 0;
50145510Sdarrenrwordtab_t	*yywordtab = NULL;
51145510Sdarrenrint		yysavedepth = 0;
52145510Sdarrenrwordtab_t	*yysavewords[30];
53145510Sdarrenr
54145510Sdarrenr
55369245Sgit2svnstatic	wordtab_t	*yyfindkey(char *);
56369245Sgit2svnstatic	int		yygetc(int);
57369245Sgit2svnstatic	void		yyunputc(int);
58369245Sgit2svnstatic	int		yyswallow(int);
59369245Sgit2svnstatic	char		*yytexttostr(int, int);
60369245Sgit2svnstatic	void		yystrtotext(char *);
61369245Sgit2svnstatic	char		*yytexttochar(void);
62145510Sdarrenr
63172776Sdarrenrstatic int yygetc(docont)
64255332Scy	int docont;
65145510Sdarrenr{
66145510Sdarrenr	int c;
67145510Sdarrenr
68145510Sdarrenr	if (yypos < yylast) {
69145510Sdarrenr		c = yytext[yypos++];
70145510Sdarrenr		if (c == '\n')
71145510Sdarrenr			yylineNum++;
72145510Sdarrenr		return c;
73145510Sdarrenr	}
74145510Sdarrenr
75145510Sdarrenr	if (yypos == YYBUFSIZ)
76145510Sdarrenr		return TOOLONG;
77145510Sdarrenr
78145510Sdarrenr	if (pos >= string_start && pos <= string_end) {
79145510Sdarrenr		c = string_val[pos - string_start];
80145510Sdarrenr		yypos++;
81145510Sdarrenr	} else {
82145510Sdarrenr		c = fgetc(yyin);
83172776Sdarrenr		if (docont && (c == '\\')) {
84172776Sdarrenr			c = fgetc(yyin);
85172776Sdarrenr			if (c == '\n') {
86172776Sdarrenr				yylineNum++;
87172776Sdarrenr				c = fgetc(yyin);
88172776Sdarrenr			}
89172776Sdarrenr		}
90145510Sdarrenr	}
91145510Sdarrenr	if (c == '\n')
92145510Sdarrenr		yylineNum++;
93145510Sdarrenr	yytext[yypos++] = c;
94145510Sdarrenr	yylast = yypos;
95145510Sdarrenr	yytext[yypos] = '\0';
96145510Sdarrenr
97145510Sdarrenr	return c;
98145510Sdarrenr}
99145510Sdarrenr
100145510Sdarrenr
101145510Sdarrenrstatic void yyunputc(c)
102255332Scy	int c;
103145510Sdarrenr{
104145510Sdarrenr	if (c == '\n')
105145510Sdarrenr		yylineNum--;
106145510Sdarrenr	yytext[--yypos] = c;
107145510Sdarrenr}
108145510Sdarrenr
109145510Sdarrenr
110145510Sdarrenrstatic int yyswallow(last)
111255332Scy	int last;
112145510Sdarrenr{
113145510Sdarrenr	int c;
114145510Sdarrenr
115172776Sdarrenr	while (((c = yygetc(0)) > '\0') && (c != last))
116145510Sdarrenr		;
117145510Sdarrenr
118145510Sdarrenr	if (c != EOF)
119145510Sdarrenr		yyunputc(c);
120145510Sdarrenr	if (c == last)
121145510Sdarrenr		return 0;
122145510Sdarrenr	return -1;
123145510Sdarrenr}
124145510Sdarrenr
125145510Sdarrenr
126172776Sdarrenrstatic char *yytexttochar()
127172776Sdarrenr{
128172776Sdarrenr	int i;
129172776Sdarrenr
130172776Sdarrenr	for (i = 0; i < yypos; i++)
131172776Sdarrenr		yychars[i] = (char)(yytext[i] & 0xff);
132172776Sdarrenr	yychars[i] = '\0';
133172776Sdarrenr	return yychars;
134172776Sdarrenr}
135172776Sdarrenr
136172776Sdarrenr
137145510Sdarrenrstatic void yystrtotext(str)
138255332Scy	char *str;
139145510Sdarrenr{
140145510Sdarrenr	int len;
141145510Sdarrenr	char *s;
142145510Sdarrenr
143145510Sdarrenr	len = strlen(str);
144145510Sdarrenr	if (len > YYBUFSIZ)
145145510Sdarrenr		len = YYBUFSIZ;
146145510Sdarrenr
147145510Sdarrenr	for (s = str; *s != '\0' && len > 0; s++, len--)
148145510Sdarrenr		yytext[yylast++] = *s;
149145510Sdarrenr	yytext[yylast] = '\0';
150145510Sdarrenr}
151145510Sdarrenr
152145510Sdarrenr
153145510Sdarrenrstatic char *yytexttostr(offset, max)
154255332Scy	int offset, max;
155145510Sdarrenr{
156145510Sdarrenr	char *str;
157145510Sdarrenr	int i;
158145510Sdarrenr
159145510Sdarrenr	if ((yytext[offset] == '\'' || yytext[offset] == '"') &&
160145510Sdarrenr	    (yytext[offset] == yytext[offset + max - 1])) {
161145510Sdarrenr		offset++;
162145510Sdarrenr		max--;
163145510Sdarrenr	}
164145510Sdarrenr
165145510Sdarrenr	if (max > yylast)
166145510Sdarrenr		max = yylast;
167145510Sdarrenr	str = malloc(max + 1);
168145510Sdarrenr	if (str != NULL) {
169145510Sdarrenr		for (i = offset; i < max; i++)
170145510Sdarrenr			str[i - offset] = (char)(yytext[i] & 0xff);
171145510Sdarrenr		str[i - offset] = '\0';
172145510Sdarrenr	}
173145510Sdarrenr	return str;
174145510Sdarrenr}
175145510Sdarrenr
176145510Sdarrenr
177145510Sdarrenrint yylex()
178145510Sdarrenr{
179255332Scy	static int prior = 0;
180255332Scy	static int priornum = 0;
181145510Sdarrenr	int c, n, isbuilding, rval, lnext, nokey = 0;
182145510Sdarrenr	char *name;
183255332Scy	int triedv6 = 0;
184145510Sdarrenr
185145510Sdarrenr	isbuilding = 0;
186145510Sdarrenr	lnext = 0;
187145510Sdarrenr	rval = 0;
188145510Sdarrenr
189145510Sdarrenr	if (yystr != NULL) {
190145510Sdarrenr		free(yystr);
191145510Sdarrenr		yystr = NULL;
192145510Sdarrenr	}
193145510Sdarrenr
194145510Sdarrenrnextchar:
195172776Sdarrenr	c = yygetc(0);
196172776Sdarrenr	if (yydebug > 1)
197255332Scy		printf("yygetc = (%x) %c [%*.*s]\n",
198255332Scy		       c, c, yypos, yypos, yytexttochar());
199145510Sdarrenr
200145510Sdarrenr	switch (c)
201145510Sdarrenr	{
202145510Sdarrenr	case '\n' :
203161357Sguido		lnext = 0;
204161357Sguido		nokey = 0;
205145510Sdarrenr	case '\t' :
206145510Sdarrenr	case '\r' :
207145510Sdarrenr	case ' ' :
208145510Sdarrenr		if (isbuilding == 1) {
209145510Sdarrenr			yyunputc(c);
210145510Sdarrenr			goto done;
211145510Sdarrenr		}
212145510Sdarrenr		if (yylast > yypos) {
213145510Sdarrenr			bcopy(yytext + yypos, yytext,
214145510Sdarrenr			      sizeof(yytext[0]) * (yylast - yypos + 1));
215145510Sdarrenr		}
216145510Sdarrenr		yylast -= yypos;
217255332Scy		if (yyexpectaddr == 2)
218255332Scy			yyexpectaddr = 0;
219145510Sdarrenr		yypos = 0;
220145510Sdarrenr		lnext = 0;
221145510Sdarrenr		nokey = 0;
222145510Sdarrenr		goto nextchar;
223145510Sdarrenr
224145510Sdarrenr	case '\\' :
225145510Sdarrenr		if (lnext == 0) {
226145510Sdarrenr			lnext = 1;
227145510Sdarrenr			if (yylast == yypos) {
228145510Sdarrenr				yylast--;
229145510Sdarrenr				yypos--;
230145510Sdarrenr			} else
231145510Sdarrenr				yypos--;
232145510Sdarrenr			if (yypos == 0)
233145510Sdarrenr				nokey = 1;
234145510Sdarrenr			goto nextchar;
235145510Sdarrenr		}
236145510Sdarrenr		break;
237145510Sdarrenr	}
238145510Sdarrenr
239145510Sdarrenr	if (lnext == 1) {
240145510Sdarrenr		lnext = 0;
241145510Sdarrenr		if ((isbuilding == 0) && !ISALNUM(c)) {
242255332Scy			prior = c;
243145510Sdarrenr			return c;
244145510Sdarrenr		}
245145510Sdarrenr		goto nextchar;
246145510Sdarrenr	}
247145510Sdarrenr
248145510Sdarrenr	switch (c)
249145510Sdarrenr	{
250145510Sdarrenr	case '#' :
251145510Sdarrenr		if (isbuilding == 1) {
252145510Sdarrenr			yyunputc(c);
253145510Sdarrenr			goto done;
254145510Sdarrenr		}
255145510Sdarrenr		yyswallow('\n');
256145510Sdarrenr		rval = YY_COMMENT;
257255332Scy		goto done;
258145510Sdarrenr
259145510Sdarrenr	case '$' :
260145510Sdarrenr		if (isbuilding == 1) {
261145510Sdarrenr			yyunputc(c);
262145510Sdarrenr			goto done;
263145510Sdarrenr		}
264172776Sdarrenr		n = yygetc(0);
265145510Sdarrenr		if (n == '{') {
266145510Sdarrenr			if (yyswallow('}') == -1) {
267145510Sdarrenr				rval = -2;
268145510Sdarrenr				goto done;
269145510Sdarrenr			}
270172776Sdarrenr			(void) yygetc(0);
271145510Sdarrenr		} else {
272145510Sdarrenr			if (!ISALPHA(n)) {
273145510Sdarrenr				yyunputc(n);
274145510Sdarrenr				break;
275145510Sdarrenr			}
276145510Sdarrenr			do {
277172776Sdarrenr				n = yygetc(1);
278145510Sdarrenr			} while (ISALPHA(n) || ISDIGIT(n) || n == '_');
279145510Sdarrenr			yyunputc(n);
280145510Sdarrenr		}
281145510Sdarrenr
282145510Sdarrenr		name = yytexttostr(1, yypos);		/* skip $ */
283145510Sdarrenr
284145510Sdarrenr		if (name != NULL) {
285145510Sdarrenr			string_val = get_variable(name, NULL, yylineNum);
286145510Sdarrenr			free(name);
287145510Sdarrenr			if (string_val != NULL) {
288145510Sdarrenr				name = yytexttostr(yypos, yylast);
289145510Sdarrenr				if (name != NULL) {
290145510Sdarrenr					yypos = 0;
291145510Sdarrenr					yylast = 0;
292145510Sdarrenr					yystrtotext(string_val);
293145510Sdarrenr					yystrtotext(name);
294145510Sdarrenr					free(string_val);
295145510Sdarrenr					free(name);
296145510Sdarrenr					goto nextchar;
297145510Sdarrenr				}
298145510Sdarrenr				free(string_val);
299145510Sdarrenr			}
300145510Sdarrenr		}
301145510Sdarrenr		break;
302145510Sdarrenr
303145510Sdarrenr	case '\'':
304145510Sdarrenr	case '"' :
305145510Sdarrenr		if (isbuilding == 1) {
306145510Sdarrenr			goto done;
307145510Sdarrenr		}
308145510Sdarrenr		do {
309172776Sdarrenr			n = yygetc(1);
310145510Sdarrenr			if (n == EOF || n == TOOLONG) {
311145510Sdarrenr				rval = -2;
312145510Sdarrenr				goto done;
313145510Sdarrenr			}
314145510Sdarrenr			if (n == '\n') {
315145510Sdarrenr				yyunputc(' ');
316145510Sdarrenr				yypos++;
317145510Sdarrenr			}
318145510Sdarrenr		} while (n != c);
319170268Sdarrenr		rval = YY_STR;
320170268Sdarrenr		goto done;
321170268Sdarrenr		/* NOTREACHED */
322145510Sdarrenr
323145510Sdarrenr	case EOF :
324145510Sdarrenr		yylineNum = 1;
325145510Sdarrenr		yypos = 0;
326145510Sdarrenr		yylast = -1;
327145510Sdarrenr		yyexpectaddr = 0;
328145510Sdarrenr		yybreakondot = 0;
329145510Sdarrenr		yyvarnext = 0;
330145510Sdarrenr		yytokentype = 0;
331255332Scy		if (yydebug)
332255332Scy			fprintf(stderr, "reset at EOF\n");
333255332Scy		prior = 0;
334145510Sdarrenr		return 0;
335145510Sdarrenr	}
336145510Sdarrenr
337145510Sdarrenr	if (strchr("=,/;{}()@", c) != NULL) {
338145510Sdarrenr		if (isbuilding == 1) {
339145510Sdarrenr			yyunputc(c);
340145510Sdarrenr			goto done;
341145510Sdarrenr		}
342145510Sdarrenr		rval = c;
343145510Sdarrenr		goto done;
344145510Sdarrenr	} else if (c == '.') {
345145510Sdarrenr		if (isbuilding == 0) {
346145510Sdarrenr			rval = c;
347145510Sdarrenr			goto done;
348145510Sdarrenr		}
349145510Sdarrenr		if (yybreakondot != 0) {
350145510Sdarrenr			yyunputc(c);
351145510Sdarrenr			goto done;
352145510Sdarrenr		}
353145510Sdarrenr	}
354145510Sdarrenr
355145510Sdarrenr	switch (c)
356145510Sdarrenr	{
357145510Sdarrenr	case '-' :
358172776Sdarrenr		n = yygetc(0);
359145510Sdarrenr		if (n == '>') {
360145510Sdarrenr			isbuilding = 1;
361145510Sdarrenr			goto done;
362145510Sdarrenr		}
363145510Sdarrenr		yyunputc(n);
364255332Scy		if (yyexpectaddr) {
365255332Scy			if (isbuilding == 1)
366255332Scy				yyunputc(c);
367255332Scy			else
368255332Scy				rval = '-';
369255332Scy			goto done;
370255332Scy		}
371255332Scy		if (isbuilding == 1)
372255332Scy			break;
373145510Sdarrenr		rval = '-';
374145510Sdarrenr		goto done;
375145510Sdarrenr
376145510Sdarrenr	case '!' :
377145510Sdarrenr		if (isbuilding == 1) {
378145510Sdarrenr			yyunputc(c);
379145510Sdarrenr			goto done;
380145510Sdarrenr		}
381172776Sdarrenr		n = yygetc(0);
382145510Sdarrenr		if (n == '=') {
383145510Sdarrenr			rval = YY_CMP_NE;
384145510Sdarrenr			goto done;
385145510Sdarrenr		}
386145510Sdarrenr		yyunputc(n);
387145510Sdarrenr		rval = '!';
388145510Sdarrenr		goto done;
389145510Sdarrenr
390145510Sdarrenr	case '<' :
391145510Sdarrenr		if (yyexpectaddr)
392145510Sdarrenr			break;
393145510Sdarrenr		if (isbuilding == 1) {
394145510Sdarrenr			yyunputc(c);
395145510Sdarrenr			goto done;
396145510Sdarrenr		}
397172776Sdarrenr		n = yygetc(0);
398145510Sdarrenr		if (n == '=') {
399145510Sdarrenr			rval = YY_CMP_LE;
400145510Sdarrenr			goto done;
401145510Sdarrenr		}
402145510Sdarrenr		if (n == '>') {
403145510Sdarrenr			rval = YY_RANGE_OUT;
404145510Sdarrenr			goto done;
405145510Sdarrenr		}
406145510Sdarrenr		yyunputc(n);
407145510Sdarrenr		rval = YY_CMP_LT;
408145510Sdarrenr		goto done;
409145510Sdarrenr
410145510Sdarrenr	case '>' :
411145510Sdarrenr		if (yyexpectaddr)
412145510Sdarrenr			break;
413145510Sdarrenr		if (isbuilding == 1) {
414145510Sdarrenr			yyunputc(c);
415145510Sdarrenr			goto done;
416145510Sdarrenr		}
417172776Sdarrenr		n = yygetc(0);
418145510Sdarrenr		if (n == '=') {
419145510Sdarrenr			rval = YY_CMP_GE;
420145510Sdarrenr			goto done;
421145510Sdarrenr		}
422145510Sdarrenr		if (n == '<') {
423145510Sdarrenr			rval = YY_RANGE_IN;
424145510Sdarrenr			goto done;
425145510Sdarrenr		}
426145510Sdarrenr		yyunputc(n);
427145510Sdarrenr		rval = YY_CMP_GT;
428145510Sdarrenr		goto done;
429145510Sdarrenr	}
430145510Sdarrenr
431145510Sdarrenr	/*
432145510Sdarrenr	 * Now for the reason this is here...IPv6 address parsing.
433145510Sdarrenr	 * The longest string we can expect is of this form:
434145510Sdarrenr	 * 0000:0000:0000:0000:0000:0000:000.000.000.000
435145510Sdarrenr	 * not:
436145510Sdarrenr	 * 0000:0000:0000:0000:0000:0000:0000:0000
437145510Sdarrenr	 */
438145510Sdarrenr#ifdef	USE_INET6
439255332Scy	if (yyexpectaddr != 0 && isbuilding == 0 &&
440255332Scy	    (ishex(c) || isdigit(c) || c == ':')) {
441145510Sdarrenr		char ipv6buf[45 + 1], *s, oc;
442145510Sdarrenr		int start;
443145510Sdarrenr
444255332Scybuildipv6:
445145510Sdarrenr		start = yypos;
446145510Sdarrenr		s = ipv6buf;
447145510Sdarrenr		oc = c;
448145510Sdarrenr
449255332Scy		if (prior == YY_NUMBER && c == ':') {
450255332Scy			sprintf(s, "%d", priornum);
451255332Scy			s += strlen(s);
452255332Scy		}
453255332Scy
454145510Sdarrenr		/*
455145510Sdarrenr		 * Perhaps we should implement stricter controls on what we
456145510Sdarrenr		 * swallow up here, but surely it would just be duplicating
457145510Sdarrenr		 * the code in inet_pton() anyway.
458145510Sdarrenr		 */
459145510Sdarrenr		do {
460145510Sdarrenr			*s++ = c;
461172776Sdarrenr			c = yygetc(1);
462145510Sdarrenr		} while ((ishex(c) || c == ':' || c == '.') &&
463145510Sdarrenr			 (s - ipv6buf < 46));
464145510Sdarrenr		yyunputc(c);
465145510Sdarrenr		*s = '\0';
466145510Sdarrenr
467145510Sdarrenr		if (inet_pton(AF_INET6, ipv6buf, &yylval.ip6) == 1) {
468145510Sdarrenr			rval = YY_IPV6;
469145510Sdarrenr			yyexpectaddr = 0;
470145510Sdarrenr			goto done;
471145510Sdarrenr		}
472145510Sdarrenr		yypos = start;
473145510Sdarrenr		c = oc;
474145510Sdarrenr	}
475145510Sdarrenr#endif
476145510Sdarrenr
477255332Scy	if ((c == ':') && (rval != YY_IPV6) && (triedv6 == 0)) {
478255332Scy#ifdef	USE_INET6
479255332Scy		yystr = yytexttostr(0, yypos - 1);
480255332Scy		if (yystr != NULL) {
481255332Scy			char *s;
482255332Scy
483255332Scy			for (s = yystr; *s && ishex(*s); s++)
484255332Scy				;
485255332Scy			if (!*s && *yystr) {
486255332Scy				isbuilding = 0;
487255332Scy				c = *yystr;
488255332Scy				free(yystr);
489255332Scy				triedv6 = 1;
490255332Scy				yypos = 1;
491255332Scy				goto buildipv6;
492255332Scy			}
493255332Scy			free(yystr);
494255332Scy		}
495255332Scy#endif
496145510Sdarrenr		if (isbuilding == 1) {
497145510Sdarrenr			yyunputc(c);
498145510Sdarrenr			goto done;
499145510Sdarrenr		}
500145510Sdarrenr		rval = ':';
501145510Sdarrenr		goto done;
502145510Sdarrenr	}
503145510Sdarrenr
504145510Sdarrenr	if (isbuilding == 0 && c == '0') {
505172776Sdarrenr		n = yygetc(0);
506145510Sdarrenr		if (n == 'x') {
507145510Sdarrenr			do {
508172776Sdarrenr				n = yygetc(1);
509145510Sdarrenr			} while (ishex(n));
510145510Sdarrenr			yyunputc(n);
511145510Sdarrenr			rval = YY_HEX;
512145510Sdarrenr			goto done;
513145510Sdarrenr		}
514145510Sdarrenr		yyunputc(n);
515145510Sdarrenr	}
516145510Sdarrenr
517145510Sdarrenr	/*
518145510Sdarrenr	 * No negative numbers with leading - sign..
519145510Sdarrenr	 */
520145510Sdarrenr	if (isbuilding == 0 && ISDIGIT(c)) {
521145510Sdarrenr		do {
522172776Sdarrenr			n = yygetc(1);
523145510Sdarrenr		} while (ISDIGIT(n));
524145510Sdarrenr		yyunputc(n);
525145510Sdarrenr		rval = YY_NUMBER;
526145510Sdarrenr		goto done;
527145510Sdarrenr	}
528145510Sdarrenr
529145510Sdarrenr	isbuilding = 1;
530145510Sdarrenr	goto nextchar;
531145510Sdarrenr
532145510Sdarrenrdone:
533145510Sdarrenr	yystr = yytexttostr(0, yypos);
534145510Sdarrenr
535170268Sdarrenr	if (yydebug)
536255332Scy		printf("isbuilding %d yyvarnext %d nokey %d fixed %d addr %d\n",
537255332Scy		       isbuilding, yyvarnext, nokey, yydictfixed, yyexpectaddr);
538145510Sdarrenr	if (isbuilding == 1) {
539145510Sdarrenr		wordtab_t *w;
540145510Sdarrenr
541145510Sdarrenr		w = NULL;
542145510Sdarrenr		isbuilding = 0;
543145510Sdarrenr
544145510Sdarrenr		if ((yyvarnext == 0) && (nokey == 0)) {
545145510Sdarrenr			w = yyfindkey(yystr);
546255332Scy			if (w == NULL && yywordtab != NULL && !yydictfixed) {
547145510Sdarrenr				yyresetdict();
548145510Sdarrenr				w = yyfindkey(yystr);
549145510Sdarrenr			}
550145510Sdarrenr		} else
551145510Sdarrenr			yyvarnext = 0;
552145510Sdarrenr		if (w != NULL)
553145510Sdarrenr			rval = w->w_value;
554145510Sdarrenr		else
555145510Sdarrenr			rval = YY_STR;
556145510Sdarrenr	}
557145510Sdarrenr
558255332Scy	if (rval == YY_STR) {
559255332Scy		if (yysavedepth > 0 && !yydictfixed)
560255332Scy			yyresetdict();
561255332Scy		if (yyexpectaddr != 0)
562255332Scy			yyexpectaddr = 0;
563255332Scy	}
564145510Sdarrenr
565145510Sdarrenr	yytokentype = rval;
566145510Sdarrenr
567145510Sdarrenr	if (yydebug)
568255332Scy		printf("lexed(%s) %d,%d,%d [%d,%d,%d] => %d @%d\n",
569255332Scy		       yystr, isbuilding, yyexpectaddr, yysavedepth,
570255332Scy		       string_start, string_end, pos, rval, yysavedepth);
571145510Sdarrenr
572145510Sdarrenr	switch (rval)
573145510Sdarrenr	{
574145510Sdarrenr	case YY_NUMBER :
575145510Sdarrenr		sscanf(yystr, "%u", &yylval.num);
576145510Sdarrenr		break;
577145510Sdarrenr
578145510Sdarrenr	case YY_HEX :
579145510Sdarrenr		sscanf(yystr, "0x%x", (u_int *)&yylval.num);
580145510Sdarrenr		break;
581145510Sdarrenr
582145510Sdarrenr	case YY_STR :
583145510Sdarrenr		yylval.str = strdup(yystr);
584145510Sdarrenr		break;
585145510Sdarrenr
586145510Sdarrenr	default :
587145510Sdarrenr		break;
588145510Sdarrenr	}
589145510Sdarrenr
590145510Sdarrenr	if (yylast > 0) {
591145510Sdarrenr		bcopy(yytext + yypos, yytext,
592145510Sdarrenr		      sizeof(yytext[0]) * (yylast - yypos + 1));
593145510Sdarrenr		yylast -= yypos;
594145510Sdarrenr		yypos = 0;
595145510Sdarrenr	}
596145510Sdarrenr
597255332Scy	if (rval == YY_NUMBER)
598255332Scy		priornum = yylval.num;
599255332Scy	prior = rval;
600145510Sdarrenr	return rval;
601145510Sdarrenr}
602145510Sdarrenr
603145510Sdarrenr
604145510Sdarrenrstatic wordtab_t *yyfindkey(key)
605255332Scy	char *key;
606145510Sdarrenr{
607145510Sdarrenr	wordtab_t *w;
608145510Sdarrenr
609145510Sdarrenr	if (yywordtab == NULL)
610145510Sdarrenr		return NULL;
611145510Sdarrenr
612145510Sdarrenr	for (w = yywordtab; w->w_word != 0; w++)
613145510Sdarrenr		if (strcasecmp(key, w->w_word) == 0)
614145510Sdarrenr			return w;
615145510Sdarrenr	return NULL;
616145510Sdarrenr}
617145510Sdarrenr
618145510Sdarrenr
619145510Sdarrenrchar *yykeytostr(num)
620255332Scy	int num;
621145510Sdarrenr{
622145510Sdarrenr	wordtab_t *w;
623145510Sdarrenr
624145510Sdarrenr	if (yywordtab == NULL)
625145510Sdarrenr		return "<unknown>";
626145510Sdarrenr
627145510Sdarrenr	for (w = yywordtab; w->w_word; w++)
628145510Sdarrenr		if (w->w_value == num)
629145510Sdarrenr			return w->w_word;
630145510Sdarrenr	return "<unknown>";
631145510Sdarrenr}
632145510Sdarrenr
633145510Sdarrenr
634145510Sdarrenrwordtab_t *yysettab(words)
635255332Scy	wordtab_t *words;
636145510Sdarrenr{
637145510Sdarrenr	wordtab_t *save;
638145510Sdarrenr
639145510Sdarrenr	save = yywordtab;
640145510Sdarrenr	yywordtab = words;
641145510Sdarrenr	return save;
642145510Sdarrenr}
643145510Sdarrenr
644145510Sdarrenr
645145510Sdarrenrvoid yyerror(msg)
646255332Scy	char *msg;
647145510Sdarrenr{
648145510Sdarrenr	char *txt, letter[2];
649145510Sdarrenr	int freetxt = 0;
650145510Sdarrenr
651145510Sdarrenr	if (yytokentype < 256) {
652145510Sdarrenr		letter[0] = yytokentype;
653145510Sdarrenr		letter[1] = '\0';
654145510Sdarrenr		txt =  letter;
655145510Sdarrenr	} else if (yytokentype == YY_STR || yytokentype == YY_HEX ||
656145510Sdarrenr		   yytokentype == YY_NUMBER) {
657145510Sdarrenr		if (yystr == NULL) {
658145510Sdarrenr			txt = yytexttostr(yypos, YYBUFSIZ);
659145510Sdarrenr			freetxt = 1;
660145510Sdarrenr		} else
661145510Sdarrenr			txt = yystr;
662145510Sdarrenr	} else {
663145510Sdarrenr		txt = yykeytostr(yytokentype);
664145510Sdarrenr	}
665145510Sdarrenr	fprintf(stderr, "%s error at \"%s\", line %d\n", msg, txt, yylineNum);
666145510Sdarrenr	if (freetxt == 1)
667145510Sdarrenr		free(txt);
668145510Sdarrenr	exit(1);
669145510Sdarrenr}
670145510Sdarrenr
671145510Sdarrenr
672255332Scyvoid yysetfixeddict(newdict)
673255332Scy	wordtab_t *newdict;
674255332Scy{
675255332Scy	if (yydebug)
676255332Scy		printf("yysetfixeddict(%lx)\n", (u_long)newdict);
677255332Scy
678255332Scy	if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) {
679255332Scy		fprintf(stderr, "%d: at maximum dictionary depth\n",
680255332Scy			yylineNum);
681255332Scy		return;
682255332Scy	}
683255332Scy
684255332Scy	yysavewords[yysavedepth++] = yysettab(newdict);
685255332Scy	if (yydebug)
686255332Scy		printf("yysavedepth++ => %d\n", yysavedepth);
687255332Scy	yydictfixed = 1;
688255332Scy}
689255332Scy
690255332Scy
691145510Sdarrenrvoid yysetdict(newdict)
692255332Scy	wordtab_t *newdict;
693145510Sdarrenr{
694255332Scy	if (yydebug)
695255332Scy		printf("yysetdict(%lx)\n", (u_long)newdict);
696255332Scy
697145510Sdarrenr	if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) {
698145510Sdarrenr		fprintf(stderr, "%d: at maximum dictionary depth\n",
699145510Sdarrenr			yylineNum);
700145510Sdarrenr		return;
701145510Sdarrenr	}
702145510Sdarrenr
703145510Sdarrenr	yysavewords[yysavedepth++] = yysettab(newdict);
704145510Sdarrenr	if (yydebug)
705145510Sdarrenr		printf("yysavedepth++ => %d\n", yysavedepth);
706145510Sdarrenr}
707145510Sdarrenr
708145510Sdarrenrvoid yyresetdict()
709145510Sdarrenr{
710170268Sdarrenr	if (yydebug)
711170268Sdarrenr		printf("yyresetdict(%d)\n", yysavedepth);
712145510Sdarrenr	if (yysavedepth > 0) {
713145510Sdarrenr		yysettab(yysavewords[--yysavedepth]);
714145510Sdarrenr		if (yydebug)
715145510Sdarrenr			printf("yysavedepth-- => %d\n", yysavedepth);
716145510Sdarrenr	}
717255332Scy	yydictfixed = 0;
718145510Sdarrenr}
719145510Sdarrenr
720145510Sdarrenr
721145510Sdarrenr
722145510Sdarrenr#ifdef	TEST_LEXER
723145510Sdarrenrint main(argc, argv)
724255332Scy	int argc;
725255332Scy	char *argv[];
726145510Sdarrenr{
727145510Sdarrenr	int n;
728145510Sdarrenr
729145510Sdarrenr	yyin = stdin;
730145510Sdarrenr
731145510Sdarrenr	while ((n = yylex()) != 0)
732145510Sdarrenr		printf("%d.n = %d [%s] %d %d\n",
733145510Sdarrenr			yylineNum, n, yystr, yypos, yylast);
734145510Sdarrenr}
735145510Sdarrenr#endif
736