xref: /freebsd/sbin/ipf/common/lexer.c (revision 90818083d795a9c06feca54f32fa6d35c200e1a2)
141edb306SCy Schubert 
241edb306SCy Schubert /*
341edb306SCy Schubert  * Copyright (C) 2012 by Darren Reed.
441edb306SCy Schubert  *
541edb306SCy Schubert  * See the IPFILTER.LICENCE file for details on licencing.
641edb306SCy Schubert  */
741edb306SCy Schubert #include <ctype.h>
841edb306SCy Schubert #include "ipf.h"
941edb306SCy Schubert #ifdef	IPFILTER_SCAN
1041edb306SCy Schubert # include "netinet/ip_scan.h"
1141edb306SCy Schubert #endif
1241edb306SCy Schubert #include <sys/ioctl.h>
1370fad8acSElyes Haouas #include <sys/param.h>
1441edb306SCy Schubert #include <syslog.h>
1541edb306SCy Schubert #ifdef	TEST_LEXER
1641edb306SCy Schubert # define	NO_YACC
1741edb306SCy Schubert union	{
1841edb306SCy Schubert 	int		num;
1941edb306SCy Schubert 	char		*str;
2041edb306SCy Schubert 	struct in_addr	ipa;
2141edb306SCy Schubert 	i6addr_t	ip6;
2241edb306SCy Schubert } yylval;
2341edb306SCy Schubert #endif
2441edb306SCy Schubert #include "lexer.h"
2541edb306SCy Schubert #include "y.tab.h"
2641edb306SCy Schubert 
2741edb306SCy Schubert FILE *yyin;
2841edb306SCy Schubert 
2941edb306SCy Schubert #define	ishex(c)	(ISDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || \
3041edb306SCy Schubert 			 ((c) >= 'A' && (c) <= 'F'))
3141edb306SCy Schubert #define	TOOLONG		-3
3241edb306SCy Schubert 
3341edb306SCy Schubert extern int	string_start;
3441edb306SCy Schubert extern int	string_end;
3541edb306SCy Schubert extern char	*string_val;
3641edb306SCy Schubert extern int	pos;
3741edb306SCy Schubert extern int	yydebug;
3841edb306SCy Schubert 
3941edb306SCy Schubert char		*yystr = NULL;
4041edb306SCy Schubert int		yytext[YYBUFSIZ+1];
4141edb306SCy Schubert char		yychars[YYBUFSIZ+1];
4241edb306SCy Schubert int		yylineNum = 1;
4341edb306SCy Schubert int		yypos = 0;
4441edb306SCy Schubert int		yylast = -1;
4541edb306SCy Schubert int		yydictfixed = 0;
4641edb306SCy Schubert int		yyexpectaddr = 0;
4741edb306SCy Schubert int		yybreakondot = 0;
4841edb306SCy Schubert int		yyvarnext = 0;
4941edb306SCy Schubert int		yytokentype = 0;
5041edb306SCy Schubert wordtab_t	*yywordtab = NULL;
5141edb306SCy Schubert int		yysavedepth = 0;
5241edb306SCy Schubert wordtab_t	*yysavewords[30];
5341edb306SCy Schubert 
5441edb306SCy Schubert 
5541edb306SCy Schubert static	wordtab_t	*yyfindkey(char *);
5641edb306SCy Schubert static	int		yygetc(int);
5741edb306SCy Schubert static	void		yyunputc(int);
5841edb306SCy Schubert static	int		yyswallow(int);
5941edb306SCy Schubert static	char		*yytexttostr(int, int);
6041edb306SCy Schubert static	void		yystrtotext(char *);
6141edb306SCy Schubert static	char		*yytexttochar(void);
6241edb306SCy Schubert 
63efeb8bffSCy Schubert static int
yygetc(int docont)64efeb8bffSCy Schubert yygetc(int docont)
6541edb306SCy Schubert {
6641edb306SCy Schubert 	int c;
6741edb306SCy Schubert 
6841edb306SCy Schubert 	if (yypos < yylast) {
6941edb306SCy Schubert 		c = yytext[yypos++];
7041edb306SCy Schubert 		if (c == '\n')
7141edb306SCy Schubert 			yylineNum++;
722582ae57SCy Schubert 		return (c);
7341edb306SCy Schubert 	}
7441edb306SCy Schubert 
7541edb306SCy Schubert 	if (yypos == YYBUFSIZ)
762582ae57SCy Schubert 		return (TOOLONG);
7741edb306SCy Schubert 
7841edb306SCy Schubert 	if (pos >= string_start && pos <= string_end) {
7941edb306SCy Schubert 		c = string_val[pos - string_start];
8041edb306SCy Schubert 		yypos++;
8141edb306SCy Schubert 	} else {
8241edb306SCy Schubert 		c = fgetc(yyin);
8341edb306SCy Schubert 		if (docont && (c == '\\')) {
8441edb306SCy Schubert 			c = fgetc(yyin);
8541edb306SCy Schubert 			if (c == '\n') {
8641edb306SCy Schubert 				yylineNum++;
8741edb306SCy Schubert 				c = fgetc(yyin);
8841edb306SCy Schubert 			}
8941edb306SCy Schubert 		}
9041edb306SCy Schubert 	}
9141edb306SCy Schubert 	if (c == '\n')
9241edb306SCy Schubert 		yylineNum++;
9341edb306SCy Schubert 	yytext[yypos++] = c;
9441edb306SCy Schubert 	yylast = yypos;
9541edb306SCy Schubert 	yytext[yypos] = '\0';
9641edb306SCy Schubert 
972582ae57SCy Schubert 	return (c);
9841edb306SCy Schubert }
9941edb306SCy Schubert 
10041edb306SCy Schubert 
101efeb8bffSCy Schubert static void
yyunputc(int c)102efeb8bffSCy Schubert yyunputc(int c)
10341edb306SCy Schubert {
10441edb306SCy Schubert 	if (c == '\n')
10541edb306SCy Schubert 		yylineNum--;
10641edb306SCy Schubert 	yytext[--yypos] = c;
10741edb306SCy Schubert }
10841edb306SCy Schubert 
10941edb306SCy Schubert 
110efeb8bffSCy Schubert static int
yyswallow(int last)111efeb8bffSCy Schubert yyswallow(int last)
11241edb306SCy Schubert {
11341edb306SCy Schubert 	int c;
11441edb306SCy Schubert 
11541edb306SCy Schubert 	while (((c = yygetc(0)) > '\0') && (c != last))
11641edb306SCy Schubert 		;
11741edb306SCy Schubert 
11841edb306SCy Schubert 	if (c != EOF)
11941edb306SCy Schubert 		yyunputc(c);
12041edb306SCy Schubert 	if (c == last)
1212582ae57SCy Schubert 		return (0);
1222582ae57SCy Schubert 	return (-1);
12341edb306SCy Schubert }
12441edb306SCy Schubert 
12541edb306SCy Schubert 
126efeb8bffSCy Schubert static char *
yytexttochar(void)127efeb8bffSCy Schubert yytexttochar(void)
12841edb306SCy Schubert {
12941edb306SCy Schubert 	int i;
13041edb306SCy Schubert 
13141edb306SCy Schubert 	for (i = 0; i < yypos; i++)
13241edb306SCy Schubert 		yychars[i] = (char)(yytext[i] & 0xff);
13341edb306SCy Schubert 	yychars[i] = '\0';
1342582ae57SCy Schubert 	return (yychars);
13541edb306SCy Schubert }
13641edb306SCy Schubert 
13741edb306SCy Schubert 
138efeb8bffSCy Schubert static void
yystrtotext(char * str)139efeb8bffSCy Schubert yystrtotext(char *str)
14041edb306SCy Schubert {
14141edb306SCy Schubert 	int len;
14241edb306SCy Schubert 	char *s;
14341edb306SCy Schubert 
14441edb306SCy Schubert 	len = strlen(str);
14541edb306SCy Schubert 	if (len > YYBUFSIZ)
14641edb306SCy Schubert 		len = YYBUFSIZ;
14741edb306SCy Schubert 
14841edb306SCy Schubert 	for (s = str; *s != '\0' && len > 0; s++, len--)
14941edb306SCy Schubert 		yytext[yylast++] = *s;
15041edb306SCy Schubert 	yytext[yylast] = '\0';
15141edb306SCy Schubert }
15241edb306SCy Schubert 
15341edb306SCy Schubert 
154efeb8bffSCy Schubert static char *
yytexttostr(int offset,int max)155efeb8bffSCy Schubert yytexttostr(int offset, int max)
15641edb306SCy Schubert {
15741edb306SCy Schubert 	char *str;
15841edb306SCy Schubert 	int i;
15941edb306SCy Schubert 
16041edb306SCy Schubert 	if ((yytext[offset] == '\'' || yytext[offset] == '"') &&
16141edb306SCy Schubert 	    (yytext[offset] == yytext[offset + max - 1])) {
16241edb306SCy Schubert 		offset++;
16341edb306SCy Schubert 		max--;
16441edb306SCy Schubert 	}
16541edb306SCy Schubert 
16641edb306SCy Schubert 	if (max > yylast)
16741edb306SCy Schubert 		max = yylast;
16841edb306SCy Schubert 	str = malloc(max + 1);
16941edb306SCy Schubert 	if (str != NULL) {
17041edb306SCy Schubert 		for (i = offset; i < max; i++)
17141edb306SCy Schubert 			str[i - offset] = (char)(yytext[i] & 0xff);
17241edb306SCy Schubert 		str[i - offset] = '\0';
17341edb306SCy Schubert 	}
1742582ae57SCy Schubert 	return (str);
17541edb306SCy Schubert }
17641edb306SCy Schubert 
17741edb306SCy Schubert 
178efeb8bffSCy Schubert int
yylex(void)179efeb8bffSCy Schubert yylex(void)
18041edb306SCy Schubert {
18141edb306SCy Schubert 	static int prior = 0;
18241edb306SCy Schubert 	static int priornum = 0;
18341edb306SCy Schubert 	int c, n, isbuilding, rval, lnext, nokey = 0;
18441edb306SCy Schubert 	char *name;
18541edb306SCy Schubert 	int triedv6 = 0;
18641edb306SCy Schubert 
18741edb306SCy Schubert 	isbuilding = 0;
18841edb306SCy Schubert 	lnext = 0;
18941edb306SCy Schubert 	rval = 0;
19041edb306SCy Schubert 
19141edb306SCy Schubert 	if (yystr != NULL) {
19241edb306SCy Schubert 		free(yystr);
19341edb306SCy Schubert 		yystr = NULL;
19441edb306SCy Schubert 	}
19541edb306SCy Schubert 
19641edb306SCy Schubert nextchar:
19741edb306SCy Schubert 	c = yygetc(0);
19841edb306SCy Schubert 	if (yydebug > 1)
19941edb306SCy Schubert 		printf("yygetc = (%x) %c [%*.*s]\n",
20041edb306SCy Schubert 		       c, c, yypos, yypos, yytexttochar());
20141edb306SCy Schubert 
20241edb306SCy Schubert 	switch (c)
20341edb306SCy Schubert 	{
20441edb306SCy Schubert 	case '\n' :
20541edb306SCy Schubert 		lnext = 0;
20641edb306SCy Schubert 		nokey = 0;
20741edb306SCy Schubert 	case '\t' :
20841edb306SCy Schubert 	case '\r' :
20941edb306SCy Schubert 	case ' ' :
21041edb306SCy Schubert 		if (isbuilding == 1) {
21141edb306SCy Schubert 			yyunputc(c);
21241edb306SCy Schubert 			goto done;
21341edb306SCy Schubert 		}
21441edb306SCy Schubert 		if (yylast > yypos) {
21541edb306SCy Schubert 			bcopy(yytext + yypos, yytext,
21641edb306SCy Schubert 			      sizeof(yytext[0]) * (yylast - yypos + 1));
21741edb306SCy Schubert 		}
21841edb306SCy Schubert 		yylast -= yypos;
21941edb306SCy Schubert 		if (yyexpectaddr == 2)
22041edb306SCy Schubert 			yyexpectaddr = 0;
22141edb306SCy Schubert 		yypos = 0;
22241edb306SCy Schubert 		lnext = 0;
22341edb306SCy Schubert 		nokey = 0;
22441edb306SCy Schubert 		goto nextchar;
22541edb306SCy Schubert 
22641edb306SCy Schubert 	case '\\' :
22741edb306SCy Schubert 		if (lnext == 0) {
22841edb306SCy Schubert 			lnext = 1;
22941edb306SCy Schubert 			if (yylast == yypos) {
23041edb306SCy Schubert 				yylast--;
23141edb306SCy Schubert 				yypos--;
23241edb306SCy Schubert 			} else
23341edb306SCy Schubert 				yypos--;
23441edb306SCy Schubert 			if (yypos == 0)
23541edb306SCy Schubert 				nokey = 1;
23641edb306SCy Schubert 			goto nextchar;
23741edb306SCy Schubert 		}
23841edb306SCy Schubert 		break;
23941edb306SCy Schubert 	}
24041edb306SCy Schubert 
24141edb306SCy Schubert 	if (lnext == 1) {
24241edb306SCy Schubert 		lnext = 0;
24341edb306SCy Schubert 		if ((isbuilding == 0) && !ISALNUM(c)) {
24441edb306SCy Schubert 			prior = c;
2452582ae57SCy Schubert 			return (c);
24641edb306SCy Schubert 		}
24741edb306SCy Schubert 		goto nextchar;
24841edb306SCy Schubert 	}
24941edb306SCy Schubert 
25041edb306SCy Schubert 	switch (c)
25141edb306SCy Schubert 	{
25241edb306SCy Schubert 	case '#' :
25341edb306SCy Schubert 		if (isbuilding == 1) {
25441edb306SCy Schubert 			yyunputc(c);
25541edb306SCy Schubert 			goto done;
25641edb306SCy Schubert 		}
25741edb306SCy Schubert 		yyswallow('\n');
25841edb306SCy Schubert 		rval = YY_COMMENT;
25941edb306SCy Schubert 		goto done;
26041edb306SCy Schubert 
26141edb306SCy Schubert 	case '$' :
26241edb306SCy Schubert 		if (isbuilding == 1) {
26341edb306SCy Schubert 			yyunputc(c);
26441edb306SCy Schubert 			goto done;
26541edb306SCy Schubert 		}
26641edb306SCy Schubert 		n = yygetc(0);
26741edb306SCy Schubert 		if (n == '{') {
26841edb306SCy Schubert 			if (yyswallow('}') == -1) {
26941edb306SCy Schubert 				rval = -2;
27041edb306SCy Schubert 				goto done;
27141edb306SCy Schubert 			}
27241edb306SCy Schubert 			(void) yygetc(0);
27341edb306SCy Schubert 		} else {
27441edb306SCy Schubert 			if (!ISALPHA(n)) {
27541edb306SCy Schubert 				yyunputc(n);
27641edb306SCy Schubert 				break;
27741edb306SCy Schubert 			}
27841edb306SCy Schubert 			do {
27941edb306SCy Schubert 				n = yygetc(1);
28041edb306SCy Schubert 			} while (ISALPHA(n) || ISDIGIT(n) || n == '_');
28141edb306SCy Schubert 			yyunputc(n);
28241edb306SCy Schubert 		}
28341edb306SCy Schubert 
28441edb306SCy Schubert 		name = yytexttostr(1, yypos);		/* skip $ */
28541edb306SCy Schubert 
28641edb306SCy Schubert 		if (name != NULL) {
28741edb306SCy Schubert 			string_val = get_variable(name, NULL, yylineNum);
28841edb306SCy Schubert 			free(name);
28941edb306SCy Schubert 			if (string_val != NULL) {
29041edb306SCy Schubert 				name = yytexttostr(yypos, yylast);
29141edb306SCy Schubert 				if (name != NULL) {
29241edb306SCy Schubert 					yypos = 0;
29341edb306SCy Schubert 					yylast = 0;
29441edb306SCy Schubert 					yystrtotext(string_val);
29541edb306SCy Schubert 					yystrtotext(name);
29641edb306SCy Schubert 					free(string_val);
29741edb306SCy Schubert 					free(name);
29841edb306SCy Schubert 					goto nextchar;
29941edb306SCy Schubert 				}
30041edb306SCy Schubert 				free(string_val);
30141edb306SCy Schubert 			}
30241edb306SCy Schubert 		}
30341edb306SCy Schubert 		break;
30441edb306SCy Schubert 
30541edb306SCy Schubert 	case '\'':
30641edb306SCy Schubert 	case '"' :
30741edb306SCy Schubert 		if (isbuilding == 1) {
30841edb306SCy Schubert 			goto done;
30941edb306SCy Schubert 		}
31041edb306SCy Schubert 		do {
31141edb306SCy Schubert 			n = yygetc(1);
31241edb306SCy Schubert 			if (n == EOF || n == TOOLONG) {
31341edb306SCy Schubert 				rval = -2;
31441edb306SCy Schubert 				goto done;
31541edb306SCy Schubert 			}
31641edb306SCy Schubert 			if (n == '\n') {
31741edb306SCy Schubert 				yyunputc(' ');
31841edb306SCy Schubert 				yypos++;
31941edb306SCy Schubert 			}
32041edb306SCy Schubert 		} while (n != c);
32141edb306SCy Schubert 		rval = YY_STR;
32241edb306SCy Schubert 		goto done;
32341edb306SCy Schubert 		/* NOTREACHED */
32441edb306SCy Schubert 
32541edb306SCy Schubert 	case EOF :
32641edb306SCy Schubert 		yylineNum = 1;
32741edb306SCy Schubert 		yypos = 0;
32841edb306SCy Schubert 		yylast = -1;
32941edb306SCy Schubert 		yyexpectaddr = 0;
33041edb306SCy Schubert 		yybreakondot = 0;
33141edb306SCy Schubert 		yyvarnext = 0;
33241edb306SCy Schubert 		yytokentype = 0;
33341edb306SCy Schubert 		if (yydebug)
33441edb306SCy Schubert 			fprintf(stderr, "reset at EOF\n");
33541edb306SCy Schubert 		prior = 0;
3362582ae57SCy Schubert 		return (0);
33741edb306SCy Schubert 	}
33841edb306SCy Schubert 
33941edb306SCy Schubert 	if (strchr("=,/;{}()@", c) != NULL) {
34041edb306SCy Schubert 		if (isbuilding == 1) {
34141edb306SCy Schubert 			yyunputc(c);
34241edb306SCy Schubert 			goto done;
34341edb306SCy Schubert 		}
34441edb306SCy Schubert 		rval = c;
34541edb306SCy Schubert 		goto done;
34641edb306SCy Schubert 	} else if (c == '.') {
34741edb306SCy Schubert 		if (isbuilding == 0) {
34841edb306SCy Schubert 			rval = c;
34941edb306SCy Schubert 			goto done;
35041edb306SCy Schubert 		}
35141edb306SCy Schubert 		if (yybreakondot != 0) {
35241edb306SCy Schubert 			yyunputc(c);
35341edb306SCy Schubert 			goto done;
35441edb306SCy Schubert 		}
35541edb306SCy Schubert 	}
35641edb306SCy Schubert 
35741edb306SCy Schubert 	switch (c)
35841edb306SCy Schubert 	{
35941edb306SCy Schubert 	case '-' :
36041edb306SCy Schubert 		n = yygetc(0);
36141edb306SCy Schubert 		if (n == '>') {
36241edb306SCy Schubert 			isbuilding = 1;
36341edb306SCy Schubert 			goto done;
36441edb306SCy Schubert 		}
36541edb306SCy Schubert 		yyunputc(n);
36641edb306SCy Schubert 		if (yyexpectaddr) {
36741edb306SCy Schubert 			if (isbuilding == 1)
36841edb306SCy Schubert 				yyunputc(c);
36941edb306SCy Schubert 			else
37041edb306SCy Schubert 				rval = '-';
37141edb306SCy Schubert 			goto done;
37241edb306SCy Schubert 		}
37341edb306SCy Schubert 		if (isbuilding == 1)
37441edb306SCy Schubert 			break;
37541edb306SCy Schubert 		rval = '-';
37641edb306SCy Schubert 		goto done;
37741edb306SCy Schubert 
37841edb306SCy Schubert 	case '!' :
37941edb306SCy Schubert 		if (isbuilding == 1) {
38041edb306SCy Schubert 			yyunputc(c);
38141edb306SCy Schubert 			goto done;
38241edb306SCy Schubert 		}
38341edb306SCy Schubert 		n = yygetc(0);
38441edb306SCy Schubert 		if (n == '=') {
38541edb306SCy Schubert 			rval = YY_CMP_NE;
38641edb306SCy Schubert 			goto done;
38741edb306SCy Schubert 		}
38841edb306SCy Schubert 		yyunputc(n);
38941edb306SCy Schubert 		rval = '!';
39041edb306SCy Schubert 		goto done;
39141edb306SCy Schubert 
39241edb306SCy Schubert 	case '<' :
39341edb306SCy Schubert 		if (yyexpectaddr)
39441edb306SCy Schubert 			break;
39541edb306SCy Schubert 		if (isbuilding == 1) {
39641edb306SCy Schubert 			yyunputc(c);
39741edb306SCy Schubert 			goto done;
39841edb306SCy Schubert 		}
39941edb306SCy Schubert 		n = yygetc(0);
40041edb306SCy Schubert 		if (n == '=') {
40141edb306SCy Schubert 			rval = YY_CMP_LE;
40241edb306SCy Schubert 			goto done;
40341edb306SCy Schubert 		}
40441edb306SCy Schubert 		if (n == '>') {
40541edb306SCy Schubert 			rval = YY_RANGE_OUT;
40641edb306SCy Schubert 			goto done;
40741edb306SCy Schubert 		}
40841edb306SCy Schubert 		yyunputc(n);
40941edb306SCy Schubert 		rval = YY_CMP_LT;
41041edb306SCy Schubert 		goto done;
41141edb306SCy Schubert 
41241edb306SCy Schubert 	case '>' :
41341edb306SCy Schubert 		if (yyexpectaddr)
41441edb306SCy Schubert 			break;
41541edb306SCy Schubert 		if (isbuilding == 1) {
41641edb306SCy Schubert 			yyunputc(c);
41741edb306SCy Schubert 			goto done;
41841edb306SCy Schubert 		}
41941edb306SCy Schubert 		n = yygetc(0);
42041edb306SCy Schubert 		if (n == '=') {
42141edb306SCy Schubert 			rval = YY_CMP_GE;
42241edb306SCy Schubert 			goto done;
42341edb306SCy Schubert 		}
42441edb306SCy Schubert 		if (n == '<') {
42541edb306SCy Schubert 			rval = YY_RANGE_IN;
42641edb306SCy Schubert 			goto done;
42741edb306SCy Schubert 		}
42841edb306SCy Schubert 		yyunputc(n);
42941edb306SCy Schubert 		rval = YY_CMP_GT;
43041edb306SCy Schubert 		goto done;
43141edb306SCy Schubert 	}
43241edb306SCy Schubert 
43341edb306SCy Schubert 	/*
43441edb306SCy Schubert 	 * Now for the reason this is here...IPv6 address parsing.
43541edb306SCy Schubert 	 * The longest string we can expect is of this form:
43641edb306SCy Schubert 	 * 0000:0000:0000:0000:0000:0000:000.000.000.000
43741edb306SCy Schubert 	 * not:
43841edb306SCy Schubert 	 * 0000:0000:0000:0000:0000:0000:0000:0000
43941edb306SCy Schubert 	 */
44041edb306SCy Schubert #ifdef	USE_INET6
44141edb306SCy Schubert 	if (yyexpectaddr != 0 && isbuilding == 0 &&
44241edb306SCy Schubert 	    (ishex(c) || isdigit(c) || c == ':')) {
44341edb306SCy Schubert 		char ipv6buf[45 + 1], *s, oc;
44441edb306SCy Schubert 		int start;
44541edb306SCy Schubert 
44641edb306SCy Schubert buildipv6:
44741edb306SCy Schubert 		start = yypos;
44841edb306SCy Schubert 		s = ipv6buf;
44941edb306SCy Schubert 		oc = c;
45041edb306SCy Schubert 
45141edb306SCy Schubert 		if (prior == YY_NUMBER && c == ':') {
452*90818083SRyan Libby 			snprintf(s, sizeof(ipv6buf), "%d", priornum);
45341edb306SCy Schubert 			s += strlen(s);
45441edb306SCy Schubert 		}
45541edb306SCy Schubert 
45641edb306SCy Schubert 		/*
45741edb306SCy Schubert 		 * Perhaps we should implement stricter controls on what we
45841edb306SCy Schubert 		 * swallow up here, but surely it would just be duplicating
45941edb306SCy Schubert 		 * the code in inet_pton() anyway.
46041edb306SCy Schubert 		 */
46141edb306SCy Schubert 		do {
46241edb306SCy Schubert 			*s++ = c;
46341edb306SCy Schubert 			c = yygetc(1);
46441edb306SCy Schubert 		} while ((ishex(c) || c == ':' || c == '.') &&
46541edb306SCy Schubert 			 (s - ipv6buf < 46));
46641edb306SCy Schubert 		yyunputc(c);
46741edb306SCy Schubert 		*s = '\0';
46841edb306SCy Schubert 
46941edb306SCy Schubert 		if (inet_pton(AF_INET6, ipv6buf, &yylval.ip6) == 1) {
47041edb306SCy Schubert 			rval = YY_IPV6;
47141edb306SCy Schubert 			yyexpectaddr = 0;
47241edb306SCy Schubert 			goto done;
47341edb306SCy Schubert 		}
47441edb306SCy Schubert 		yypos = start;
47541edb306SCy Schubert 		c = oc;
47641edb306SCy Schubert 	}
47741edb306SCy Schubert #endif
47841edb306SCy Schubert 
47941edb306SCy Schubert 	if ((c == ':') && (rval != YY_IPV6) && (triedv6 == 0)) {
48041edb306SCy Schubert #ifdef	USE_INET6
48141edb306SCy Schubert 		yystr = yytexttostr(0, yypos - 1);
48241edb306SCy Schubert 		if (yystr != NULL) {
48341edb306SCy Schubert 			char *s;
48441edb306SCy Schubert 
48541edb306SCy Schubert 			for (s = yystr; *s && ishex(*s); s++)
48641edb306SCy Schubert 				;
48741edb306SCy Schubert 			if (!*s && *yystr) {
48841edb306SCy Schubert 				isbuilding = 0;
48941edb306SCy Schubert 				c = *yystr;
49041edb306SCy Schubert 				free(yystr);
49141edb306SCy Schubert 				triedv6 = 1;
49241edb306SCy Schubert 				yypos = 1;
49341edb306SCy Schubert 				goto buildipv6;
49441edb306SCy Schubert 			}
49541edb306SCy Schubert 			free(yystr);
49641edb306SCy Schubert 		}
49741edb306SCy Schubert #endif
49841edb306SCy Schubert 		if (isbuilding == 1) {
49941edb306SCy Schubert 			yyunputc(c);
50041edb306SCy Schubert 			goto done;
50141edb306SCy Schubert 		}
50241edb306SCy Schubert 		rval = ':';
50341edb306SCy Schubert 		goto done;
50441edb306SCy Schubert 	}
50541edb306SCy Schubert 
50641edb306SCy Schubert 	if (isbuilding == 0 && c == '0') {
50741edb306SCy Schubert 		n = yygetc(0);
50841edb306SCy Schubert 		if (n == 'x') {
50941edb306SCy Schubert 			do {
51041edb306SCy Schubert 				n = yygetc(1);
51141edb306SCy Schubert 			} while (ishex(n));
51241edb306SCy Schubert 			yyunputc(n);
51341edb306SCy Schubert 			rval = YY_HEX;
51441edb306SCy Schubert 			goto done;
51541edb306SCy Schubert 		}
51641edb306SCy Schubert 		yyunputc(n);
51741edb306SCy Schubert 	}
51841edb306SCy Schubert 
51941edb306SCy Schubert 	/*
52041edb306SCy Schubert 	 * No negative numbers with leading - sign..
52141edb306SCy Schubert 	 */
52241edb306SCy Schubert 	if (isbuilding == 0 && ISDIGIT(c)) {
52341edb306SCy Schubert 		do {
52441edb306SCy Schubert 			n = yygetc(1);
52541edb306SCy Schubert 		} while (ISDIGIT(n));
52641edb306SCy Schubert 		yyunputc(n);
52741edb306SCy Schubert 		rval = YY_NUMBER;
52841edb306SCy Schubert 		goto done;
52941edb306SCy Schubert 	}
53041edb306SCy Schubert 
53141edb306SCy Schubert 	isbuilding = 1;
53241edb306SCy Schubert 	goto nextchar;
53341edb306SCy Schubert 
53441edb306SCy Schubert done:
53541edb306SCy Schubert 	yystr = yytexttostr(0, yypos);
53641edb306SCy Schubert 
53741edb306SCy Schubert 	if (yydebug)
53841edb306SCy Schubert 		printf("isbuilding %d yyvarnext %d nokey %d fixed %d addr %d\n",
53941edb306SCy Schubert 		       isbuilding, yyvarnext, nokey, yydictfixed, yyexpectaddr);
54041edb306SCy Schubert 	if (isbuilding == 1) {
54141edb306SCy Schubert 		wordtab_t *w;
54241edb306SCy Schubert 
54341edb306SCy Schubert 		w = NULL;
54441edb306SCy Schubert 		isbuilding = 0;
54541edb306SCy Schubert 
54641edb306SCy Schubert 		if ((yyvarnext == 0) && (nokey == 0)) {
54741edb306SCy Schubert 			w = yyfindkey(yystr);
54841edb306SCy Schubert 			if (w == NULL && yywordtab != NULL && !yydictfixed) {
54941edb306SCy Schubert 				yyresetdict();
55041edb306SCy Schubert 				w = yyfindkey(yystr);
55141edb306SCy Schubert 			}
55241edb306SCy Schubert 		} else
55341edb306SCy Schubert 			yyvarnext = 0;
55441edb306SCy Schubert 		if (w != NULL)
55541edb306SCy Schubert 			rval = w->w_value;
55641edb306SCy Schubert 		else
55741edb306SCy Schubert 			rval = YY_STR;
55841edb306SCy Schubert 	}
55941edb306SCy Schubert 
56041edb306SCy Schubert 	if (rval == YY_STR) {
56141edb306SCy Schubert 		if (yysavedepth > 0 && !yydictfixed)
56241edb306SCy Schubert 			yyresetdict();
56341edb306SCy Schubert 		if (yyexpectaddr != 0)
56441edb306SCy Schubert 			yyexpectaddr = 0;
56541edb306SCy Schubert 	}
56641edb306SCy Schubert 
56741edb306SCy Schubert 	yytokentype = rval;
56841edb306SCy Schubert 
56941edb306SCy Schubert 	if (yydebug)
57041edb306SCy Schubert 		printf("lexed(%s) %d,%d,%d [%d,%d,%d] => %d @%d\n",
57141edb306SCy Schubert 		       yystr, isbuilding, yyexpectaddr, yysavedepth,
57241edb306SCy Schubert 		       string_start, string_end, pos, rval, yysavedepth);
57341edb306SCy Schubert 
57441edb306SCy Schubert 	switch (rval)
57541edb306SCy Schubert 	{
57641edb306SCy Schubert 	case YY_NUMBER :
57741edb306SCy Schubert 		sscanf(yystr, "%u", &yylval.num);
57841edb306SCy Schubert 		break;
57941edb306SCy Schubert 
58041edb306SCy Schubert 	case YY_HEX :
58141edb306SCy Schubert 		sscanf(yystr, "0x%x", (u_int *)&yylval.num);
58241edb306SCy Schubert 		break;
58341edb306SCy Schubert 
58441edb306SCy Schubert 	case YY_STR :
58541edb306SCy Schubert 		yylval.str = strdup(yystr);
58641edb306SCy Schubert 		break;
58741edb306SCy Schubert 
58841edb306SCy Schubert 	default :
58941edb306SCy Schubert 		break;
59041edb306SCy Schubert 	}
59141edb306SCy Schubert 
59241edb306SCy Schubert 	if (yylast > 0) {
59341edb306SCy Schubert 		bcopy(yytext + yypos, yytext,
59441edb306SCy Schubert 		      sizeof(yytext[0]) * (yylast - yypos + 1));
59541edb306SCy Schubert 		yylast -= yypos;
59641edb306SCy Schubert 		yypos = 0;
59741edb306SCy Schubert 	}
59841edb306SCy Schubert 
59941edb306SCy Schubert 	if (rval == YY_NUMBER)
60041edb306SCy Schubert 		priornum = yylval.num;
60141edb306SCy Schubert 	prior = rval;
6022582ae57SCy Schubert 	return (rval);
60341edb306SCy Schubert }
60441edb306SCy Schubert 
60541edb306SCy Schubert 
yyfindkey(char * key)6062ac057ddSJohn Baldwin static wordtab_t *yyfindkey(char *key)
60741edb306SCy Schubert {
60841edb306SCy Schubert 	wordtab_t *w;
60941edb306SCy Schubert 
61041edb306SCy Schubert 	if (yywordtab == NULL)
6112582ae57SCy Schubert 		return (NULL);
61241edb306SCy Schubert 
61341edb306SCy Schubert 	for (w = yywordtab; w->w_word != 0; w++)
61441edb306SCy Schubert 		if (strcasecmp(key, w->w_word) == 0)
6152582ae57SCy Schubert 			return (w);
6162582ae57SCy Schubert 	return (NULL);
61741edb306SCy Schubert }
61841edb306SCy Schubert 
61941edb306SCy Schubert 
620efeb8bffSCy Schubert char *
yykeytostr(int num)621efeb8bffSCy Schubert yykeytostr(int num)
62241edb306SCy Schubert {
62341edb306SCy Schubert 	wordtab_t *w;
62441edb306SCy Schubert 
62541edb306SCy Schubert 	if (yywordtab == NULL)
6262582ae57SCy Schubert 		return ("<unknown>");
62741edb306SCy Schubert 
62841edb306SCy Schubert 	for (w = yywordtab; w->w_word; w++)
62941edb306SCy Schubert 		if (w->w_value == num)
6302582ae57SCy Schubert 			return (w->w_word);
6312582ae57SCy Schubert 	return ("<unknown>");
63241edb306SCy Schubert }
63341edb306SCy Schubert 
63441edb306SCy Schubert 
635efeb8bffSCy Schubert wordtab_t *
yysettab(wordtab_t * words)636efeb8bffSCy Schubert yysettab(wordtab_t *words)
63741edb306SCy Schubert {
63841edb306SCy Schubert 	wordtab_t *save;
63941edb306SCy Schubert 
64041edb306SCy Schubert 	save = yywordtab;
64141edb306SCy Schubert 	yywordtab = words;
6422582ae57SCy Schubert 	return (save);
64341edb306SCy Schubert }
64441edb306SCy Schubert 
64541edb306SCy Schubert 
646efeb8bffSCy Schubert void
yyerror(char * msg)647efeb8bffSCy Schubert yyerror(char *msg)
64841edb306SCy Schubert {
64941edb306SCy Schubert 	char *txt, letter[2];
65041edb306SCy Schubert 	int freetxt = 0;
65141edb306SCy Schubert 
65241edb306SCy Schubert 	if (yytokentype < 256) {
65341edb306SCy Schubert 		letter[0] = yytokentype;
65441edb306SCy Schubert 		letter[1] = '\0';
65541edb306SCy Schubert 		txt =  letter;
65641edb306SCy Schubert 	} else if (yytokentype == YY_STR || yytokentype == YY_HEX ||
65741edb306SCy Schubert 		   yytokentype == YY_NUMBER) {
65841edb306SCy Schubert 		if (yystr == NULL) {
65941edb306SCy Schubert 			txt = yytexttostr(yypos, YYBUFSIZ);
66041edb306SCy Schubert 			freetxt = 1;
66141edb306SCy Schubert 		} else
66241edb306SCy Schubert 			txt = yystr;
66341edb306SCy Schubert 	} else {
66441edb306SCy Schubert 		txt = yykeytostr(yytokentype);
66541edb306SCy Schubert 	}
66641edb306SCy Schubert 	fprintf(stderr, "%s error at \"%s\", line %d\n", msg, txt, yylineNum);
66741edb306SCy Schubert 	if (freetxt == 1)
66841edb306SCy Schubert 		free(txt);
66941edb306SCy Schubert 	exit(1);
67041edb306SCy Schubert }
67141edb306SCy Schubert 
67241edb306SCy Schubert 
673efeb8bffSCy Schubert void
yysetfixeddict(wordtab_t * newdict)674efeb8bffSCy Schubert yysetfixeddict(wordtab_t *newdict)
67541edb306SCy Schubert {
67641edb306SCy Schubert 	if (yydebug)
67741edb306SCy Schubert 		printf("yysetfixeddict(%lx)\n", (u_long)newdict);
67841edb306SCy Schubert 
67970fad8acSElyes Haouas 	if (yysavedepth == nitems(yysavewords)) {
68041edb306SCy Schubert 		fprintf(stderr, "%d: at maximum dictionary depth\n",
68141edb306SCy Schubert 			yylineNum);
68241edb306SCy Schubert 		return;
68341edb306SCy Schubert 	}
68441edb306SCy Schubert 
68541edb306SCy Schubert 	yysavewords[yysavedepth++] = yysettab(newdict);
68641edb306SCy Schubert 	if (yydebug)
68741edb306SCy Schubert 		printf("yysavedepth++ => %d\n", yysavedepth);
68841edb306SCy Schubert 	yydictfixed = 1;
68941edb306SCy Schubert }
69041edb306SCy Schubert 
69141edb306SCy Schubert 
692efeb8bffSCy Schubert void
yysetdict(wordtab_t * newdict)693efeb8bffSCy Schubert yysetdict(wordtab_t *newdict)
69441edb306SCy Schubert {
69541edb306SCy Schubert 	if (yydebug)
69641edb306SCy Schubert 		printf("yysetdict(%lx)\n", (u_long)newdict);
69741edb306SCy Schubert 
69870fad8acSElyes Haouas 	if (yysavedepth == nitems(yysavewords)) {
69941edb306SCy Schubert 		fprintf(stderr, "%d: at maximum dictionary depth\n",
70041edb306SCy Schubert 			yylineNum);
70141edb306SCy Schubert 		return;
70241edb306SCy Schubert 	}
70341edb306SCy Schubert 
70441edb306SCy Schubert 	yysavewords[yysavedepth++] = yysettab(newdict);
70541edb306SCy Schubert 	if (yydebug)
70641edb306SCy Schubert 		printf("yysavedepth++ => %d\n", yysavedepth);
70741edb306SCy Schubert }
70841edb306SCy Schubert 
709efeb8bffSCy Schubert void
yyresetdict(void)710efeb8bffSCy Schubert yyresetdict(void)
71141edb306SCy Schubert {
71241edb306SCy Schubert 	if (yydebug)
71341edb306SCy Schubert 		printf("yyresetdict(%d)\n", yysavedepth);
71441edb306SCy Schubert 	if (yysavedepth > 0) {
71541edb306SCy Schubert 		yysettab(yysavewords[--yysavedepth]);
71641edb306SCy Schubert 		if (yydebug)
71741edb306SCy Schubert 			printf("yysavedepth-- => %d\n", yysavedepth);
71841edb306SCy Schubert 	}
71941edb306SCy Schubert 	yydictfixed = 0;
72041edb306SCy Schubert }
72141edb306SCy Schubert 
72241edb306SCy Schubert 
72341edb306SCy Schubert 
72441edb306SCy Schubert #ifdef	TEST_LEXER
725efeb8bffSCy Schubert int
main(int argc,char * argv[])726efeb8bffSCy Schubert main(int argc, char *argv[])
72741edb306SCy Schubert {
72841edb306SCy Schubert 	int n;
72941edb306SCy Schubert 
73041edb306SCy Schubert 	yyin = stdin;
73141edb306SCy Schubert 
73241edb306SCy Schubert 	while ((n = yylex()) != 0)
73341edb306SCy Schubert 		printf("%d.n = %d [%s] %d %d\n",
73441edb306SCy Schubert 			yylineNum, n, yystr, yypos, yylast);
73541edb306SCy Schubert }
73641edb306SCy Schubert #endif
737