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