1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
3145510Sdarrenr/*
4170268Sdarrenr * Copyright (C) 2002-2006 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;
45145510Sdarrenrint		yyexpectaddr = 0;
46145510Sdarrenrint		yybreakondot = 0;
47145510Sdarrenrint		yyvarnext = 0;
48145510Sdarrenrint		yytokentype = 0;
49145510Sdarrenrwordtab_t	*yywordtab = NULL;
50145510Sdarrenrint		yysavedepth = 0;
51145510Sdarrenrwordtab_t	*yysavewords[30];
52145510Sdarrenr
53145510Sdarrenr
54145510Sdarrenrstatic	wordtab_t	*yyfindkey __P((char *));
55172776Sdarrenrstatic	int		yygetc __P((int));
56145510Sdarrenrstatic	void		yyunputc __P((int));
57145510Sdarrenrstatic	int		yyswallow __P((int));
58145510Sdarrenrstatic	char		*yytexttostr __P((int, int));
59145510Sdarrenrstatic	void		yystrtotext __P((char *));
60172776Sdarrenrstatic	char		*yytexttochar __P((void));
61145510Sdarrenr
62172776Sdarrenrstatic int yygetc(docont)
63172776Sdarrenrint docont;
64145510Sdarrenr{
65145510Sdarrenr	int c;
66145510Sdarrenr
67145510Sdarrenr	if (yypos < yylast) {
68145510Sdarrenr		c = yytext[yypos++];
69145510Sdarrenr		if (c == '\n')
70145510Sdarrenr			yylineNum++;
71145510Sdarrenr		return c;
72145510Sdarrenr	}
73145510Sdarrenr
74145510Sdarrenr	if (yypos == YYBUFSIZ)
75145510Sdarrenr		return TOOLONG;
76145510Sdarrenr
77145510Sdarrenr	if (pos >= string_start && pos <= string_end) {
78145510Sdarrenr		c = string_val[pos - string_start];
79145510Sdarrenr		yypos++;
80145510Sdarrenr	} else {
81145510Sdarrenr		c = fgetc(yyin);
82172776Sdarrenr		if (docont && (c == '\\')) {
83172776Sdarrenr			c = fgetc(yyin);
84172776Sdarrenr			if (c == '\n') {
85172776Sdarrenr				yylineNum++;
86172776Sdarrenr				c = fgetc(yyin);
87172776Sdarrenr			}
88172776Sdarrenr		}
89145510Sdarrenr	}
90145510Sdarrenr	if (c == '\n')
91145510Sdarrenr		yylineNum++;
92145510Sdarrenr	yytext[yypos++] = c;
93145510Sdarrenr	yylast = yypos;
94145510Sdarrenr	yytext[yypos] = '\0';
95145510Sdarrenr
96145510Sdarrenr	return c;
97145510Sdarrenr}
98145510Sdarrenr
99145510Sdarrenr
100145510Sdarrenrstatic void yyunputc(c)
101145510Sdarrenrint c;
102145510Sdarrenr{
103145510Sdarrenr	if (c == '\n')
104145510Sdarrenr		yylineNum--;
105145510Sdarrenr	yytext[--yypos] = c;
106145510Sdarrenr}
107145510Sdarrenr
108145510Sdarrenr
109145510Sdarrenrstatic int yyswallow(last)
110145510Sdarrenrint last;
111145510Sdarrenr{
112145510Sdarrenr	int c;
113145510Sdarrenr
114172776Sdarrenr	while (((c = yygetc(0)) > '\0') && (c != last))
115145510Sdarrenr		;
116145510Sdarrenr
117145510Sdarrenr	if (c != EOF)
118145510Sdarrenr		yyunputc(c);
119145510Sdarrenr	if (c == last)
120145510Sdarrenr		return 0;
121145510Sdarrenr	return -1;
122145510Sdarrenr}
123145510Sdarrenr
124145510Sdarrenr
125172776Sdarrenrstatic char *yytexttochar()
126172776Sdarrenr{
127172776Sdarrenr	int i;
128172776Sdarrenr
129172776Sdarrenr	for (i = 0; i < yypos; i++)
130172776Sdarrenr		yychars[i] = (char)(yytext[i] & 0xff);
131172776Sdarrenr	yychars[i] = '\0';
132172776Sdarrenr	return yychars;
133172776Sdarrenr}
134172776Sdarrenr
135172776Sdarrenr
136145510Sdarrenrstatic void yystrtotext(str)
137145510Sdarrenrchar *str;
138145510Sdarrenr{
139145510Sdarrenr	int len;
140145510Sdarrenr	char *s;
141145510Sdarrenr
142145510Sdarrenr	len = strlen(str);
143145510Sdarrenr	if (len > YYBUFSIZ)
144145510Sdarrenr		len = YYBUFSIZ;
145145510Sdarrenr
146145510Sdarrenr	for (s = str; *s != '\0' && len > 0; s++, len--)
147145510Sdarrenr		yytext[yylast++] = *s;
148145510Sdarrenr	yytext[yylast] = '\0';
149145510Sdarrenr}
150145510Sdarrenr
151145510Sdarrenr
152145510Sdarrenrstatic char *yytexttostr(offset, max)
153145510Sdarrenrint offset, max;
154145510Sdarrenr{
155145510Sdarrenr	char *str;
156145510Sdarrenr	int i;
157145510Sdarrenr
158145510Sdarrenr	if ((yytext[offset] == '\'' || yytext[offset] == '"') &&
159145510Sdarrenr	    (yytext[offset] == yytext[offset + max - 1])) {
160145510Sdarrenr		offset++;
161145510Sdarrenr		max--;
162145510Sdarrenr	}
163145510Sdarrenr
164145510Sdarrenr	if (max > yylast)
165145510Sdarrenr		max = yylast;
166145510Sdarrenr	str = malloc(max + 1);
167145510Sdarrenr	if (str != NULL) {
168145510Sdarrenr		for (i = offset; i < max; i++)
169145510Sdarrenr			str[i - offset] = (char)(yytext[i] & 0xff);
170145510Sdarrenr		str[i - offset] = '\0';
171145510Sdarrenr	}
172145510Sdarrenr	return str;
173145510Sdarrenr}
174145510Sdarrenr
175145510Sdarrenr
176145510Sdarrenrint yylex()
177145510Sdarrenr{
178145510Sdarrenr	int c, n, isbuilding, rval, lnext, nokey = 0;
179145510Sdarrenr	char *name;
180145510Sdarrenr
181145510Sdarrenr	isbuilding = 0;
182145510Sdarrenr	lnext = 0;
183145510Sdarrenr	rval = 0;
184145510Sdarrenr
185145510Sdarrenr	if (yystr != NULL) {
186145510Sdarrenr		free(yystr);
187145510Sdarrenr		yystr = NULL;
188145510Sdarrenr	}
189145510Sdarrenr
190145510Sdarrenrnextchar:
191172776Sdarrenr	c = yygetc(0);
192172776Sdarrenr	if (yydebug > 1)
193172776Sdarrenr		printf("yygetc = (%x) %c [%*.*s]\n", c, c, yypos, yypos, yytexttochar());
194145510Sdarrenr
195145510Sdarrenr	switch (c)
196145510Sdarrenr	{
197145510Sdarrenr	case '\n' :
198161357Sguido		lnext = 0;
199161357Sguido		nokey = 0;
200145510Sdarrenr	case '\t' :
201145510Sdarrenr	case '\r' :
202145510Sdarrenr	case ' ' :
203145510Sdarrenr		if (isbuilding == 1) {
204145510Sdarrenr			yyunputc(c);
205145510Sdarrenr			goto done;
206145510Sdarrenr		}
207145510Sdarrenr		if (yylast > yypos) {
208145510Sdarrenr			bcopy(yytext + yypos, yytext,
209145510Sdarrenr			      sizeof(yytext[0]) * (yylast - yypos + 1));
210145510Sdarrenr		}
211145510Sdarrenr		yylast -= yypos;
212145510Sdarrenr		yypos = 0;
213145510Sdarrenr		lnext = 0;
214145510Sdarrenr		nokey = 0;
215145510Sdarrenr		goto nextchar;
216145510Sdarrenr
217145510Sdarrenr	case '\\' :
218145510Sdarrenr		if (lnext == 0) {
219145510Sdarrenr			lnext = 1;
220145510Sdarrenr			if (yylast == yypos) {
221145510Sdarrenr				yylast--;
222145510Sdarrenr				yypos--;
223145510Sdarrenr			} else
224145510Sdarrenr				yypos--;
225145510Sdarrenr			if (yypos == 0)
226145510Sdarrenr				nokey = 1;
227145510Sdarrenr			goto nextchar;
228145510Sdarrenr		}
229145510Sdarrenr		break;
230145510Sdarrenr	}
231145510Sdarrenr
232145510Sdarrenr	if (lnext == 1) {
233145510Sdarrenr		lnext = 0;
234145510Sdarrenr		if ((isbuilding == 0) && !ISALNUM(c)) {
235145510Sdarrenr			return c;
236145510Sdarrenr		}
237145510Sdarrenr		goto nextchar;
238145510Sdarrenr	}
239145510Sdarrenr
240145510Sdarrenr	switch (c)
241145510Sdarrenr	{
242145510Sdarrenr	case '#' :
243145510Sdarrenr		if (isbuilding == 1) {
244145510Sdarrenr			yyunputc(c);
245145510Sdarrenr			goto done;
246145510Sdarrenr		}
247145510Sdarrenr		yyswallow('\n');
248145510Sdarrenr		rval = YY_COMMENT;
249145510Sdarrenr		goto nextchar;
250145510Sdarrenr
251145510Sdarrenr	case '$' :
252145510Sdarrenr		if (isbuilding == 1) {
253145510Sdarrenr			yyunputc(c);
254145510Sdarrenr			goto done;
255145510Sdarrenr		}
256172776Sdarrenr		n = yygetc(0);
257145510Sdarrenr		if (n == '{') {
258145510Sdarrenr			if (yyswallow('}') == -1) {
259145510Sdarrenr				rval = -2;
260145510Sdarrenr				goto done;
261145510Sdarrenr			}
262172776Sdarrenr			(void) yygetc(0);
263145510Sdarrenr		} else {
264145510Sdarrenr			if (!ISALPHA(n)) {
265145510Sdarrenr				yyunputc(n);
266145510Sdarrenr				break;
267145510Sdarrenr			}
268145510Sdarrenr			do {
269172776Sdarrenr				n = yygetc(1);
270145510Sdarrenr			} while (ISALPHA(n) || ISDIGIT(n) || n == '_');
271145510Sdarrenr			yyunputc(n);
272145510Sdarrenr		}
273145510Sdarrenr
274145510Sdarrenr		name = yytexttostr(1, yypos);		/* skip $ */
275145510Sdarrenr
276145510Sdarrenr		if (name != NULL) {
277145510Sdarrenr			string_val = get_variable(name, NULL, yylineNum);
278145510Sdarrenr			free(name);
279145510Sdarrenr			if (string_val != NULL) {
280145510Sdarrenr				name = yytexttostr(yypos, yylast);
281145510Sdarrenr				if (name != NULL) {
282145510Sdarrenr					yypos = 0;
283145510Sdarrenr					yylast = 0;
284145510Sdarrenr					yystrtotext(string_val);
285145510Sdarrenr					yystrtotext(name);
286145510Sdarrenr					free(string_val);
287145510Sdarrenr					free(name);
288145510Sdarrenr					goto nextchar;
289145510Sdarrenr				}
290145510Sdarrenr				free(string_val);
291145510Sdarrenr			}
292145510Sdarrenr		}
293145510Sdarrenr		break;
294145510Sdarrenr
295145510Sdarrenr	case '\'':
296145510Sdarrenr	case '"' :
297145510Sdarrenr		if (isbuilding == 1) {
298145510Sdarrenr			goto done;
299145510Sdarrenr		}
300145510Sdarrenr		do {
301172776Sdarrenr			n = yygetc(1);
302145510Sdarrenr			if (n == EOF || n == TOOLONG) {
303145510Sdarrenr				rval = -2;
304145510Sdarrenr				goto done;
305145510Sdarrenr			}
306145510Sdarrenr			if (n == '\n') {
307145510Sdarrenr				yyunputc(' ');
308145510Sdarrenr				yypos++;
309145510Sdarrenr			}
310145510Sdarrenr		} while (n != c);
311170268Sdarrenr		rval = YY_STR;
312170268Sdarrenr		goto done;
313170268Sdarrenr		/* NOTREACHED */
314145510Sdarrenr
315145510Sdarrenr	case EOF :
316145510Sdarrenr		yylineNum = 1;
317145510Sdarrenr		yypos = 0;
318145510Sdarrenr		yylast = -1;
319145510Sdarrenr		yyexpectaddr = 0;
320145510Sdarrenr		yybreakondot = 0;
321145510Sdarrenr		yyvarnext = 0;
322145510Sdarrenr		yytokentype = 0;
323145510Sdarrenr		return 0;
324145510Sdarrenr	}
325145510Sdarrenr
326145510Sdarrenr	if (strchr("=,/;{}()@", c) != NULL) {
327145510Sdarrenr		if (isbuilding == 1) {
328145510Sdarrenr			yyunputc(c);
329145510Sdarrenr			goto done;
330145510Sdarrenr		}
331145510Sdarrenr		rval = c;
332145510Sdarrenr		goto done;
333145510Sdarrenr	} else if (c == '.') {
334145510Sdarrenr		if (isbuilding == 0) {
335145510Sdarrenr			rval = c;
336145510Sdarrenr			goto done;
337145510Sdarrenr		}
338145510Sdarrenr		if (yybreakondot != 0) {
339145510Sdarrenr			yyunputc(c);
340145510Sdarrenr			goto done;
341145510Sdarrenr		}
342145510Sdarrenr	}
343145510Sdarrenr
344145510Sdarrenr	switch (c)
345145510Sdarrenr	{
346145510Sdarrenr	case '-' :
347145510Sdarrenr		if (yyexpectaddr)
348145510Sdarrenr			break;
349145510Sdarrenr		if (isbuilding == 1)
350145510Sdarrenr			break;
351172776Sdarrenr		n = yygetc(0);
352145510Sdarrenr		if (n == '>') {
353145510Sdarrenr			isbuilding = 1;
354145510Sdarrenr			goto done;
355145510Sdarrenr		}
356145510Sdarrenr		yyunputc(n);
357145510Sdarrenr		rval = '-';
358145510Sdarrenr		goto done;
359145510Sdarrenr
360145510Sdarrenr	case '!' :
361145510Sdarrenr		if (isbuilding == 1) {
362145510Sdarrenr			yyunputc(c);
363145510Sdarrenr			goto done;
364145510Sdarrenr		}
365172776Sdarrenr		n = yygetc(0);
366145510Sdarrenr		if (n == '=') {
367145510Sdarrenr			rval = YY_CMP_NE;
368145510Sdarrenr			goto done;
369145510Sdarrenr		}
370145510Sdarrenr		yyunputc(n);
371145510Sdarrenr		rval = '!';
372145510Sdarrenr		goto done;
373145510Sdarrenr
374145510Sdarrenr	case '<' :
375145510Sdarrenr		if (yyexpectaddr)
376145510Sdarrenr			break;
377145510Sdarrenr		if (isbuilding == 1) {
378145510Sdarrenr			yyunputc(c);
379145510Sdarrenr			goto done;
380145510Sdarrenr		}
381172776Sdarrenr		n = yygetc(0);
382145510Sdarrenr		if (n == '=') {
383145510Sdarrenr			rval = YY_CMP_LE;
384145510Sdarrenr			goto done;
385145510Sdarrenr		}
386145510Sdarrenr		if (n == '>') {
387145510Sdarrenr			rval = YY_RANGE_OUT;
388145510Sdarrenr			goto done;
389145510Sdarrenr		}
390145510Sdarrenr		yyunputc(n);
391145510Sdarrenr		rval = YY_CMP_LT;
392145510Sdarrenr		goto done;
393145510Sdarrenr
394145510Sdarrenr	case '>' :
395145510Sdarrenr		if (yyexpectaddr)
396145510Sdarrenr			break;
397145510Sdarrenr		if (isbuilding == 1) {
398145510Sdarrenr			yyunputc(c);
399145510Sdarrenr			goto done;
400145510Sdarrenr		}
401172776Sdarrenr		n = yygetc(0);
402145510Sdarrenr		if (n == '=') {
403145510Sdarrenr			rval = YY_CMP_GE;
404145510Sdarrenr			goto done;
405145510Sdarrenr		}
406145510Sdarrenr		if (n == '<') {
407145510Sdarrenr			rval = YY_RANGE_IN;
408145510Sdarrenr			goto done;
409145510Sdarrenr		}
410145510Sdarrenr		yyunputc(n);
411145510Sdarrenr		rval = YY_CMP_GT;
412145510Sdarrenr		goto done;
413145510Sdarrenr	}
414145510Sdarrenr
415145510Sdarrenr	/*
416145510Sdarrenr	 * Now for the reason this is here...IPv6 address parsing.
417145510Sdarrenr	 * The longest string we can expect is of this form:
418145510Sdarrenr	 * 0000:0000:0000:0000:0000:0000:000.000.000.000
419145510Sdarrenr	 * not:
420145510Sdarrenr	 * 0000:0000:0000:0000:0000:0000:0000:0000
421145510Sdarrenr	 */
422145510Sdarrenr#ifdef	USE_INET6
423145510Sdarrenr	if (yyexpectaddr == 1 && isbuilding == 0 && (ishex(c) || c == ':')) {
424145510Sdarrenr		char ipv6buf[45 + 1], *s, oc;
425145510Sdarrenr		int start;
426145510Sdarrenr
427145510Sdarrenr		start = yypos;
428145510Sdarrenr		s = ipv6buf;
429145510Sdarrenr		oc = c;
430145510Sdarrenr
431145510Sdarrenr		/*
432145510Sdarrenr		 * Perhaps we should implement stricter controls on what we
433145510Sdarrenr		 * swallow up here, but surely it would just be duplicating
434145510Sdarrenr		 * the code in inet_pton() anyway.
435145510Sdarrenr		 */
436145510Sdarrenr		do {
437145510Sdarrenr			*s++ = c;
438172776Sdarrenr			c = yygetc(1);
439145510Sdarrenr		} while ((ishex(c) || c == ':' || c == '.') &&
440145510Sdarrenr			 (s - ipv6buf < 46));
441145510Sdarrenr		yyunputc(c);
442145510Sdarrenr		*s = '\0';
443145510Sdarrenr
444145510Sdarrenr		if (inet_pton(AF_INET6, ipv6buf, &yylval.ip6) == 1) {
445145510Sdarrenr			rval = YY_IPV6;
446145510Sdarrenr			yyexpectaddr = 0;
447145510Sdarrenr			goto done;
448145510Sdarrenr		}
449145510Sdarrenr		yypos = start;
450145510Sdarrenr		c = oc;
451145510Sdarrenr	}
452145510Sdarrenr#endif
453145510Sdarrenr
454145510Sdarrenr	if (c == ':') {
455145510Sdarrenr		if (isbuilding == 1) {
456145510Sdarrenr			yyunputc(c);
457145510Sdarrenr			goto done;
458145510Sdarrenr		}
459145510Sdarrenr		rval = ':';
460145510Sdarrenr		goto done;
461145510Sdarrenr	}
462145510Sdarrenr
463145510Sdarrenr	if (isbuilding == 0 && c == '0') {
464172776Sdarrenr		n = yygetc(0);
465145510Sdarrenr		if (n == 'x') {
466145510Sdarrenr			do {
467172776Sdarrenr				n = yygetc(1);
468145510Sdarrenr			} while (ishex(n));
469145510Sdarrenr			yyunputc(n);
470145510Sdarrenr			rval = YY_HEX;
471145510Sdarrenr			goto done;
472145510Sdarrenr		}
473145510Sdarrenr		yyunputc(n);
474145510Sdarrenr	}
475145510Sdarrenr
476145510Sdarrenr	/*
477145510Sdarrenr	 * No negative numbers with leading - sign..
478145510Sdarrenr	 */
479145510Sdarrenr	if (isbuilding == 0 && ISDIGIT(c)) {
480145510Sdarrenr		do {
481172776Sdarrenr			n = yygetc(1);
482145510Sdarrenr		} while (ISDIGIT(n));
483145510Sdarrenr		yyunputc(n);
484145510Sdarrenr		rval = YY_NUMBER;
485145510Sdarrenr		goto done;
486145510Sdarrenr	}
487145510Sdarrenr
488145510Sdarrenr	isbuilding = 1;
489145510Sdarrenr	goto nextchar;
490145510Sdarrenr
491145510Sdarrenrdone:
492145510Sdarrenr	yystr = yytexttostr(0, yypos);
493145510Sdarrenr
494170268Sdarrenr	if (yydebug)
495170268Sdarrenr		printf("isbuilding %d yyvarnext %d nokey %d\n",
496170268Sdarrenr		       isbuilding, yyvarnext, nokey);
497145510Sdarrenr	if (isbuilding == 1) {
498145510Sdarrenr		wordtab_t *w;
499145510Sdarrenr
500145510Sdarrenr		w = NULL;
501145510Sdarrenr		isbuilding = 0;
502145510Sdarrenr
503145510Sdarrenr		if ((yyvarnext == 0) && (nokey == 0)) {
504145510Sdarrenr			w = yyfindkey(yystr);
505145510Sdarrenr			if (w == NULL && yywordtab != NULL) {
506145510Sdarrenr				yyresetdict();
507145510Sdarrenr				w = yyfindkey(yystr);
508145510Sdarrenr			}
509145510Sdarrenr		} else
510145510Sdarrenr			yyvarnext = 0;
511145510Sdarrenr		if (w != NULL)
512145510Sdarrenr			rval = w->w_value;
513145510Sdarrenr		else
514145510Sdarrenr			rval = YY_STR;
515145510Sdarrenr	}
516145510Sdarrenr
517145510Sdarrenr	if (rval == YY_STR && yysavedepth > 0)
518145510Sdarrenr		yyresetdict();
519145510Sdarrenr
520145510Sdarrenr	yytokentype = rval;
521145510Sdarrenr
522145510Sdarrenr	if (yydebug)
523170268Sdarrenr		printf("lexed(%s) [%d,%d,%d] => %d @%d\n", yystr, string_start,
524170268Sdarrenr			string_end, pos, rval, yysavedepth);
525145510Sdarrenr
526145510Sdarrenr	switch (rval)
527145510Sdarrenr	{
528145510Sdarrenr	case YY_NUMBER :
529145510Sdarrenr		sscanf(yystr, "%u", &yylval.num);
530145510Sdarrenr		break;
531145510Sdarrenr
532145510Sdarrenr	case YY_HEX :
533145510Sdarrenr		sscanf(yystr, "0x%x", (u_int *)&yylval.num);
534145510Sdarrenr		break;
535145510Sdarrenr
536145510Sdarrenr	case YY_STR :
537145510Sdarrenr		yylval.str = strdup(yystr);
538145510Sdarrenr		break;
539145510Sdarrenr
540145510Sdarrenr	default :
541145510Sdarrenr		break;
542145510Sdarrenr	}
543145510Sdarrenr
544145510Sdarrenr	if (yylast > 0) {
545145510Sdarrenr		bcopy(yytext + yypos, yytext,
546145510Sdarrenr		      sizeof(yytext[0]) * (yylast - yypos + 1));
547145510Sdarrenr		yylast -= yypos;
548145510Sdarrenr		yypos = 0;
549145510Sdarrenr	}
550145510Sdarrenr
551145510Sdarrenr	return rval;
552145510Sdarrenr}
553145510Sdarrenr
554145510Sdarrenr
555145510Sdarrenrstatic wordtab_t *yyfindkey(key)
556145510Sdarrenrchar *key;
557145510Sdarrenr{
558145510Sdarrenr	wordtab_t *w;
559145510Sdarrenr
560145510Sdarrenr	if (yywordtab == NULL)
561145510Sdarrenr		return NULL;
562145510Sdarrenr
563145510Sdarrenr	for (w = yywordtab; w->w_word != 0; w++)
564145510Sdarrenr		if (strcasecmp(key, w->w_word) == 0)
565145510Sdarrenr			return w;
566145510Sdarrenr	return NULL;
567145510Sdarrenr}
568145510Sdarrenr
569145510Sdarrenr
570145510Sdarrenrchar *yykeytostr(num)
571145510Sdarrenrint num;
572145510Sdarrenr{
573145510Sdarrenr	wordtab_t *w;
574145510Sdarrenr
575145510Sdarrenr	if (yywordtab == NULL)
576145510Sdarrenr		return "<unknown>";
577145510Sdarrenr
578145510Sdarrenr	for (w = yywordtab; w->w_word; w++)
579145510Sdarrenr		if (w->w_value == num)
580145510Sdarrenr			return w->w_word;
581145510Sdarrenr	return "<unknown>";
582145510Sdarrenr}
583145510Sdarrenr
584145510Sdarrenr
585145510Sdarrenrwordtab_t *yysettab(words)
586145510Sdarrenrwordtab_t *words;
587145510Sdarrenr{
588145510Sdarrenr	wordtab_t *save;
589145510Sdarrenr
590145510Sdarrenr	save = yywordtab;
591145510Sdarrenr	yywordtab = words;
592145510Sdarrenr	return save;
593145510Sdarrenr}
594145510Sdarrenr
595145510Sdarrenr
596145510Sdarrenrvoid yyerror(msg)
597145510Sdarrenrchar *msg;
598145510Sdarrenr{
599145510Sdarrenr	char *txt, letter[2];
600145510Sdarrenr	int freetxt = 0;
601145510Sdarrenr
602145510Sdarrenr	if (yytokentype < 256) {
603145510Sdarrenr		letter[0] = yytokentype;
604145510Sdarrenr		letter[1] = '\0';
605145510Sdarrenr		txt =  letter;
606145510Sdarrenr	} else if (yytokentype == YY_STR || yytokentype == YY_HEX ||
607145510Sdarrenr		   yytokentype == YY_NUMBER) {
608145510Sdarrenr		if (yystr == NULL) {
609145510Sdarrenr			txt = yytexttostr(yypos, YYBUFSIZ);
610145510Sdarrenr			freetxt = 1;
611145510Sdarrenr		} else
612145510Sdarrenr			txt = yystr;
613145510Sdarrenr	} else {
614145510Sdarrenr		txt = yykeytostr(yytokentype);
615145510Sdarrenr	}
616145510Sdarrenr	fprintf(stderr, "%s error at \"%s\", line %d\n", msg, txt, yylineNum);
617145510Sdarrenr	if (freetxt == 1)
618145510Sdarrenr		free(txt);
619145510Sdarrenr	exit(1);
620145510Sdarrenr}
621145510Sdarrenr
622145510Sdarrenr
623145510Sdarrenrvoid yysetdict(newdict)
624145510Sdarrenrwordtab_t *newdict;
625145510Sdarrenr{
626145510Sdarrenr	if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) {
627145510Sdarrenr		fprintf(stderr, "%d: at maximum dictionary depth\n",
628145510Sdarrenr			yylineNum);
629145510Sdarrenr		return;
630145510Sdarrenr	}
631145510Sdarrenr
632145510Sdarrenr	yysavewords[yysavedepth++] = yysettab(newdict);
633145510Sdarrenr	if (yydebug)
634145510Sdarrenr		printf("yysavedepth++ => %d\n", yysavedepth);
635145510Sdarrenr}
636145510Sdarrenr
637145510Sdarrenrvoid yyresetdict()
638145510Sdarrenr{
639170268Sdarrenr	if (yydebug)
640170268Sdarrenr		printf("yyresetdict(%d)\n", yysavedepth);
641145510Sdarrenr	if (yysavedepth > 0) {
642145510Sdarrenr		yysettab(yysavewords[--yysavedepth]);
643145510Sdarrenr		if (yydebug)
644145510Sdarrenr			printf("yysavedepth-- => %d\n", yysavedepth);
645145510Sdarrenr	}
646145510Sdarrenr}
647145510Sdarrenr
648145510Sdarrenr
649145510Sdarrenr
650145510Sdarrenr#ifdef	TEST_LEXER
651145510Sdarrenrint main(argc, argv)
652145510Sdarrenrint argc;
653145510Sdarrenrchar *argv[];
654145510Sdarrenr{
655145510Sdarrenr	int n;
656145510Sdarrenr
657145510Sdarrenr	yyin = stdin;
658145510Sdarrenr
659145510Sdarrenr	while ((n = yylex()) != 0)
660145510Sdarrenr		printf("%d.n = %d [%s] %d %d\n",
661145510Sdarrenr			yylineNum, n, yystr, yypos, yylast);
662145510Sdarrenr}
663145510Sdarrenr#endif
664