]> The Tcpdump Group git mirrors - libpcap/commitdiff
Generate a reentrant lexical analyzer and parser.
authorGuy Harris <[email protected]>
Sat, 5 Dec 2015 03:00:46 +0000 (19:00 -0800)
committerGuy Harris <[email protected]>
Sat, 5 Dec 2015 03:00:46 +0000 (19:00 -0800)
This doesn't make pcap_compile() completely reentrant and thread-safe,
but it's a significant step along the way.

Get rid of some stuff left over from when we supported classic Lex.

gencode.c
gencode.h
grammar.y
pcap-int.h
scanner.l

index 165920e6f90840c4f494447a178fc5360f79e806..1d4d89471c2490a75939a616ba6e3a3c34ae9bce 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -74,6 +74,9 @@
 #include "pcap/ipnet.h"
 #include "arcnet.h"
 
+#include "grammar.h"
+#include "scanner.h"
+
 #if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
 #include <linux/types.h>
 #include <linux/if_packet.h>
@@ -472,6 +475,8 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
 {
        extern int n_errors;
        const char * volatile xbuf = buf;
+       yyscan_t scanner = NULL;
+       YY_BUFFER_STATE in_buffer = NULL;
        u_int len;
        int  rc;
 
@@ -512,8 +517,6 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
                        ai = NULL;
                }
 #endif
-               lex_cleanup();
-               freechunks();
                rc = -1;
                goto quit;
        }
@@ -528,9 +531,11 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
                goto quit;
        }
 
-       lex_init(xbuf ? xbuf : "");
+       if (pcap_lex_init(&scanner) != 0)
+               bpf_error("can't initialize scanner: %s", pcap_strerror(errno));
+       in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner);
        init_linktype(p);
-       (void)pcap_parse();
+       (void)pcap_parse(scanner);
 
        if (n_errors)
                syntax();
@@ -547,13 +552,21 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
        program->bf_insns = icode_to_fcode(root, &len);
        program->bf_len = len;
 
-       lex_cleanup();
-       pcap_lex_destroy();
-       freechunks();
-
        rc = 0;  /* We're all okay */
 
 quit:
+       /*
+        * Clean up everything for the lexical analyzer.
+        */
+       if (in_buffer != NULL)
+               pcap__delete_buffer(in_buffer, scanner);
+       if (scanner != NULL)
+               pcap_lex_destroy(scanner);
+
+       /*
+        * Clean up our own allocated memory.
+        */
+       freechunks();
 
 #ifdef _WIN32
        LeaveCriticalSection(&g_PcapCompileCriticalSection);
index 67ed0dc076bbad49369957903239f2b7bbf2bc25..5abca72d5b26238b644454f0407b4df59b51eb62 100644 (file)
--- a/gencode.h
+++ b/gencode.h
@@ -353,9 +353,7 @@ void finish_parse(struct block *);
 char *sdup(const char *);
 
 struct bpf_insn *icode_to_fcode(struct block *, u_int *);
-int pcap_parse(void);
-void lex_init(const char *);
-void lex_cleanup(void);
+int pcap_parse(void *);
 void sappend(struct slist *, struct slist *);
 
 /* XXX */
index cb94824bf0129d8d6df2ad9b3eb7dbbef9dfcaa1..5acf13cadbf4099486564afb9d145b08e2fcb188 100644 (file)
--- a/grammar.y
+++ b/grammar.y
@@ -1,3 +1,16 @@
+/*
+ * We want a reentrant parser.
+ */
+%pure-parser
+
+/*
+ * We also want a reentrant scanner, so we have to pass the
+ * handle for the reentrant scanner to the parser, and the
+ * parser has to pass it to the lexical analyzer.
+ */
+%parse-param   {yyscan_t yyscanner}
+%lex-param   {yyscan_t yyscanner}
+
 %{
 /*
  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
@@ -49,6 +62,9 @@ struct rtentry;
 #include "pcap-int.h"
 
 #include "gencode.h"
+#include "grammar.h"
+#include "scanner.h"
+
 #ifdef HAVE_NET_PFVAR_H
 #include <net/if.h>
 #include <net/pfvar.h>
@@ -174,7 +190,7 @@ int n_errors = 0;
 static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
 
 static void
-yyerror(const char *msg)
+yyerror(yyscan_t yyscanner, const char *msg)
 {
        ++n_errors;
        bpf_error("%s", msg);
index 091b041938d2b2e37d6defa8d00948894f99abd1..04d2ba4bf85369f6f771b04a83c49e0cd0ce6a40 100644 (file)
@@ -361,8 +361,6 @@ struct oneshot_userdata {
        pcap_t *pd;
 };
 
-int    yylex(void);
-
 #ifndef min
 #define min(a, b) ((a) > (b) ? (b) : (a))
 #endif
index 6b46fbe36a7bac0e1a28e8786630b41e11eb61e9..451f86b444ecbd6e7ea539f05fc5b0a738e4f4a1 100644 (file)
--- a/scanner.l
+++ b/scanner.l
@@ -5,11 +5,28 @@
 #endif
 }
 
+/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
+ * We don't use input, so don't generate code for it.
+ */
+%option noinput
+
+/*
+ * We don't use unput, so don't generate code for it.
+ */
+%option nounput
+
 /*
  * We don't read from the terminal.
  */
 %option never-interactive
 
+%option bison-bridge
+
 %{
 /*
  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
 
 #include "gencode.h"
 
+#include "grammar.h"
+
+/*
+ * Earlier versions of Flex dsn't declare these, so we declare them
+ * ourselves to squelch warnings.
+ */
+int pcap_get_column(yyscan_t);
+void pcap_set_column(int, yyscan_t);
+
 #ifdef INET6
 
 #ifdef _WIN32
 static int stoi(char *);
 static inline int xdtoi(int);
 
-#ifdef FLEX_SCANNER
-#define YY_NO_INPUT
-#define YY_NO_UNPUT
-static YY_BUFFER_STATE in_buffer;
-#else
-static const char *in_buffer;
-
-#undef getc
-#define getc(fp)  (*in_buffer == 0 ? EOF : *in_buffer++)
-#endif
-
-#define yylval pcap_lval
-extern YYSTYPE yylval;
-
 %}
 
 N              ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
@@ -357,17 +369,17 @@ hsls              return HSLS;
 "=="                   return '=';
 "<<"                   return LSH;
 ">>"                   return RSH;
-${B}                   { yylval.e = pcap_ether_aton(((char *)yytext)+1);
-                         if (yylval.e == NULL)
+${B}                   { yylval->e = pcap_ether_aton(((char *)yytext)+1);
+                         if (yylval->e == NULL)
                                bpf_error("malloc");
                          return AID; }
-{MAC}                  { yylval.e = pcap_ether_aton((char *)yytext);
-                         if (yylval.e == NULL)
+{MAC}                  { yylval->e = pcap_ether_aton((char *)yytext);
+                         if (yylval->e == NULL)
                                bpf_error("malloc");
                          return EID; }
-{N}                    { yylval.i = stoi((char *)yytext); return NUM; }
+{N}                    { yylval->i = stoi((char *)yytext); return NUM; }
 ({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N})        {
-                       yylval.s = sdup((char *)yytext); return HID; }
+                       yylval->s = sdup((char *)yytext); return HID; }
 {V6}                   {
 #ifdef INET6
                          struct addrinfo hints, *res;
@@ -378,67 +390,44 @@ ${B}                      { yylval.e = pcap_ether_aton(((char *)yytext)+1);
                                bpf_error("bogus IPv6 address %s", yytext);
                          else {
                                freeaddrinfo(res);
-                               yylval.s = sdup((char *)yytext); return HID6;
+                               yylval->s = sdup((char *)yytext); return HID6;
                          }
 #else
                          bpf_error("IPv6 address %s not supported", yytext);
 #endif /*INET6*/
                        }
 {B}:+({B}:+)+          { bpf_error("bogus ethernet address %s", yytext); }
-icmptype               { yylval.i = 0; return NUM; }
-icmpcode               { yylval.i = 1; return NUM; }
-icmp-echoreply         { yylval.i = 0; return NUM; }
-icmp-unreach           { yylval.i = 3; return NUM; }
-icmp-sourcequench      { yylval.i = 4; return NUM; }
-icmp-redirect          { yylval.i = 5; return NUM; }
-icmp-echo              { yylval.i = 8; return NUM; }
-icmp-routeradvert      { yylval.i = 9; return NUM; }
-icmp-routersolicit     { yylval.i = 10; return NUM; }
-icmp-timxceed          { yylval.i = 11; return NUM; }
-icmp-paramprob         { yylval.i = 12; return NUM; }
-icmp-tstamp            { yylval.i = 13; return NUM; }
-icmp-tstampreply       { yylval.i = 14; return NUM; }
-icmp-ireq              { yylval.i = 15; return NUM; }
-icmp-ireqreply         { yylval.i = 16; return NUM; }
-icmp-maskreq           { yylval.i = 17; return NUM; }
-icmp-maskreply         { yylval.i = 18; return NUM; }
-tcpflags               { yylval.i = 13; return NUM; }
-tcp-fin                        { yylval.i = 0x01; return NUM; }
-tcp-syn                        { yylval.i = 0x02; return NUM; }
-tcp-rst                        { yylval.i = 0x04; return NUM; }
-tcp-push               { yylval.i = 0x08; return NUM; }
-tcp-ack                        { yylval.i = 0x10; return NUM; }
-tcp-urg                        { yylval.i = 0x20; return NUM; }
+icmptype               { yylval->i = 0; return NUM; }
+icmpcode               { yylval->i = 1; return NUM; }
+icmp-echoreply         { yylval->i = 0; return NUM; }
+icmp-unreach           { yylval->i = 3; return NUM; }
+icmp-sourcequench      { yylval->i = 4; return NUM; }
+icmp-redirect          { yylval->i = 5; return NUM; }
+icmp-echo              { yylval->i = 8; return NUM; }
+icmp-routeradvert      { yylval->i = 9; return NUM; }
+icmp-routersolicit     { yylval->i = 10; return NUM; }
+icmp-timxceed          { yylval->i = 11; return NUM; }
+icmp-paramprob         { yylval->i = 12; return NUM; }
+icmp-tstamp            { yylval->i = 13; return NUM; }
+icmp-tstampreply       { yylval->i = 14; return NUM; }
+icmp-ireq              { yylval->i = 15; return NUM; }
+icmp-ireqreply         { yylval->i = 16; return NUM; }
+icmp-maskreq           { yylval->i = 17; return NUM; }
+icmp-maskreply         { yylval->i = 18; return NUM; }
+tcpflags               { yylval->i = 13; return NUM; }
+tcp-fin                        { yylval->i = 0x01; return NUM; }
+tcp-syn                        { yylval->i = 0x02; return NUM; }
+tcp-rst                        { yylval->i = 0x04; return NUM; }
+tcp-push               { yylval->i = 0x08; return NUM; }
+tcp-ack                        { yylval->i = 0x10; return NUM; }
+tcp-urg                        { yylval->i = 0x20; return NUM; }
 [A-Za-z0-9]([-_.A-Za-z0-9]*[.A-Za-z0-9])? {
-                        yylval.s = sdup((char *)yytext); return ID; }
-"\\"[^ !()\n\t]+       { yylval.s = sdup((char *)yytext + 1); return ID; }
+                        yylval->s = sdup((char *)yytext); return ID; }
+"\\"[^ !()\n\t]+       { yylval->s = sdup((char *)yytext + 1); return ID; }
 [^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ {
                        bpf_error("illegal token: %s", yytext); }
 .                      { bpf_error("illegal char '%c'", *yytext); }
 %%
-void
-lex_init(buf)
-       const char *buf;
-{
-#ifdef FLEX_SCANNER
-       in_buffer = yy_scan_string(buf);
-#else
-       in_buffer = buf;
-#endif
-}
-
-/*
- * Do any cleanup necessary after parsing.
- */
-void
-lex_cleanup()
-{
-#ifdef FLEX_SCANNER
-       if (in_buffer != NULL)
-               yy_delete_buffer(in_buffer);
-       in_buffer = NULL;
-#endif
-}
 
 /*
  * Also define a yywrap.  Note that if we're using flex, it will