Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ipf / tools / lexer.c
blob64d0d15a3be22f7d7d6432659acd5d01cff7d7bc
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2002-2006 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8 #include <ctype.h>
9 #include "ipf.h"
10 #ifdef IPFILTER_SCAN
11 # include "netinet/ip_scan.h"
12 #endif
13 #include <sys/ioctl.h>
14 #include <syslog.h>
15 #ifdef TEST_LEXER
16 # define NO_YACC
17 union {
18 int num;
19 char *str;
20 struct in_addr ipa;
21 i6addr_t ip6;
22 } yylval;
23 #endif
24 #include "lexer.h"
25 #include "y.tab.h"
27 FILE *yyin;
29 #define ishex(c) (ISDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || \
30 ((c) >= 'A' && (c) <= 'F'))
31 #define TOOLONG -3
33 extern int string_start;
34 extern int string_end;
35 extern char *string_val;
36 extern int pos;
37 extern int yydebug;
39 char *yystr = NULL;
40 int yytext[YYBUFSIZ+1];
41 char yychars[YYBUFSIZ+1];
42 int yylineNum = 1;
43 int yypos = 0;
44 int yylast = -1;
45 int yyexpectaddr = 0;
46 int yybreakondot = 0;
47 int yyvarnext = 0;
48 int yytokentype = 0;
49 wordtab_t *yywordtab = NULL;
50 int yysavedepth = 0;
51 wordtab_t *yysavewords[30];
54 static wordtab_t *yyfindkey __P((char *));
55 static int yygetc __P((int));
56 static void yyunputc __P((int));
57 static int yyswallow __P((int));
58 static char *yytexttostr __P((int, int));
59 static void yystrtotext __P((char *));
60 static char *yytexttochar __P((void));
62 static int yygetc(docont)
63 int docont;
65 int c;
67 if (yypos < yylast) {
68 c = yytext[yypos++];
69 if (c == '\n')
70 yylineNum++;
71 return c;
74 if (yypos == YYBUFSIZ)
75 return TOOLONG;
77 if (pos >= string_start && pos <= string_end) {
78 c = string_val[pos - string_start];
79 yypos++;
80 } else {
81 c = fgetc(yyin);
82 if (docont && (c == '\\')) {
83 c = fgetc(yyin);
84 if (c == '\n') {
85 yylineNum++;
86 c = fgetc(yyin);
90 if (c == '\n')
91 yylineNum++;
92 yytext[yypos++] = c;
93 yylast = yypos;
94 yytext[yypos] = '\0';
96 return c;
100 static void yyunputc(c)
101 int c;
103 if (c == '\n')
104 yylineNum--;
105 yytext[--yypos] = c;
109 static int yyswallow(last)
110 int last;
112 int c;
114 while (((c = yygetc(0)) > '\0') && (c != last))
117 if (c != EOF)
118 yyunputc(c);
119 if (c == last)
120 return 0;
121 return -1;
125 static char *yytexttochar()
127 int i;
129 for (i = 0; i < yypos; i++)
130 yychars[i] = (char)(yytext[i] & 0xff);
131 yychars[i] = '\0';
132 return yychars;
136 static void yystrtotext(str)
137 char *str;
139 int len;
140 char *s;
142 len = strlen(str);
143 if (len > YYBUFSIZ)
144 len = YYBUFSIZ;
146 for (s = str; *s != '\0' && len > 0; s++, len--)
147 yytext[yylast++] = *s;
148 yytext[yylast] = '\0';
152 static char *yytexttostr(offset, max)
153 int offset, max;
155 char *str;
156 int i;
158 if ((yytext[offset] == '\'' || yytext[offset] == '"') &&
159 (yytext[offset] == yytext[offset + max - 1])) {
160 offset++;
161 max--;
164 if (max > yylast)
165 max = yylast;
166 str = malloc(max + 1);
167 if (str != NULL) {
168 for (i = offset; i < max; i++)
169 str[i - offset] = (char)(yytext[i] & 0xff);
170 str[i - offset] = '\0';
172 return str;
176 int yylex()
178 int c, n, isbuilding, rval, lnext, nokey = 0;
179 char *name;
181 isbuilding = 0;
182 lnext = 0;
183 rval = 0;
185 if (yystr != NULL) {
186 free(yystr);
187 yystr = NULL;
190 nextchar:
191 c = yygetc(0);
192 if (yydebug > 1)
193 printf("yygetc = (%x) %c [%*.*s]\n", c, c, yypos, yypos, yytexttochar());
195 switch (c)
197 case '\n' :
198 lnext = 0;
199 nokey = 0;
200 case '\t' :
201 case '\r' :
202 case ' ' :
203 if (isbuilding == 1) {
204 yyunputc(c);
205 goto done;
207 if (yylast > yypos) {
208 bcopy(yytext + yypos, yytext,
209 sizeof(yytext[0]) * (yylast - yypos + 1));
211 yylast -= yypos;
212 yypos = 0;
213 lnext = 0;
214 nokey = 0;
215 goto nextchar;
217 case '\\' :
218 if (lnext == 0) {
219 lnext = 1;
220 if (yylast == yypos) {
221 yylast--;
222 yypos--;
223 } else
224 yypos--;
225 if (yypos == 0)
226 nokey = 1;
227 goto nextchar;
229 break;
232 if (lnext == 1) {
233 lnext = 0;
234 if ((isbuilding == 0) && !ISALNUM(c)) {
235 return c;
237 goto nextchar;
240 switch (c)
242 case '#' :
243 if (isbuilding == 1) {
244 yyunputc(c);
245 goto done;
247 yyswallow('\n');
248 rval = YY_COMMENT;
249 goto done;
251 case '$' :
252 if (isbuilding == 1) {
253 yyunputc(c);
254 goto done;
256 n = yygetc(0);
257 if (n == '{') {
258 if (yyswallow('}') == -1) {
259 rval = -2;
260 goto done;
262 (void) yygetc(0);
263 } else {
264 if (!ISALPHA(n)) {
265 yyunputc(n);
266 break;
268 do {
269 n = yygetc(1);
270 } while (ISALPHA(n) || ISDIGIT(n) || n == '_');
271 yyunputc(n);
274 name = yytexttostr(1, yypos); /* skip $ */
276 if (name != NULL) {
277 string_val = get_variable(name, NULL, yylineNum);
278 free(name);
279 if (string_val != NULL) {
280 name = yytexttostr(yypos, yylast);
281 if (name != NULL) {
282 yypos = 0;
283 yylast = 0;
284 yystrtotext(string_val);
285 yystrtotext(name);
286 free(string_val);
287 free(name);
288 goto nextchar;
290 free(string_val);
293 break;
295 case '\'':
296 case '"' :
297 if (isbuilding == 1) {
298 goto done;
300 do {
301 n = yygetc(1);
302 if (n == EOF || n == TOOLONG) {
303 rval = -2;
304 goto done;
306 if (n == '\n') {
307 yyunputc(' ');
308 yypos++;
310 } while (n != c);
311 rval = YY_STR;
312 goto done;
313 /* NOTREACHED */
315 case EOF :
316 yylineNum = 1;
317 yypos = 0;
318 yylast = -1;
319 yyexpectaddr = 0;
320 yybreakondot = 0;
321 yyvarnext = 0;
322 yytokentype = 0;
323 return 0;
326 if (strchr("=,/;{}()@", c) != NULL) {
327 if (isbuilding == 1) {
328 yyunputc(c);
329 goto done;
331 rval = c;
332 goto done;
333 } else if (c == '.') {
334 if (isbuilding == 0) {
335 rval = c;
336 goto done;
338 if (yybreakondot != 0) {
339 yyunputc(c);
340 goto done;
344 switch (c)
346 case '-' :
347 if (yyexpectaddr)
348 break;
349 if (isbuilding == 1)
350 break;
351 n = yygetc(0);
352 if (n == '>') {
353 isbuilding = 1;
354 goto done;
356 yyunputc(n);
357 rval = '-';
358 goto done;
360 case '!' :
361 if (isbuilding == 1) {
362 yyunputc(c);
363 goto done;
365 n = yygetc(0);
366 if (n == '=') {
367 rval = YY_CMP_NE;
368 goto done;
370 yyunputc(n);
371 rval = '!';
372 goto done;
374 case '<' :
375 if (yyexpectaddr)
376 break;
377 if (isbuilding == 1) {
378 yyunputc(c);
379 goto done;
381 n = yygetc(0);
382 if (n == '=') {
383 rval = YY_CMP_LE;
384 goto done;
386 if (n == '>') {
387 rval = YY_RANGE_OUT;
388 goto done;
390 yyunputc(n);
391 rval = YY_CMP_LT;
392 goto done;
394 case '>' :
395 if (yyexpectaddr)
396 break;
397 if (isbuilding == 1) {
398 yyunputc(c);
399 goto done;
401 n = yygetc(0);
402 if (n == '=') {
403 rval = YY_CMP_GE;
404 goto done;
406 if (n == '<') {
407 rval = YY_RANGE_IN;
408 goto done;
410 yyunputc(n);
411 rval = YY_CMP_GT;
412 goto done;
416 * Now for the reason this is here...IPv6 address parsing.
417 * The longest string we can expect is of this form:
418 * 0000:0000:0000:0000:0000:0000:000.000.000.000
419 * not:
420 * 0000:0000:0000:0000:0000:0000:0000:0000
422 #ifdef USE_INET6
423 if (yyexpectaddr == 1 && isbuilding == 0 && (ishex(c) || c == ':')) {
424 char ipv6buf[45 + 1], *s, oc;
425 int start;
427 start = yypos;
428 s = ipv6buf;
429 oc = c;
432 * Perhaps we should implement stricter controls on what we
433 * swallow up here, but surely it would just be duplicating
434 * the code in inet_pton() anyway.
436 do {
437 *s++ = c;
438 c = yygetc(1);
439 } while ((ishex(c) || c == ':' || c == '.') &&
440 (s - ipv6buf < 46));
441 yyunputc(c);
442 *s = '\0';
444 if (inet_pton(AF_INET6, ipv6buf, &yylval.ip6) == 1) {
445 rval = YY_IPV6;
446 yyexpectaddr = 0;
447 goto done;
449 yypos = start;
450 c = oc;
452 #endif
454 if (c == ':') {
455 if (isbuilding == 1) {
456 yyunputc(c);
457 goto done;
459 rval = ':';
460 goto done;
463 if (isbuilding == 0 && c == '0') {
464 n = yygetc(0);
465 if (n == 'x') {
466 do {
467 n = yygetc(1);
468 } while (ishex(n));
469 yyunputc(n);
470 rval = YY_HEX;
471 goto done;
473 yyunputc(n);
477 * No negative numbers with leading - sign..
479 if (isbuilding == 0 && ISDIGIT(c)) {
480 do {
481 n = yygetc(1);
482 } while (ISDIGIT(n));
483 yyunputc(n);
484 rval = YY_NUMBER;
485 goto done;
488 isbuilding = 1;
489 goto nextchar;
491 done:
492 yystr = yytexttostr(0, yypos);
494 if (yydebug)
495 printf("isbuilding %d yyvarnext %d nokey %d\n",
496 isbuilding, yyvarnext, nokey);
497 if (isbuilding == 1) {
498 wordtab_t *w;
500 w = NULL;
501 isbuilding = 0;
503 if ((yyvarnext == 0) && (nokey == 0)) {
504 w = yyfindkey(yystr);
505 if (w == NULL && yywordtab != NULL) {
506 yyresetdict();
507 w = yyfindkey(yystr);
509 } else
510 yyvarnext = 0;
511 if (w != NULL)
512 rval = w->w_value;
513 else
514 rval = YY_STR;
517 if (rval == YY_STR && yysavedepth > 0)
518 yyresetdict();
520 yytokentype = rval;
522 if (yydebug)
523 printf("lexed(%s) [%d,%d,%d] => %d @%d\n", yystr, string_start,
524 string_end, pos, rval, yysavedepth);
526 switch (rval)
528 case YY_NUMBER :
529 sscanf(yystr, "%u", &yylval.num);
530 break;
532 case YY_HEX :
533 sscanf(yystr, "0x%x", (u_int *)&yylval.num);
534 break;
536 case YY_STR :
537 yylval.str = strdup(yystr);
538 break;
540 default :
541 break;
544 if (yylast > 0) {
545 bcopy(yytext + yypos, yytext,
546 sizeof(yytext[0]) * (yylast - yypos + 1));
547 yylast -= yypos;
548 yypos = 0;
551 return rval;
555 static wordtab_t *yyfindkey(key)
556 char *key;
558 wordtab_t *w;
560 if (yywordtab == NULL)
561 return NULL;
563 for (w = yywordtab; w->w_word != 0; w++)
564 if (strcasecmp(key, w->w_word) == 0)
565 return w;
566 return NULL;
570 char *yykeytostr(num)
571 int num;
573 wordtab_t *w;
575 if (yywordtab == NULL)
576 return "<unknown>";
578 for (w = yywordtab; w->w_word; w++)
579 if (w->w_value == num)
580 return w->w_word;
581 return "<unknown>";
585 wordtab_t *yysettab(words)
586 wordtab_t *words;
588 wordtab_t *save;
590 save = yywordtab;
591 yywordtab = words;
592 return save;
596 void yyerror(msg)
597 char *msg;
599 char *txt, letter[2];
600 int freetxt = 0;
602 if (yytokentype < 256) {
603 letter[0] = yytokentype;
604 letter[1] = '\0';
605 txt = letter;
606 } else if (yytokentype == YY_STR || yytokentype == YY_HEX ||
607 yytokentype == YY_NUMBER) {
608 if (yystr == NULL) {
609 txt = yytexttostr(yypos, YYBUFSIZ);
610 freetxt = 1;
611 } else
612 txt = yystr;
613 } else {
614 txt = yykeytostr(yytokentype);
616 fprintf(stderr, "%s error at \"%s\", line %d\n", msg, txt, yylineNum);
617 if (freetxt == 1)
618 free(txt);
619 exit(1);
623 void yysetdict(newdict)
624 wordtab_t *newdict;
626 if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) {
627 fprintf(stderr, "%d: at maximum dictionary depth\n",
628 yylineNum);
629 return;
632 yysavewords[yysavedepth++] = yysettab(newdict);
633 if (yydebug)
634 printf("yysavedepth++ => %d\n", yysavedepth);
637 void yyresetdict()
639 if (yydebug)
640 printf("yyresetdict(%d)\n", yysavedepth);
641 if (yysavedepth > 0) {
642 yysettab(yysavewords[--yysavedepth]);
643 if (yydebug)
644 printf("yysavedepth-- => %d\n", yysavedepth);
650 #ifdef TEST_LEXER
651 int main(argc, argv)
652 int argc;
653 char *argv[];
655 int n;
657 yyin = stdin;
659 while ((n = yylex()) != 0)
660 printf("%d.n = %d [%s] %d %d\n",
661 yylineNum, n, yystr, yypos, yylast);
663 #endif