aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2016-03-30 18:44:01 -0700
committerGuy Harris <guy@alum.mit.edu>2016-04-03 22:21:29 +0000
commit59816ef00c6dd09532d80b393ba03f8194aba236 (patch)
treef5e84c67ebe0e69542db94d56db70fa476c0db6c
parente42a43bc58a36848316adae19981878a5f430c46 (diff)
Make the Flex scanners and YACC parser in libraries reentrant.
master-branch libpcap now generates a reentrant Flex scanner and Bison/Berkeley YACC parser for capture filter expressions, so it requires versions of Flex and Bison/Berkeley YACC that support that. We might as well do the same. For libwiretap, it means we could actually have multiple K12 text or Ascend/Lucent text files open at the same time. For libwireshark, it might not be as useful, as we only read configuration files at startup (which should only happen once, in one thread) or on demand (in which case, if we ever support multiple threads running libwireshark, we'd need a mutex to ensure that only one file reads it), but it's still the right thing to do. We also require a version of Flex that can write out a header file, so we change the runlex script to generate the header file ourselves. This means we require a version of Flex new enough to support --header-file. Clean up some other stuff encountered in the process. Change-Id: Id23078c6acea549a52fc687779bb55d715b55c16 Reviewed-on: https://code.wireshark.org/review/14719 Reviewed-by: Guy Harris <guy@alum.mit.edu>
-rw-r--r--cmake/modules/FindLEX.cmake10
-rw-r--r--epan/Makefile.am3
-rw-r--r--epan/dfilter/dfilter-int.h8
-rw-r--r--epan/dfilter/dfilter.c37
-rw-r--r--epan/dfilter/scanner.l75
-rw-r--r--epan/diam_dict.l537
-rw-r--r--epan/dtd_parse.h1
-rw-r--r--epan/dtd_parse.l151
-rw-r--r--epan/dtd_preparse.l165
-rw-r--r--epan/radius_dict.l449
-rw-r--r--epan/uat_load.l267
-rw-r--r--plugins/mate/Makefile.am3
-rw-r--r--plugins/mate/mate_parser.l275
-rw-r--r--plugins/wimaxasncp/Makefile.am4
-rw-r--r--plugins/wimaxasncp/wimaxasncp_dict.l447
-rwxr-xr-xtools/runlex.sh91
-rw-r--r--ui/Makefile.am2
-rw-r--r--ui/gtk/file_import_dlg.c7
-rw-r--r--ui/qt/import_text_dialog.cpp8
-rw-r--r--ui/text_import.c20
-rw-r--r--ui/text_import.h2
-rw-r--r--ui/text_import_scanner.l42
-rw-r--r--wiretap/Makefile.am6
-rw-r--r--wiretap/ascend-int.h43
-rw-r--r--wiretap/ascend.y395
-rw-r--r--wiretap/ascend_scanner.l126
-rw-r--r--wiretap/ascendtext.c133
-rw-r--r--wiretap/k12text.l268
28 files changed, 2185 insertions, 1390 deletions
diff --git a/cmake/modules/FindLEX.cmake b/cmake/modules/FindLEX.cmake
index c540011041..ec53b04acd 100644
--- a/cmake/modules/FindLEX.cmake
+++ b/cmake/modules/FindLEX.cmake
@@ -35,15 +35,15 @@ MACRO(ADD_LEX_FILES _sources )
SET(_outh ${CMAKE_CURRENT_BINARY_DIR}/${_basename}_lex.h)
ADD_CUSTOM_COMMAND(
- OUTPUT ${_outc}
+ OUTPUT ${_outc} ${_outh}
COMMAND ${SH_EXECUTABLE} ${SH_FLAGS1} ${SH_FLAGS2} ${CMAKE_SOURCE_DIR}/tools/runlex.sh ${LEX_EXECUTABLE} ${SED_EXECUTABLE}
-o${_outc}
- --header-file=${_outh}
${_in}
DEPENDS ${_in}
)
- SET(${_sources} ${${_sources}} ${_outc} )
- INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
- ENDFOREACH (_current_FILE)
+ SET(${_sources} ${${_sources}} ${_outc} )
+ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+ ENDFOREACH (_current_FILE)
ENDMACRO(ADD_LEX_FILES)
diff --git a/epan/Makefile.am b/epan/Makefile.am
index a1394b6e67..66270fe8bc 100644
--- a/epan/Makefile.am
+++ b/epan/Makefile.am
@@ -116,7 +116,8 @@ MAINTAINERCLEANFILES = \
Makefile.in
BUILT_SOURCES = \
- dtd_grammar.h
+ $(LIBWIRESHARK_GENERATED_HEADER_FILES) \
+ $(NODIST_LIBWIRESHARK_GENERATED_HEADER_FILES)
#
# Add the object files for missing routines, if any.
diff --git a/epan/dfilter/dfilter-int.h b/epan/dfilter/dfilter-int.h
index 40e55488b5..f94c78f139 100644
--- a/epan/dfilter/dfilter-int.h
+++ b/epan/dfilter/dfilter-int.h
@@ -56,10 +56,12 @@ typedef struct {
} dfwork_t;
/*
- * XXX - if we're using a version of Flex that supports reentrant lexical
- * analyzers, we should put this into the lexical analyzer's state.
+ * State kept by the scanner.
*/
-extern dfwork_t *global_dfw;
+typedef struct {
+ dfwork_t *dfw;
+ GString* quoted_string;
+} df_scanner_state_t;
/* Constructor/Destructor prototypes for Lemon Parser */
void *DfilterAlloc(void* (*)(gsize));
diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c
index df24b1ced7..151bb5ec7d 100644
--- a/epan/dfilter/dfilter.c
+++ b/epan/dfilter/dfilter.c
@@ -31,14 +31,10 @@
#include <epan/epan_dissect.h>
#include "dfilter.h"
#include "dfilter-macro.h"
+#include "scanner_lex.h"
#define DFILTER_TOKEN_ID_OFFSET 1
-/* From scanner.c */
-void df_scanner_text(const char *text);
-void df_scanner_cleanup(void);
-int df_lex(void);
-
/* Holds the singular instance of our Lemon parser object */
static void* ParserObj = NULL;
@@ -214,6 +210,9 @@ dfilter_compile(const gchar *text, dfilter_t **dfp, gchar **err_msg)
int token;
dfilter_t *dfilter;
dfwork_t *dfw;
+ df_scanner_state_t state;
+ yyscan_t scanner;
+ YY_BUFFER_STATE in_buffer;
gboolean failure = FALSE;
const char *depr_test;
guint i;
@@ -233,21 +232,28 @@ dfilter_compile(const gchar *text, dfilter_t **dfp, gchar **err_msg)
return FALSE;
}
+ if (df_lex_init(&scanner) != 0) {
+ *dfp = NULL;
+ if (err_msg != NULL)
+ *err_msg = g_strdup_printf("Can't initialize scanner: %s",
+ g_strerror(errno));
+ return FALSE;
+ }
+
+ in_buffer = df__scan_string(expanded_text, scanner);
+
dfw = dfwork_new();
- /*
- * XXX - if we're using a version of Flex that supports reentrant lexical
- * analyzers, we should put this into the lexical analyzer's state.
- */
- global_dfw = dfw;
+ state.dfw = dfw;
+ state.quoted_string = NULL;
- df_scanner_text(expanded_text);
+ df_set_extra(&state, scanner);
deprecated = g_ptr_array_new();
while (1) {
df_lval = stnode_new(STTYPE_UNINITIALIZED, NULL);
- token = df_lex();
+ token = df_lex(scanner);
/* Check for scanner failure */
if (token == SCAN_FAILED) {
@@ -307,8 +313,11 @@ dfilter_compile(const gchar *text, dfilter_t **dfp, gchar **err_msg)
if (dfw->syntax_error)
failure = TRUE;
- /* Reset flex */
- df_scanner_cleanup();
+ /* Free scanner state */
+ if (state.quoted_string != NULL)
+ g_string_free(state.quoted_string, TRUE);
+ df__delete_buffer(in_buffer, scanner);
+ df_lex_destroy(scanner);
if (failure)
goto FAILURE;
diff --git a/epan/dfilter/scanner.l b/epan/dfilter/scanner.l
index c213ac8351..ce138da8b6 100644
--- a/epan/dfilter/scanner.l
+++ b/epan/dfilter/scanner.l
@@ -1,4 +1,9 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
* We don't use input, so don't generate code for it.
*/
%option noinput
@@ -24,6 +29,24 @@
*/
%option noyywrap
+/*
+ * The type for the state we keep for a scanner.
+ */
+%option extra-type="df_scanner_state_t *"
+
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
%{
/*
* Wireshark - Network traffic analyzer
@@ -54,7 +77,6 @@
#include "syntax-tree.h"
#include "grammar.h"
#include "dfunctions.h"
-#include "scanner_lex.h"
#ifdef _WIN32
/* disable Windows VC compiler warning "signed/unsigned mismatch" associated */
@@ -76,9 +98,20 @@ static int set_lval(int token, gpointer data);
static int set_lval_int(dfwork_t *dfw, int token, char *s);
static int simple(int token);
static gboolean str_to_gint32(dfwork_t *dfw, char *s, gint32* pint);
-GString* quoted_string = NULL;
static void mark_lval_deprecated(const char *s);
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
+
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define df_alloc(size, yyscanner) (void *)malloc(size)
+#define df_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define df_free(ptr, yyscanner) free((char *)ptr)
+
%}
%x RANGE_INT
@@ -136,12 +169,12 @@ static void mark_lval_deprecated(const char *s);
<RANGE_INT>[+-]?[[:digit:]]+ {
BEGIN(RANGE_PUNCT);
- return set_lval_int(global_dfw, TOKEN_INTEGER, yytext);
+ return set_lval_int(yyextra->dfw, TOKEN_INTEGER, yytext);
}
<RANGE_INT>[+-]?0x[[:xdigit:]]+ {
BEGIN(RANGE_PUNCT);
- return set_lval_int(global_dfw, TOKEN_INTEGER, yytext);
+ return set_lval_int(yyextra->dfw, TOKEN_INTEGER, yytext);
}
<RANGE_INT,RANGE_PUNCT>":" {
@@ -167,7 +200,7 @@ static void mark_lval_deprecated(const char *s);
/* Error if none of the above while scanning a range (slice) */
<RANGE_PUNCT>[^:\-,\]]+ {
- dfilter_fail(global_dfw, "Invalid string \"%s\" found while scanning slice.", yytext);
+ dfilter_fail(yyextra->dfw, "Invalid string \"%s\" found while scanning slice.", yytext);
return SCAN_FAILED;
}
@@ -176,7 +209,7 @@ static void mark_lval_deprecated(const char *s);
*/
<RANGE_INT>. {
- dfilter_fail(global_dfw, "Invalid character \"%s\" found while scanning slice; expected integer.", yytext);
+ dfilter_fail(yyextra->dfw, "Invalid character \"%s\" found while scanning slice; expected integer.", yytext);
return SCAN_FAILED;
}
@@ -192,13 +225,13 @@ static void mark_lval_deprecated(const char *s);
a missing end quote will have left quoted_string set
to something. Clear it now that we are starting
a new quoted string. */
- if (quoted_string) {
- g_string_free(quoted_string, TRUE);
+ if (yyextra->quoted_string) {
+ g_string_free(yyextra->quoted_string, TRUE);
/* Don't set quoted_string to NULL, as we
do in other quoted_string-cleanup code, as we're
about to set it in the next line. */
}
- quoted_string = g_string_new("");
+ yyextra->quoted_string = g_string_new("");
}
<DQUOTE><<EOF>> {
@@ -208,7 +241,7 @@ static void mark_lval_deprecated(const char *s);
See:
http://www.gnu.org/software/flex/manual/html_node/flex_13.html */
- dfilter_fail(global_dfw, "The final quote was missing from a quoted string.");
+ dfilter_fail(yyextra->dfw, "The final quote was missing from a quoted string.");
return SCAN_FAILED;
}
@@ -216,9 +249,9 @@ static void mark_lval_deprecated(const char *s);
/* end quote */
int token;
BEGIN(INITIAL);
- token = set_lval(TOKEN_STRING, quoted_string->str);
- g_string_free(quoted_string, TRUE);
- quoted_string = NULL;
+ token = set_lval(TOKEN_STRING, yyextra->quoted_string->str);
+ g_string_free(yyextra->quoted_string, TRUE);
+ yyextra->quoted_string = NULL;
return token;
}
@@ -227,30 +260,30 @@ static void mark_lval_deprecated(const char *s);
unsigned long result;
result = strtoul(yytext + 1, NULL, 8);
if (result > 0xff) {
- g_string_free(quoted_string, TRUE);
- quoted_string = NULL;
- dfilter_fail(global_dfw, "%s is larger than 255.", yytext);
+ g_string_free(yyextra->quoted_string, TRUE);
+ yyextra->quoted_string = NULL;
+ dfilter_fail(yyextra->dfw, "%s is larger than 255.", yytext);
return SCAN_FAILED;
}
- g_string_append_c(quoted_string, (gchar) result);
+ g_string_append_c(yyextra->quoted_string, (gchar) result);
}
<DQUOTE>\\x[[:xdigit:]]{1,2} {
/* hex sequence */
unsigned long result;
result = strtoul(yytext + 2, NULL, 16);
- g_string_append_c(quoted_string, (gchar) result);
+ g_string_append_c(yyextra->quoted_string, (gchar) result);
}
<DQUOTE>\\. {
/* escaped character */
- g_string_append_c(quoted_string, yytext[1]);
+ g_string_append_c(yyextra->quoted_string, yytext[1]);
}
<DQUOTE>[^\\\042]+ {
/* non-escaped string */
- g_string_append(quoted_string, yytext);
+ g_string_append(yyextra->quoted_string, yytext);
}
@@ -429,5 +462,3 @@ mark_lval_deprecated(const char *s)
{
df_lval->deprecated_token = s;
}
-
-#include <lemonflex-tail.inc>
diff --git a/epan/diam_dict.l b/epan/diam_dict.l
index e97ca8d821..3c450465dc 100644
--- a/epan/diam_dict.l
+++ b/epan/diam_dict.l
@@ -1,4 +1,9 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
* We don't use input, so don't generate code for it.
*/
%option noinput
@@ -29,13 +34,31 @@
%option noyywrap
/*
- * Prefix scanner routines with "DiamDict" rather than "yy", so this scanner
+ * The type for the state we keep for a scanner.
+ */
+%option extra-type="DiamDict_scanner_state_t *"
+
+/*
+ * Prefix scanner routines with "DiamDict_" rather than "yy", so this scanner
* can coexist with other scanners.
*/
-%option prefix="DiamDict"
+%option prefix="DiamDict_"
%option outfile="diam_dict.c"
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
%{
/*
** diam_dict.h
@@ -68,7 +91,6 @@
#include <stdlib.h>
#include <stdarg.h>
#include "diam_dict.h"
-#include "diam_dict_lex.h"
#include <epan/to_str.h>
#include <wsutil/file_util.h>
@@ -78,48 +100,80 @@ typedef struct entity_t {
struct entity_t* next;
} entity_t;
-#define ATTR_UINT(cont) do { D(("attr_uint " #cont "\t" )); attr_uint = &(cont); yy_push_state(GET_UINT_ATTR); } while(0)
-#define ATTR_STR(cont) do { D(("attr_str " #cont "\t" )); attr_str = &(cont); yy_push_state(GET_ATTR); } while(0)
-#define IGNORE() do { D(("ignore: %s\t",yytext)); yy_push_state(IGNORE_ATTR); } while(0)
+#define ATTR_UINT(cont) do { D(("attr_uint " #cont "\t" )); yyextra->attr_uint = &(cont); yy_push_state(GET_UINT_ATTR, yyscanner); } while(0)
+#define ATTR_STR(cont) do { D(("attr_str " #cont "\t" )); yyextra->attr_str = &(cont); yy_push_state(GET_ATTR, yyscanner); } while(0)
+#define IGNORE() do { D(("ignore: %s\t",yytext)); yy_push_state(IGNORE_ATTR, yyscanner); } while(0)
#define D(args) ddict_debug args
#define MAX_INCLUDE_DEPTH 10
-#define YY_INPUT(buf,result,max_size) { result = current_yyinput(buf,max_size); }
+#define YY_INPUT(buf,result,max_size) { result = yyextra->current_yyinput(buf,max_size,yyscanner); }
+#define YY_USER_INIT { \
+ DiamDict_scanner_state_t *scanner_state = DiamDict_get_extra(yyscanner); \
+ BEGIN(scanner_state->start_state); \
+}
#define ECHO
-#define APPEND(txt,len) append_to_buffer(txt,len)
-
-static entity_t ents;
-static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
-static int include_stack_ptr = 0;
-static size_t (*current_yyinput)(char*,size_t);
-static const char* sys_dir;
-static ddict_t* dict;
-static ddict_application_t* appl;
-static ddict_avp_t* avp;
-static ddict_enum_t* enumitem;
-static ddict_gavp_t* gavp;
-static ddict_typedefn_t* typedefn;
-static ddict_cmd_t* cmd;
-static ddict_vendor_t* vnd;
-static ddict_xmlpi_t* xmlpi;
-
-static ddict_application_t* last_appl;
-static ddict_avp_t* last_avp;
-static ddict_enum_t* last_enumitem;
-static ddict_gavp_t* last_gavp;
-static ddict_typedefn_t* last_typedefn;
-static ddict_cmd_t* last_cmd;
-static ddict_vendor_t* last_vnd;
-static ddict_xmlpi_t* last_xmlpi;
-
-static char** attr_str;
-static unsigned* attr_uint;
+#define APPEND(txt,len) append_to_buffer(txt,len,yyextra)
+
+typedef struct {
+ const char* sys_dir;
+
+ char* write_ptr;
+ char* read_ptr;
+
+ char* strbuf;
+ unsigned size_strbuf;
+ unsigned len_strbuf;
+
+ ddict_t* dict;
+
+ ddict_application_t* appl;
+ ddict_avp_t* avp;
+ ddict_enum_t* enumitem;
+ ddict_gavp_t* gavp;
+ ddict_typedefn_t* typedefn;
+ ddict_cmd_t* cmd;
+ ddict_vendor_t* vnd;
+ ddict_xmlpi_t* xmlpi;
+
+ ddict_application_t* last_appl;
+ ddict_avp_t* last_avp;
+ ddict_enum_t* last_enumitem;
+ ddict_gavp_t* last_gavp;
+ ddict_typedefn_t* last_typedefn;
+ ddict_cmd_t* last_cmd;
+ ddict_vendor_t* last_vnd;
+ ddict_xmlpi_t* last_xmlpi;
+
+ entity_t *ents;
+
+ char** attr_str;
+ unsigned* attr_uint;
+
+ size_t (*current_yyinput)(char*,size_t,yyscan_t);
+
+ YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+ int include_stack_ptr;
+
+ int start_state;
+} DiamDict_scanner_state_t;
static void ddict_debug(const char* fmt, ...) G_GNUC_PRINTF(1, 2);
-static void append_to_buffer(const char* txt, unsigned len);
+static void append_to_buffer(const char* txt, unsigned len, DiamDict_scanner_state_t *statep);
static FILE* ddict_open(const char*, const char*);
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
+
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define DiamDict_alloc(size, yyscanner) (void *)malloc(size)
+#define DiamDict_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define DiamDict_free(ptr, yyscanner) free((char *)ptr)
+
%}
@@ -215,23 +269,25 @@ description_attr description=\042
<LOADING>{xmlpi_start} BEGIN LOADING_XMLPI;
<LOADING_XMLPI>{whitespace} ;
<LOADING_XMLPI>{entityname} {
- xmlpi = g_new(ddict_xmlpi_t,1);
- xmlpi->name = g_strdup(yytext);
- xmlpi->key = NULL;
- xmlpi->value = NULL;
- xmlpi->next = NULL;
+ yyextra->xmlpi = g_new(ddict_xmlpi_t,1);
+ yyextra->xmlpi->name = g_strdup(yytext);
+ yyextra->xmlpi->key = NULL;
+ yyextra->xmlpi->value = NULL;
+ yyextra->xmlpi->next = NULL;
- if (!dict->xmlpis) last_xmlpi = dict->xmlpis = xmlpi;
- else last_xmlpi = last_xmlpi->next = xmlpi;
+ if (!yyextra->dict->xmlpis)
+ yyextra->last_xmlpi = yyextra->dict->xmlpis = yyextra->xmlpi;
+ else
+ yyextra->last_xmlpi = yyextra->last_xmlpi->next = yyextra->xmlpi;
BEGIN XMLPI_ATTRS;
}
<XMLPI_ATTRS>{xmlpi_key_attr} BEGIN XMLPI_GETKEY;
-<XMLPI_GETKEY>{ndquot} { xmlpi->key = strdup(yytext); BEGIN XMLPI_ATTRS; }
+<XMLPI_GETKEY>{ndquot} { yyextra->xmlpi->key = strdup(yytext); BEGIN XMLPI_ATTRS; }
<XMLPI_ATTRS>{xmlpi_value_attr} BEGIN XMLPI_GETVAL;
-<XMLPI_GETVAL>{ndquot} { xmlpi->value = strdup(yytext); BEGIN XMLPI_ATTRS; }
+<XMLPI_GETVAL>{ndquot} { yyextra->xmlpi->value = strdup(yytext); BEGIN XMLPI_ATTRS; }
<XMLPI_ATTRS>.
<XMLPI_ATTRS>{xmlpi_end} BEGIN LOADING;
@@ -241,13 +297,13 @@ description_attr description=\042
<ENTITY>{entityname} {
entity_t* e = g_new(entity_t,1);
e->name = strdup(yytext);
- e->next = ents.next;
- ents.next = e;
+ e->next = yyextra->ents;
+ yyextra->ents = e;
BEGIN GET_SYSTEM;
};
<GET_SYSTEM>{system} BEGIN GET_FILE;
<GET_FILE>{ndquot} {
- ents.next->file = strdup(yytext);
+ yyextra->ents->file = strdup(yytext);
BEGIN END_ENTITY;
}
<END_ENTITY>{end_entity} BEGIN LOADING;
@@ -278,14 +334,14 @@ description_attr description=\042
D(("looking for entity: %s\n",yytext));
- if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
+ if ( yyextra->include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
fprintf(stderr, "included files nested to deeply\n");
yyterminate();
}
- for (e = ents.next; e; e = e->next) {
+ for (e = yyextra->ents; e; e = e->next) {
if (strcmp(e->name,yytext) == 0) {
- yyin = ddict_open(sys_dir,e->file);
+ yyin = ddict_open(yyextra->sys_dir,e->file);
D(("entity: %s filename: %s yyin: %p\n",e->name,e->file,(void*)yyin));
if (!yyin) {
if (errno)
@@ -294,8 +350,8 @@ description_attr description=\042
fprintf(stderr, "Could not open file: '%s', error unknown (errno == 0)\n", e->file );
yyterminate();
} else {
- include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
- yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
+ yyextra->include_stack[yyextra->include_stack_ptr++] = YY_CURRENT_BUFFER;
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner), yyscanner);
BEGIN LOADING;
}
break;
@@ -313,35 +369,35 @@ description_attr description=\042
if (!yyin) yyterminate();
fclose(yyin);
- D(("closing: %p %i\n",(void*)yyin,include_stack_ptr));
+ D(("closing: %p %i\n",(void*)yyin,yyextra->include_stack_ptr));
- if ( --include_stack_ptr < 0 ) {
+ if ( --yyextra->include_stack_ptr < 0 ) {
D(("DONE READING\n"));
yyin = NULL;
yyterminate();
} else {
- yy_delete_buffer( YY_CURRENT_BUFFER );
- yy_switch_to_buffer(include_stack[include_stack_ptr]);
+ yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner);
+ yy_switch_to_buffer(yyextra->include_stack[yyextra->include_stack_ptr], yyscanner);
BEGIN LOADING;
}
}
<GET_ATTR>{ndquot} {
- *attr_str = strdup(yytext);
+ *(yyextra->attr_str) = strdup(yytext);
D(("%s\n",yytext));
- attr_str = NULL;
+ yyextra->attr_str = NULL;
BEGIN END_ATTR;
}
<GET_UINT_ATTR>{number} {
- *attr_uint = (unsigned) strtoul(yytext,NULL,10);
+ *(yyextra->attr_uint) = (unsigned) strtoul(yytext,NULL,10);
D(("%s\n",yytext););
- attr_uint = NULL;
+ yyextra->attr_uint = NULL;
BEGIN END_ATTR;
}
-<END_ATTR>{dquot} { yy_pop_state(); }
+<END_ATTR>{dquot} { yy_pop_state(yyscanner); }
<IGNORE_ATTR>. {
/* XXX: should go?*/
@@ -350,7 +406,7 @@ description_attr description=\042
<IGNORE_ATTR>{ignored_quoted} {
D(("=>%s<=\n",yytext));
- yy_pop_state();
+ yy_pop_state(yyscanner);
}
<OUTSIDE>{dictionary_start} {
@@ -367,19 +423,21 @@ description_attr description=\042
<IN_DICT>{application_start} {
D(("application_start\n"));
- appl = g_new(ddict_application_t,1);
- appl->name = NULL;
- appl->code = 0;
- appl->next = NULL;
+ yyextra->appl = g_new(ddict_application_t,1);
+ yyextra->appl->name = NULL;
+ yyextra->appl->code = 0;
+ yyextra->appl->next = NULL;
- if (!dict->applications) last_appl = dict->applications = appl;
- else last_appl = last_appl->next = appl;
+ if (!yyextra->dict->applications)
+ yyextra->last_appl = yyextra->dict->applications = yyextra->appl;
+ else
+ yyextra->last_appl = yyextra->last_appl->next = yyextra->appl;
BEGIN APPL_ATTRS;
}
-<APPL_ATTRS>{name_attr} { ATTR_STR(appl->name); }
-<APPL_ATTRS>{id_attr} { ATTR_UINT(appl->code); }
+<APPL_ATTRS>{name_attr} { ATTR_STR(yyextra->appl->name); }
+<APPL_ATTRS>{id_attr} { ATTR_UINT(yyextra->appl->code); }
<APPL_ATTRS>{stop} BEGIN IN_APPL;
<APPL_ATTRS>{stop_end} BEGIN IN_DICT;
@@ -389,60 +447,66 @@ description_attr description=\042
<IN_APPL>{command_start} {
D(("command_start\n"));
- cmd = g_new(ddict_cmd_t,1);
- cmd->name = NULL;
- cmd->vendor = NULL;
- cmd->code = 0;
- cmd->next = NULL;
+ yyextra->cmd = g_new(ddict_cmd_t,1);
+ yyextra->cmd->name = NULL;
+ yyextra->cmd->vendor = NULL;
+ yyextra->cmd->code = 0;
+ yyextra->cmd->next = NULL;
- if (!dict->cmds) last_cmd = dict->cmds = cmd;
- else last_cmd = last_cmd->next = cmd;
+ if (!yyextra->dict->cmds)
+ yyextra->last_cmd = yyextra->dict->cmds = yyextra->cmd;
+ else
+ yyextra->last_cmd = yyextra->last_cmd->next = yyextra->cmd;
BEGIN COMMAND_ATTRS;
}
-<COMMAND_ATTRS>{name_attr} { ATTR_STR(cmd->name); }
-<COMMAND_ATTRS>{vendor_attr} { ATTR_STR(cmd->vendor); }
-<COMMAND_ATTRS>{code_attr} { ATTR_UINT(cmd->code); }
+<COMMAND_ATTRS>{name_attr} { ATTR_STR(yyextra->cmd->name); }
+<COMMAND_ATTRS>{vendor_attr} { ATTR_STR(yyextra->cmd->vendor); }
+<COMMAND_ATTRS>{code_attr} { ATTR_UINT(yyextra->cmd->code); }
<COMMAND_ATTRS>{stop} |
<COMMAND_ATTRS>{stop_end} { BEGIN IN_APPL; }
<IN_DICT>{vendor_start} {
D(("vendor_start\n"));
- vnd = g_new(ddict_vendor_t,1);
- vnd->name = NULL;
- vnd->code = 0;
- vnd->next = NULL;
+ yyextra->vnd = g_new(ddict_vendor_t,1);
+ yyextra->vnd->name = NULL;
+ yyextra->vnd->code = 0;
+ yyextra->vnd->next = NULL;
- if (!dict->vendors) last_vnd = dict->vendors = vnd;
- else last_vnd = last_vnd->next = vnd;
+ if (!yyextra->dict->vendors)
+ yyextra->last_vnd = yyextra->dict->vendors = yyextra->vnd;
+ else
+ yyextra->last_vnd = yyextra->last_vnd->next = yyextra->vnd;
BEGIN VENDOR_ATTRS;
}
-<VENDOR_ATTRS>{name_attr} { ATTR_STR(vnd->desc); }
-<VENDOR_ATTRS>{vendor_attr} { ATTR_STR(vnd->name); }
-<VENDOR_ATTRS>{code_attr} { ATTR_UINT(vnd->code); }
+<VENDOR_ATTRS>{name_attr} { ATTR_STR(yyextra->vnd->desc); }
+<VENDOR_ATTRS>{vendor_attr} { ATTR_STR(yyextra->vnd->name); }
+<VENDOR_ATTRS>{code_attr} { ATTR_UINT(yyextra->vnd->code); }
<VENDOR_ATTRS>{stop} { BEGIN IN_APPL; }
<VENDOR_ATTRS>{stop_end} { BEGIN IN_DICT; }
<IN_APPL>{typedefn_start} {
D(("typedefn_start\n"));
- typedefn = g_new(ddict_typedefn_t,1);
- typedefn->name = NULL;
- typedefn->parent = NULL;
- typedefn->next = NULL;
+ yyextra->typedefn = g_new(ddict_typedefn_t,1);
+ yyextra->typedefn->name = NULL;
+ yyextra->typedefn->parent = NULL;
+ yyextra->typedefn->next = NULL;
- if (!dict->typedefns) last_typedefn = dict->typedefns = typedefn;
- else last_typedefn = last_typedefn->next = typedefn;
+ if (!yyextra->dict->typedefns)
+ yyextra->last_typedefn = yyextra->dict->typedefns = yyextra->typedefn;
+ else
+ yyextra->last_typedefn = yyextra->last_typedefn->next = yyextra->typedefn;
BEGIN TYPEDEFN_ATTRS;
}
-<TYPEDEFN_ATTRS>{typename_attr} { ATTR_STR(typedefn->name); }
-<TYPEDEFN_ATTRS>{typeparent_attr} { ATTR_STR(typedefn->parent); }
+<TYPEDEFN_ATTRS>{typename_attr} { ATTR_STR(yyextra->typedefn->name); }
+<TYPEDEFN_ATTRS>{typeparent_attr} { ATTR_STR(yyextra->typedefn->parent); }
<TYPEDEFN_ATTRS>{stop} |
<TYPEDEFN_ATTRS>{stop_end} { BEGIN IN_APPL; }
@@ -450,71 +514,77 @@ description_attr description=\042
<IN_APPL>{avp_start} {
D(("avp_start\n"));
- avp = g_new(ddict_avp_t,1);
- avp->name = NULL;
- avp->description = NULL;
- avp->vendor = NULL;
- avp->code = 0;
- avp->type = NULL;
- avp->enums = NULL;
- avp->gavps = NULL;
- avp->next = NULL;
-
- if (! dict->avps ) last_avp = dict->avps = avp;
- else last_avp = last_avp->next = avp;
+ yyextra->avp = g_new(ddict_avp_t,1);
+ yyextra->avp->name = NULL;
+ yyextra->avp->description = NULL;
+ yyextra->avp->vendor = NULL;
+ yyextra->avp->code = 0;
+ yyextra->avp->type = NULL;
+ yyextra->avp->enums = NULL;
+ yyextra->avp->gavps = NULL;
+ yyextra->avp->next = NULL;
+
+ if (! yyextra->dict->avps )
+ yyextra->last_avp = yyextra->dict->avps = yyextra->avp;
+ else
+ yyextra->last_avp = yyextra->last_avp->next = yyextra->avp;
BEGIN AVP_ATTRS;
}
-<AVP_ATTRS>{name_attr} { ATTR_STR(avp->name); }
-<AVP_ATTRS>{description_attr} { ATTR_STR(avp->description); }
-<AVP_ATTRS>{vendor_attr} { ATTR_STR(avp->vendor); }
-<AVP_ATTRS>{code_attr} { ATTR_UINT(avp->code); }
+<AVP_ATTRS>{name_attr} { ATTR_STR(yyextra->avp->name); }
+<AVP_ATTRS>{description_attr} { ATTR_STR(yyextra->avp->description); }
+<AVP_ATTRS>{vendor_attr} { ATTR_STR(yyextra->avp->vendor); }
+<AVP_ATTRS>{code_attr} { ATTR_UINT(yyextra->avp->code); }
<AVP_ATTRS>{stop} { BEGIN IN_AVP; }
<AVP_ATTRS>{stop_end} { BEGIN IN_APPL; }
-<IN_AVP>{grouped_start} { avp->type = strdup("Grouped"); };
+<IN_AVP>{grouped_start} { yyextra->avp->type = strdup("Grouped"); };
<IN_AVP>{grouped_end} ;
<IN_AVP>{type_start} { BEGIN TYPE_ATTRS; }
-<TYPE_ATTRS>{typename_attr} { ATTR_STR(avp->type); }
+<TYPE_ATTRS>{typename_attr} { ATTR_STR(yyextra->avp->type); }
<IN_AVP>{gavp_start} {
D(("gavp_start\n"));
- gavp = g_new(ddict_gavp_t,1);
- gavp->name = NULL;
- gavp->code = 0;
- gavp->next = NULL;
+ yyextra->gavp = g_new(ddict_gavp_t,1);
+ yyextra->gavp->name = NULL;
+ yyextra->gavp->code = 0;
+ yyextra->gavp->next = NULL;
- if (!avp->gavps) last_gavp = avp->gavps = gavp;
- else last_gavp = last_gavp->next = gavp;
+ if (!yyextra->avp->gavps)
+ yyextra->last_gavp = yyextra->avp->gavps = yyextra->gavp;
+ else
+ yyextra->last_gavp = yyextra->last_gavp->next = yyextra->gavp;
BEGIN GAVP_ATTRS;
}
-<GAVP_ATTRS>{name_attr} { ATTR_STR(gavp->name); }
+<GAVP_ATTRS>{name_attr} { ATTR_STR(yyextra->gavp->name); }
<IN_AVP>{enum_start} {
D(("enum_start\n"));
- enumitem = g_new(ddict_enum_t,1);
- enumitem->name = NULL;
- enumitem->code = 0;
- enumitem->next = NULL;
+ yyextra->enumitem = g_new(ddict_enum_t,1);
+ yyextra->enumitem->name = NULL;
+ yyextra->enumitem->code = 0;
+ yyextra->enumitem->next = NULL;
- if (!avp->enums) last_enumitem = avp->enums = enumitem;
- else last_enumitem = last_enumitem->next = enumitem;
+ if (!yyextra->avp->enums)
+ yyextra->last_enumitem = yyextra->avp->enums = yyextra->enumitem;
+ else
+ yyextra->last_enumitem = yyextra->last_enumitem->next = yyextra->enumitem;
BEGIN ENUM_ATTRS;
}
-<ENUM_ATTRS>{name_attr} { ATTR_STR(enumitem->name); }
-<ENUM_ATTRS>{code_attr} { ATTR_UINT(enumitem->code); }
+<ENUM_ATTRS>{name_attr} { ATTR_STR(yyextra->enumitem->name); }
+<ENUM_ATTRS>{code_attr} { ATTR_UINT(yyextra->enumitem->code); }
<TYPE_ATTRS,GAVP_ATTRS,ENUM_ATTRS>{stop} { BEGIN IN_AVP; }
<TYPE_ATTRS,GAVP_ATTRS,ENUM_ATTRS>{stop_end} { BEGIN IN_AVP; }
@@ -561,45 +631,44 @@ static void ddict_debug(const char* fmt, ...) {
fflush(stderr);
}
+/*
+ * Sleazy hack to avoid unused function warnings for yy_top_state.
+ */
+extern void ddict_unused(yyscan_t yyscanner);
-static char* strbuf = NULL;
-static char* write_ptr = NULL;
-static char* read_ptr = NULL;
-
-static unsigned size_strbuf = 8192;
-static unsigned len_strbuf = 0;
-
-extern void ddict_unused(void);
void
-ddict_unused(void)
+ddict_unused(yyscan_t yyscanner)
{
- yy_top_state();
+ yy_top_state(yyscanner);
}
static void
-append_to_buffer(const char* txt, unsigned len)
+append_to_buffer(const char* txt, unsigned len, DiamDict_scanner_state_t *statep)
{
- if (strbuf == NULL) {
- read_ptr = write_ptr = strbuf = (char*)g_malloc(size_strbuf);
+ if (statep->strbuf == NULL) {
+ statep->strbuf = (char*)g_malloc(statep->size_strbuf);
+ statep->read_ptr = statep->strbuf;
+ statep->write_ptr = statep->strbuf;
}
- if ( (len_strbuf + len) >= size_strbuf ) {
- read_ptr = strbuf = (char*)g_realloc(strbuf,size_strbuf *= 2);
+ if ( (statep->len_strbuf + len) >= statep->size_strbuf ) {
+ statep->strbuf = (char*)g_realloc(statep->strbuf,statep->size_strbuf *= 2);
+ statep->read_ptr = statep->strbuf;
}
- write_ptr = strbuf + len_strbuf;
- strncpy(write_ptr,txt,len);
- len_strbuf += len;
-
+ statep->write_ptr = statep->strbuf + statep->len_strbuf;
+ strncpy(statep->write_ptr,txt,len);
+ statep->len_strbuf += len;
}
static size_t
-file_input(char* buf, size_t max)
+file_input(char* buf, size_t max, yyscan_t scanner)
{
+ FILE *in = yyget_in(scanner);
size_t read_cnt;
- read_cnt = fread(buf,1,max,yyin);
+ read_cnt = fread(buf,1,max,in);
if ( read_cnt == max ) {
return max;
@@ -612,16 +681,18 @@ file_input(char* buf, size_t max)
static size_t
-string_input(char* buf, size_t max)
+string_input(char* buf, size_t max, yyscan_t scanner)
{
- if (read_ptr >= write_ptr ) {
+ DiamDict_scanner_state_t *statep = yyget_extra(scanner);
+
+ if (statep->read_ptr >= statep->write_ptr ) {
return YY_NULL;
- } else if ( read_ptr + max > write_ptr ) {
- max = write_ptr - read_ptr;
+ } else if ( statep->read_ptr + max > statep->write_ptr ) {
+ max = statep->write_ptr - statep->read_ptr;
}
- memcpy(buf,read_ptr,max);
- read_ptr += max;
+ memcpy(buf,statep->read_ptr,max);
+ statep->read_ptr += max;
return max;
}
@@ -651,64 +722,114 @@ ddict_open(const char* system_directory, const char* filename)
ddict_t *
ddict_scan(const char* system_directory, const char* filename, int dbg)
{
+ DiamDict_scanner_state_t state;
+ FILE *in;
+ yyscan_t scanner;
debugging = dbg;
- sys_dir = system_directory;
+ state.sys_dir = system_directory;
+
+ state.write_ptr = NULL;
+ state.read_ptr = NULL;
+
+ state.strbuf = NULL;
+ state.size_strbuf = 8192;
+ state.len_strbuf = 0;
+
+ state.dict = g_new(ddict_t,1);
+ state.dict->applications = NULL;
+ state.dict->cmds = NULL;
+ state.dict->vendors = NULL;
+ state.dict->typedefns = NULL;
+ state.dict->avps = NULL;
+ state.dict->xmlpis = NULL;
+
+ state.appl = NULL;
+ state.avp = NULL;
+ state.enumitem = NULL;
+ state.gavp = NULL;
+ state.typedefn = NULL;
+ state.cmd = NULL;
+ state.vnd = NULL;
+ state.xmlpi = NULL;
+
+ state.last_appl = NULL;
+ state.last_avp = NULL;
+ state.last_enumitem = NULL;
+ state.last_gavp = NULL;
+ state.last_typedefn = NULL;
+ state.last_cmd = NULL;
+ state.last_vnd = NULL;
+ state.last_xmlpi = NULL;
+
+ state.ents = NULL;
+
+ state.attr_str = NULL;
+ state.attr_uint = NULL;
- yyin = ddict_open(sys_dir,filename);
+ /*
+ * Pass 1.
+ *
+ * Reads the file, does some work, and stores a modified version
+ * of the file contents in memory.
+ */
+ state.current_yyinput = file_input;
+ state.include_stack_ptr = 0;
- if (yyin == NULL) {
- D(("unable to open %s\n", filename));
+ in = ddict_open(system_directory,filename);
+
+ if (in == NULL) {
+ D(("unable to open %s: %s\n", filename, g_strerror(errno)));
+ g_free(state.dict);
return NULL;
}
- write_ptr = NULL;
- read_ptr = NULL;
-
- dict = g_new(ddict_t,1);
- dict->applications = NULL;
- dict->cmds = NULL;
- dict->vendors = NULL;
- dict->typedefns = NULL;
- dict->avps = NULL;
- dict->xmlpis = NULL;
-
- appl = NULL;
- avp = NULL;
- enumitem = NULL;
- gavp = NULL;
- typedefn = NULL;
- cmd = NULL;
- vnd = NULL;
- xmlpi = NULL;
-
- last_appl = NULL;
- last_avp = NULL;
- last_enumitem = NULL;
- last_gavp = NULL;
- last_typedefn = NULL;
- last_cmd = NULL;
- last_vnd = NULL;
- last_xmlpi = NULL;
-
- ents.next = NULL;
- current_yyinput = file_input;
- BEGIN LOADING;
- yylex();
-
- D(("\n---------------\n%s\n------- %u -------\n",strbuf,len_strbuf));
-
- current_yyinput = string_input;
-
- BEGIN OUTSIDE;
- yylex();
-
- g_free(strbuf);
- strbuf = NULL;
- size_strbuf = 8192;
-
- return dict;
+ if (DiamDict_lex_init(&scanner) != 0) {
+ D(("Can't initialize scanner: %s\n", g_strerror(errno)));
+ fclose(in);
+ g_free(state.dict);
+ return NULL;
+ }
+
+ DiamDict_set_in(in, scanner);
+
+ /* Associate the state with the scanner */
+ DiamDict_set_extra(&state, scanner);
+
+ state.start_state = LOADING;
+ DiamDict_lex(scanner);
+
+ DiamDict_lex_destroy(scanner);
+ fclose(in);
+
+ D(("\n---------------\n%s\n------- %u -------\n",state.strbuf,state.len_strbuf));
+
+ /*
+ * Pass 2.
+ *
+ * Reads the modified version of the file contents and does the
+ * rest of the work.
+ */
+ state.current_yyinput = string_input;
+
+ if (DiamDict_lex_init(&scanner) != 0) {
+ D(("Can't initialize scanner: %s\n", g_strerror(errno)));
+ g_free(state.dict);
+ g_free(state.strbuf);
+ return NULL;
+ }
+
+ /* Associate the state with the scanner */
+ DiamDict_set_extra(&state, scanner);
+
+ state.start_state = OUTSIDE;
+ DiamDict_lex(scanner);
+
+ DiamDict_lex_destroy(scanner);
+ g_free(state.strbuf);
+
+ return state.dict;
}
void
diff --git a/epan/dtd_parse.h b/epan/dtd_parse.h
index 01c2983dbd..a9c3c6117d 100644
--- a/epan/dtd_parse.h
+++ b/epan/dtd_parse.h
@@ -28,4 +28,3 @@ extern void DtdParse(void*,int,dtd_token_data_t*,dtd_build_data_t*);
extern void *DtdParseAlloc(void *(*)(gsize));
extern void DtdParseFree( void*, void(*)(void*) );
extern void DtdParseTrace(FILE *TraceFILE, char *zTracePrompt);
-extern int Dtd_Parse_lex(void);
diff --git a/epan/dtd_parse.l b/epan/dtd_parse.l
index 1c9554478a..ae67cd4a5d 100644
--- a/epan/dtd_parse.l
+++ b/epan/dtd_parse.l
@@ -1,4 +1,9 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
* We don't use input, so don't generate code for it.
*/
%option noinput
@@ -19,6 +24,11 @@
%option noyywrap
/*
+ * The type for the state we keep for a scanner.
+ */
+%option extra-type="Dtd_Parse_scanner_state_t *"
+
+/*
* Prefix scanner routines with "Dtd_Parse_" rather than "yy", so this scanner
* can coexist with other scanners.
*/
@@ -26,6 +36,19 @@
%option outfile="dtd_parse.c"
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
%{
/* dtd_parse.l
@@ -53,29 +76,32 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "config.h"
+
#include <glib.h>
#include <string.h>
#include "dtd.h"
#include "dtd_grammar.h"
#include "dtd_parse.h"
-#include "dtd_parse_lex.h"
struct _proto_xmlpi_attr {
const gchar* name;
void (*act)(gchar*);
};
- static void* pParser;
- static GString* input_string;
- static size_t offsetx;
- static size_t len;
- static gchar* location;
- static gchar* attr_name;
+ typedef struct {
+ GString* input_string;
+ size_t offsetx;
+ size_t len;
+ void* pParser;
+ gchar* location;
+ gchar* attr_name;
+ } Dtd_Parse_scanner_state_t;
- static size_t my_yyinput(char* buff,size_t size);
+ static size_t my_yyinput(Dtd_Parse_scanner_state_t *state,char* buff,size_t size);
- static dtd_token_data_t* new_token(gchar*);
+ static dtd_token_data_t* new_token(gchar*,gchar*);
static dtd_build_data_t* build_data;
@@ -85,16 +111,6 @@
static void set_description (gchar* val) { if(build_data->description) g_free(build_data->description); build_data->description = g_strdup(val); }
static void set_recursive (gchar* val) { build_data->recursion = ( g_ascii_strcasecmp(val,"yes") == 0 ) ? TRUE : FALSE; }
- static struct _proto_xmlpi_attr proto_attrs[] =
- {
- { "proto_name", set_proto_name },
- { "media", set_media_type },
- { "root", set_proto_root },
- { "description", set_description },
- { "hierarchy", set_recursive },
- {NULL,NULL}
- };
-
#ifdef DEBUG_DTD_PARSER
#define DEBUG_DTD_TOKEN fprintf(stderr,"->%s (%i)%s\n",location,token_type,yytext)
#else
@@ -103,12 +119,13 @@
#define DTD_PARSE(token_type) \
{ DEBUG_DTD_TOKEN; \
- DtdParse(pParser, (token_type), new_token(yytext), build_data); \
+ DtdParse(yyextra->pParser, (token_type), new_token(yytext, yyextra->location), build_data); \
if(build_data->error->len > 0) yyterminate(); \
}
-#define YY_INPUT(buff,result,max_size) ( (result) = my_yyinput((buff),(max_size)) )
+#define YY_INPUT(buff,result,max_size) ( (result) = my_yyinput(yyextra,(buff),(max_size)) )
+#define YY_USER_INIT BEGIN DTD;
/*
* Flex (v 2.5.35) uses this symbol to "exclude" unistd.h
@@ -117,6 +134,18 @@
#define YY_NO_UNISTD_H
#endif
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
+
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define Dtd_Parse_alloc(size, yyscanner) (void *)malloc(size)
+#define Dtd_Parse_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define Dtd_Parse_free(ptr, yyscanner) free((char *)ptr)
+
%}
comment_start "<!--"
@@ -210,15 +239,15 @@ squoted ['][^\']*[']
<XMLPI>{stop_xmlpi} BEGIN DTD;
<LOCATION>{get_location_xmlpi} {
- if(location) g_free(location);
- location = g_strdup(yytext);
+ if(yyextra->location) g_free(yyextra->location);
+ yyextra->location = g_strdup(yytext);
BEGIN DONE;
}
<DONE>{stop_xmlpi} BEGIN DTD;
<PROTOCOL>{name} {
- attr_name = g_ascii_strdown(yytext, -1);
+ yyextra->attr_name = g_ascii_strdown(yytext, -1);
BEGIN GET_ATTR_QUOTE;
}
@@ -227,7 +256,7 @@ squoted ['][^\']*[']
<GET_ATTR_QUOTE>. {
g_string_append_printf(build_data->error,
"error in wireshark:protocol xmpli at %s : could not find attribute value!",
- location);
+ yyextra->location);
yyterminate();
}
@@ -235,9 +264,18 @@ squoted ['][^\']*[']
/*"*/
struct _proto_xmlpi_attr* pa;
gboolean got_it = FALSE;
+ static struct _proto_xmlpi_attr proto_attrs[] =
+ {
+ { "proto_name", set_proto_name },
+ { "media", set_media_type },
+ { "root", set_proto_root },
+ { "description", set_description },
+ { "hierarchy", set_recursive },
+ {NULL,NULL}
+ };
for(pa = proto_attrs; pa->name; pa++) {
- if (g_ascii_strcasecmp(attr_name,pa->name) == 0) {
+ if (g_ascii_strcasecmp(yyextra->attr_name,pa->name) == 0) {
pa->act(yytext);
got_it = TRUE;
break;
@@ -247,12 +285,12 @@ squoted ['][^\']*[']
if (! got_it) {
g_string_append_printf(build_data->error,
"error in wireshark:protocol xmpli at %s : no such parameter %s!",
- location, attr_name);
- g_free(attr_name);
+ yyextra->location, yyextra->attr_name);
+ g_free(yyextra->attr_name);
yyterminate();
}
- g_free(attr_name);
+ g_free(yyextra->attr_name);
BEGIN GET_ATTR_CLOSE_QUOTE;
}
@@ -303,7 +341,7 @@ squoted ['][^\']*[']
%%
-static dtd_token_data_t* new_token(gchar* text) {
+static dtd_token_data_t* new_token(gchar* text, gchar* location) {
dtd_token_data_t* t = g_new(dtd_token_data_t,1);
t->text = g_strdup(text);
@@ -313,29 +351,39 @@ static dtd_token_data_t* new_token(gchar* text) {
}
-static size_t my_yyinput(char* buff, size_t size) {
+static size_t my_yyinput(Dtd_Parse_scanner_state_t *state, char* buff, size_t size) {
- if (offsetx >= len ) {
+ if (state->offsetx >= state->len) {
return YY_NULL;
- } else if ( offsetx + size <= len ) {
- memcpy(buff, input_string->str + offsetx,size);
- offsetx += size;
+ } else if (state->offsetx + size <= state->len) {
+ memcpy(buff, state->input_string->str + state->offsetx, size);
+ state->offsetx += size;
return size;
} else {
- size = len - offsetx;
- memcpy(buff, input_string->str + offsetx,size);
- offsetx = len;
+ size = state->len - state->offsetx;
+ memcpy(buff, state->input_string->str + state->offsetx, size);
+ state->offsetx = state->len;
return size;
}
}
extern dtd_build_data_t* dtd_parse(GString* s) {
+ yyscan_t scanner;
+ Dtd_Parse_scanner_state_t state;
- input_string = s;
- offsetx = 0;
- len = input_string->len;
+ if (Dtd_Parse_lex_init(&scanner) != 0) {
+#ifdef DEBUG_DTD_PARSER
+ fprintf(stderr, "Can't initialize scanner: %s\n",
+ strerror(errno));
+#endif
+ return NULL;
+ }
- pParser = DtdParseAlloc(g_malloc);
+ state.input_string = s;
+ state.offsetx = 0;
+ state.len = state.input_string->len;
+
+ state.pParser = DtdParseAlloc(g_malloc);
#ifdef DEBUG_DTD_PARSER
DtdParseTrace(stderr, ">>");
@@ -354,21 +402,22 @@ extern dtd_build_data_t* dtd_parse(GString* s) {
build_data->error = g_string_new("");
- location = NULL;
-
- BEGIN DTD;
+ state.location = NULL;
+ state.attr_name = NULL;
- yylex();
+ /* Associate the state with the scanner */
+ Dtd_Parse_set_extra(&state, scanner);
- DtdParse(pParser, 0, NULL,build_data);
+ Dtd_Parse_lex(scanner);
- yyrestart(NULL);
+ DtdParse(state.pParser, 0, NULL, build_data);
- if (location) g_free(location);
+ Dtd_Parse_lex_destroy(scanner);
- location = NULL;
+ if (state.location)
+ g_free(state.location);
- DtdParseFree(pParser, g_free );
+ DtdParseFree(state.pParser, g_free);
return build_data;
}
diff --git a/epan/dtd_preparse.l b/epan/dtd_preparse.l
index 5188fbae02..f51f1c7f7a 100644
--- a/epan/dtd_preparse.l
+++ b/epan/dtd_preparse.l
@@ -1,4 +1,9 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
* We don't use input, so don't generate code for it.
*/
%option noinput
@@ -19,6 +24,11 @@
%option noyywrap
/*
+ * The type for the state we keep for a scanner.
+ */
+%option extra-type="Dtd_PreParse_scanner_state_t *"
+
+/*
* The language we're scanning is case-insensitive.
*/
%option caseless
@@ -31,14 +41,27 @@
%option outfile="dtd_preparse.c"
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
%{
/*
- * dtd_preparser.l
+ * dtd_preparse.l
*
* an XML dissector for wireshark
*
* DTD Preparser - import a dtd file into a GString
- * including files, removing comments
+ * including files, removing comments
* and resolving %entities;
*
* Copyright 2004, Luis E. Garcia Ontanon <luis@ontanon.org>
@@ -69,23 +92,29 @@
#include <errno.h>
#include <stdio.h>
#include "dtd.h"
-#include "dtd_preparse_lex.h"
#include <wsutil/file_util.h>
-#define ECHO g_string_append(current,yytext);
+#define ECHO g_string_append(yyextra->current,yytext);
-static GString* current;
-static GString* output;
-static GHashTable* entities;
-static gchar* entity_name;
-static GString* error;
+typedef struct {
+ const gchar* dtd_dirname;
+ const gchar* filename;
+ guint linenum;
-static const gchar* dtd_dirname;
-static const gchar* filename;
-static guint linenum;
+ GString* error;
-static const gchar* replace_entity(gchar* s);
-static const gchar* location(void);
+ GHashTable* entities;
+ GString* current;
+ GString* output;
+ gchar* entity_name;
+} Dtd_PreParse_scanner_state_t;
+
+static const gchar* replace_entity(Dtd_PreParse_scanner_state_t* state, gchar* s);
+static const gchar* location(Dtd_PreParse_scanner_state_t* state);
+
+#define YY_USER_INIT { \
+ BEGIN OUTSIDE; \
+}
/*
* Flex (v 2.5.35) uses this symbol to "exclude" unistd.h
@@ -100,6 +129,18 @@ static const gchar* location(void);
#pragma warning (disable:4018)
#endif
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
+
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define Dtd_PreParse_alloc(size, yyscanner) (void *)malloc(size)
+#define Dtd_PreParse_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define Dtd_PreParse_free(ptr, yyscanner) free((char *)ptr)
+
%}
xmlpi_start "<?"
xmlpi_stop "?>"
@@ -132,63 +173,63 @@ newline \n
%%
-{entity} if (current) g_string_append_printf(current,"%s\n%s\n",replace_entity(yytext),location());
+{entity} if (yyextra->current) g_string_append_printf(yyextra->current,"%s\n%s\n",replace_entity(yyextra, yytext),location(yyextra));
-{whitespace} if (current) g_string_append(current," ");
+{whitespace} if (yyextra->current) g_string_append(yyextra->current," ");
-<OUTSIDE>{xmlpi_start} { g_string_append(current,yytext); BEGIN XMLPI; }
-<XMLPI>{xmlpi_chars} { g_string_append(current,yytext); }
-<XMLPI>{newline} { g_string_append(current,yytext); }
-<XMLPI>{xmlpi_stop} { g_string_append(current,yytext); BEGIN OUTSIDE; }
+<OUTSIDE>{xmlpi_start} { g_string_append(yyextra->current,yytext); BEGIN XMLPI; }
+<XMLPI>{xmlpi_chars} { g_string_append(yyextra->current,yytext); }
+<XMLPI>{newline} { g_string_append(yyextra->current,yytext); }
+<XMLPI>{xmlpi_stop} { g_string_append(yyextra->current,yytext); BEGIN OUTSIDE; }
-<OUTSIDE>{comment_start} { current = NULL; BEGIN IN_COMMENT; }
-<IN_COMMENT>[^-]? |
-<IN_COMMENT>[-] ;
-<IN_COMMENT>{comment_stop} { current = output; BEGIN OUTSIDE; }
+<OUTSIDE>{comment_start} { yyextra->current = NULL; BEGIN IN_COMMENT; }
+<IN_COMMENT>[^-]? |
+<IN_COMMENT>[-] ;
+<IN_COMMENT>{comment_stop} { yyextra->current = yyextra->output; BEGIN OUTSIDE; }
-{newline} {
- linenum++;
- if (current) g_string_append_printf(current,"%s\n",location());
+{newline} {
+ yyextra->linenum++;
+ if (yyextra->current) g_string_append_printf(yyextra->current,"%s\n",location(yyextra));
}
<OUTSIDE>{entity_start} { BEGIN IN_ENTITY; }
-<IN_ENTITY>{name} { entity_name = g_strdup_printf("%%%s;",yytext); BEGIN NAMED_ENTITY; }
-<NAMED_ENTITY>{quote} { current = g_string_new(location()); BEGIN IN_QUOTE; }
-<IN_QUOTE>{quote} { g_hash_table_insert(entities,entity_name,current); BEGIN ENTITY_DONE; }
-<IN_QUOTE>{percent} |
+<IN_ENTITY>{name} { yyextra->entity_name = g_strdup_printf("%%%s;",yytext); BEGIN NAMED_ENTITY; }
+<NAMED_ENTITY>{quote} { yyextra->current = g_string_new(location(yyextra)); BEGIN IN_QUOTE; }
+<IN_QUOTE>{quote} { g_hash_table_insert(yyextra->entities,yyextra->entity_name,yyextra->current); BEGIN ENTITY_DONE; }
+<IN_QUOTE>{percent} |
<IN_QUOTE>{non_quote} |
-<IN_QUOTE>{escaped_quote} g_string_append(current,yytext);
+<IN_QUOTE>{escaped_quote} g_string_append(yyextra->current,yytext);
<NAMED_ENTITY>{system} {
- g_string_append_printf(error,"at %s:%u: file inclusion is not supported!", filename, linenum);
+ g_string_append_printf(yyextra->error,"at %s:%u: file inclusion is not supported!", yyextra->filename, yyextra->linenum);
yyterminate();
}
-<ENTITY_DONE>{special_stop} { current = output; g_string_append(current,"\n"); BEGIN OUTSIDE; }
+<ENTITY_DONE>{special_stop} { yyextra->current = yyextra->output; g_string_append(yyextra->current,"\n"); BEGIN OUTSIDE; }
%%
-static const gchar* replace_entity(gchar* entity) {
+static const gchar* replace_entity(Dtd_PreParse_scanner_state_t* state, gchar* entity) {
GString* replacement;
*entity = '%';
- replacement = (GString*)g_hash_table_lookup(entities,entity);
+ replacement = (GString*)g_hash_table_lookup(state->entities,entity);
if (replacement) {
return replacement->str;
} else {
- g_string_append_printf(error,"dtd_preparse: in file '%s': entity %s does not exists\n", filename, entity);
+ g_string_append_printf(state->error,"dtd_preparse: in file '%s': entity %s does not exists\n", state->filename, entity);
return "";
}
}
-static const gchar* location(void) {
+static const gchar* location(Dtd_PreParse_scanner_state_t* state) {
static gchar* loc = NULL;
if (loc) g_free(loc);
- loc = g_strdup_printf("<? wireshark:location %s:%u ?>", filename, linenum);
+ loc = g_strdup_printf("<? wireshark:location %s:%u ?>", state->filename, state->linenum);
return loc;
}
@@ -201,37 +242,51 @@ static gboolean free_gstring_hash_items(gpointer k,gpointer v,gpointer p _U_) {
extern GString* dtd_preparse(const gchar* dname,const gchar* fname, GString* err) {
gchar* fullname = g_strdup_printf("%s%c%s",dname,G_DIR_SEPARATOR,fname);
+ FILE *in;
+ yyscan_t scanner;
+ Dtd_PreParse_scanner_state_t state;
- dtd_dirname = dname;
- filename = fname;
- linenum = 1;
+ in = ws_fopen(fullname,"r");
- yyin = ws_fopen(fullname,"r");
-
- if (!yyin) {
+ if (!in) {
if (err)
g_string_append_printf(err, "Could not open file: '%s', error: %s",fullname,g_strerror(errno));
return NULL;
}
- error = err;
+ if (Dtd_PreParse_lex_init(&scanner) != 0) {
+ if (err)
+ g_string_append_printf(err, "Can't initialize scanner: %s",
+ strerror(errno));
+ fclose(in);
+ return FALSE;
+ }
+
+ Dtd_PreParse_set_in(in, scanner);
+
+ state.dtd_dirname = dname;
+ state.filename = fname;
+ state.linenum = 1;
- entities = g_hash_table_new(g_str_hash,g_str_equal);
- current = output = g_string_new(location());
+ state.error = err;
- BEGIN OUTSIDE;
+ state.entities = g_hash_table_new(g_str_hash,g_str_equal);
+ state.current = state.output = g_string_new(location(&state));
+ state.entity_name = NULL;
- yylex();
+ /* Associate the state with the scanner */
+ Dtd_PreParse_set_extra(&state, scanner);
- fclose(yyin);
+ Dtd_PreParse_lex(scanner);
- yyrestart(NULL);
+ Dtd_PreParse_lex_destroy(scanner);
+ fclose(in);
- g_hash_table_foreach_remove(entities,free_gstring_hash_items,NULL);
- g_hash_table_destroy(entities);
+ g_hash_table_foreach_remove(state.entities,free_gstring_hash_items,NULL);
+ g_hash_table_destroy(state.entities);
g_free(fullname);
- return output;
+ return state.output;
}
diff --git a/epan/radius_dict.l b/epan/radius_dict.l
index ebbf2a060a..86a8428f07 100644
--- a/epan/radius_dict.l
+++ b/epan/radius_dict.l
@@ -1,4 +1,9 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
* We don't use input, so don't generate code for it.
*/
%option noinput
@@ -24,10 +29,28 @@
%option caseless
/*
- * Prefix scanner routines with "Radius" rather than "yy", so this scanner
+ * The type for the state we keep for a scanner.
+ */
+%option extra-type="Radius_scanner_state_t*"
+
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
+/*
+ * Prefix scanner routines with "Radius_" rather than "yy", so this scanner
* can coexist with other scanners.
*/
-%option prefix="Radius"
+%option prefix="Radius_"
%option outfile="radius_dict.c"
@@ -64,9 +87,10 @@
#include <errno.h>
#include <epan/packet.h>
#include <epan/dissectors/packet-radius.h>
-#include "radius_dict_lex.h"
#include <wsutil/file_util.h>
+#define YY_USER_INIT BEGIN WS_OUT;
+
#ifdef _WIN32
/* disable Windows VC compiler warning "signed/unsigned mismatch" associated */
/* with YY_INPUT code generated by flex versions such as 2.5.35. */
@@ -76,36 +100,51 @@
#define ECHO
#define MAX_INCLUDE_DEPTH 10
- static void add_vendor(const gchar* name, guint32 id, guint type_octets, guint length_octets, gboolean has_flags);
- static void add_value(const gchar* attrib_name,const gchar* repr, guint32 value);
- static void add_tlv(const gchar* name, const gchar* code, radius_attr_dissector_t type, const gchar* attr);
- static void add_attribute(const gchar*,const gchar*, radius_attr_dissector_t,const gchar*, guint, gboolean, const gchar*);
-
- static YY_BUFFER_STATE include_stack[10];
- static int include_stack_ptr = 0;
-
- static radius_dictionary_t* dict = NULL;
- static GHashTable* value_strings = NULL; /* GArray(value_string) by attribute name */
-
- static gchar* attr_name = NULL;
- static gchar* attr_id = NULL;
- static radius_attr_dissector_t* attr_type = NULL;
- static gchar* attr_vendor = NULL;
- static gchar* vendor_name = NULL;
- static guint32 vendor_id = 0;
- static guint vendor_type_octets = 1;
- static guint vendor_length_octets = 1;
- static gboolean vendor_has_flags = FALSE;
- static gchar* value_repr = NULL;
- static guint encrypted = 0;
- static gboolean has_tag = FALSE;
- static gchar* current_vendor = NULL;
- static gchar* current_attr = NULL;
-
- static GString* error = NULL;
- static gchar* directory = NULL;
- static int linenums[] = {1,1,1,1,1,1,1,1,1,1};
- static gchar* fullpaths[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+typedef struct {
+ YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+ int include_stack_ptr;
+
+ radius_dictionary_t* dict;
+ GHashTable* value_strings; /* GArray(value_string) by attribute name */
+
+ gchar* attr_name;
+ gchar* attr_id;
+ radius_attr_dissector_t* attr_type;
+ gchar* attr_vendor;
+ gchar* vendor_name;
+ guint32 vendor_id;
+ guint vendor_type_octets;
+ guint vendor_length_octets;
+ gboolean vendor_has_flags;
+ gchar* value_repr;
+ guint encrypted;
+ gboolean has_tag;
+ gchar* current_vendor;
+ gchar* current_attr;
+
+ gchar* directory;
+ gchar* fullpaths[MAX_INCLUDE_DEPTH];
+ int linenums[MAX_INCLUDE_DEPTH];
+
+ GString* error;
+} Radius_scanner_state_t;
+
+static void add_vendor(Radius_scanner_state_t* state, const gchar* name, guint32 id, guint type_octets, guint length_octets, gboolean has_flags);
+static gboolean add_attribute(Radius_scanner_state_t* state, const gchar*,const gchar*, radius_attr_dissector_t,const gchar*, guint, gboolean, const gchar*);
+static gboolean add_tlv(Radius_scanner_state_t* state, const gchar* name, const gchar* code, radius_attr_dissector_t type, const gchar* attr);
+static void add_value(Radius_scanner_state_t* state, const gchar* attrib_name, const gchar* repr, guint32 value);
+
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
+
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define Radius_alloc(size, yyscanner) (void *)malloc(size)
+#define Radius_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define Radius_free(ptr, yyscanner) free((char *)ptr)
%}
@@ -132,63 +171,63 @@
<WS_OUT>END-TLV { BEGIN END_TLV; }
<BEGIN_VENDOR>[0-9a-z_-]+ {
- if (current_vendor) {
- g_free(current_vendor);
+ if (yyextra->current_vendor) {
+ g_free(yyextra->current_vendor);
}
- current_vendor = g_strdup(yytext);
+ yyextra->current_vendor = g_strdup(yytext);
BEGIN WS_OUT;
}
<END_VENDOR>[^\n]* {
- if (current_vendor) {
- g_free(current_vendor);
- current_vendor = NULL;
+ if (yyextra->current_vendor) {
+ g_free(yyextra->current_vendor);
+ yyextra->current_vendor = NULL;
}
BEGIN WS_OUT;
}
<BEGIN_TLV>[0-9a-z_-]+ {
- if (current_attr) {
- g_free(current_attr);
+ if (yyextra->current_attr) {
+ g_free(yyextra->current_attr);
}
- current_attr = g_strdup(yytext);
+ yyextra->current_attr = g_strdup(yytext);
BEGIN WS_OUT;
}
<END_TLV>[^\n]* {
- if (current_attr) {
- g_free(current_attr);
- current_attr = NULL;
+ if (yyextra->current_attr) {
+ g_free(yyextra->current_attr);
+ yyextra->current_attr = NULL;
}
BEGIN WS_OUT;
}
<VENDOR>[0-9a-z_-]+ {
- vendor_name = g_strdup(yytext);
- vendor_type_octets = 1;
- vendor_length_octets = 1;
- vendor_has_flags = FALSE;
+ yyextra->vendor_name = g_strdup(yytext);
+ yyextra->vendor_type_octets = 1;
+ yyextra->vendor_length_octets = 1;
+ yyextra->vendor_has_flags = FALSE;
BEGIN VENDOR_W_NAME;
}
<VENDOR_W_NAME>[0-9]+ {
- vendor_id = (guint32) strtoul(yytext,NULL,10);
+ yyextra->vendor_id = (guint32) strtoul(yytext,NULL,10);
BEGIN VENDOR_W_ID;
}
<VENDOR_W_NAME>0x[0-9a-f]+ {
- vendor_id = (guint32) strtoul(yytext,NULL,16);
+ yyextra->vendor_id = (guint32) strtoul(yytext,NULL,16);
BEGIN VENDOR_W_ID;
}
<VENDOR_W_ID>format= {
BEGIN VENDOR_W_FORMAT;
}
<VENDOR_W_FORMAT>[124] {
- vendor_type_octets = (guint) strtoul(yytext,NULL,10);
+ yyextra->vendor_type_octets = (guint) strtoul(yytext,NULL,10);
BEGIN VENDOR_W_TYPE_OCTETS;
}
<VENDOR_W_TYPE_OCTETS>,[012] {
- vendor_length_octets = (guint) strtoul(yytext+1,NULL,10);
+ yyextra->vendor_length_octets = (guint) strtoul(yytext+1,NULL,10);
BEGIN VENDOR_W_LENGTH_OCTETS;
}
<VENDOR_W_LENGTH_OCTETS>,c {
- vendor_has_flags = TRUE;
+ yyextra->vendor_has_flags = TRUE;
BEGIN VENDOR_W_CONTINUATION;
}
<VENDOR_W_FORMAT>\n |
@@ -196,98 +235,103 @@
<VENDOR_W_LENGTH_OCTETS>\n |
<VENDOR_W_CONTINUATION>\n |
<VENDOR_W_ID>\n {
- add_vendor(vendor_name, vendor_id, vendor_type_octets, vendor_length_octets, vendor_has_flags);
- g_free(vendor_name);
+ add_vendor(yyextra, yyextra->vendor_name, yyextra->vendor_id, yyextra->vendor_type_octets, yyextra->vendor_length_octets, yyextra->vendor_has_flags);
+ g_free(yyextra->vendor_name);
BEGIN WS_OUT;
}
-<ATTR>[0-9a-z_/.-]+ { attr_name = g_strdup(yytext); encrypted = 0; has_tag = FALSE; BEGIN ATTR_W_NAME; }
-<ATTR_W_NAME>[0-9]+ { attr_id = g_strdup(yytext); BEGIN ATTR_W_ID;}
-<ATTR_W_NAME>0x[0-9a-f]+ { attr_id = g_strdup_printf("%u",(int)strtoul(yytext,NULL,16)); BEGIN ATTR_W_ID;}
-<ATTR_W_ID>integer { attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>string { attr_type = radius_string; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>octets { attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ipaddr { attr_type = radius_ipaddr; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ipv6addr { attr_type = radius_ipv6addr; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ipv6prefix { attr_type = radius_ipv6prefix; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ipxnet { attr_type = radius_ipxnet; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>date { attr_type = radius_date; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>abinary { attr_type = radius_abinary; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ether { attr_type = radius_ether; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ifid { attr_type = radius_ifid; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>byte { attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>short { attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>signed { attr_type = radius_signed; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>combo-ip { attr_type = radius_combo_ip; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>tlv { attr_type = radius_tlv; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>[0-9a-z_-]+ { attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
-<ATTR_W_TYPE>has_tag[,]? { has_tag = TRUE; }
-<ATTR_W_TYPE>encrypt=[123][,]? { encrypted = (guint) strtoul(yytext+8,NULL,10); }
+<ATTR>[0-9a-z_/.-]+ { yyextra->attr_name = g_strdup(yytext); yyextra->encrypted = 0; yyextra->has_tag = FALSE; BEGIN ATTR_W_NAME; }
+<ATTR_W_NAME>[0-9]+ { yyextra->attr_id = g_strdup(yytext); BEGIN ATTR_W_ID;}
+<ATTR_W_NAME>0x[0-9a-f]+ { yyextra->attr_id = g_strdup_printf("%u",(int)strtoul(yytext,NULL,16)); BEGIN ATTR_W_ID;}
+<ATTR_W_ID>integer { yyextra->attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>string { yyextra->attr_type = radius_string; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>octets { yyextra->attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ipaddr { yyextra->attr_type = radius_ipaddr; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ipv6addr { yyextra->attr_type = radius_ipv6addr; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ipv6prefix { yyextra->attr_type = radius_ipv6prefix; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ipxnet { yyextra->attr_type = radius_ipxnet; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>date { yyextra->attr_type = radius_date; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>abinary { yyextra->attr_type = radius_abinary; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ether { yyextra->attr_type = radius_ether; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ifid { yyextra->attr_type = radius_ifid; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>byte { yyextra->attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>short { yyextra->attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>signed { yyextra->attr_type = radius_signed; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>combo-ip { yyextra->attr_type = radius_combo_ip; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>tlv { yyextra->attr_type = radius_tlv; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>[0-9a-z_-]+ { yyextra->attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
+<ATTR_W_TYPE>has_tag[,]? { yyextra->has_tag = TRUE; }
+<ATTR_W_TYPE>encrypt=[123][,]? { yyextra->encrypted = (guint) strtoul(yytext+8,NULL,10); }
<ATTR_W_TYPE>[0-9a-z_-]+=([^\n]*) ;
<ATTR_W_TYPE>[0-9a-z_-]+ {
- attr_vendor = g_strdup(yytext);
- add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypted,has_tag,current_attr);
- g_free(attr_id);
- g_free(attr_vendor);
- g_free(attr_name);
- attr_id = NULL;
- attr_vendor = NULL;
- attr_name = NULL;
- BEGIN WS_OUT;
+ gboolean attribute_ok;
+
+ yyextra->attr_vendor = g_strdup(yytext);
+ attribute_ok = add_attribute(yyextra, yyextra->attr_name, yyextra->attr_id, yyextra->attr_type, yyextra->attr_vendor, yyextra->encrypted, yyextra->has_tag, yyextra->current_attr);
+ g_free(yyextra->attr_id);
+ g_free(yyextra->attr_vendor);
+ g_free(yyextra->attr_name);
+ yyextra->attr_id = NULL;
+ yyextra->attr_vendor = NULL;
+ yyextra->attr_name = NULL;
+ if (attribute_ok)
+ BEGIN WS_OUT;
+ else
+ BEGIN JUNK;
}
<ATTR_W_TYPE>\n {
- add_attribute(attr_name,attr_id,attr_type,current_vendor,encrypted,has_tag,current_attr);
- g_free(attr_id);
- g_free(attr_name);
- linenums[include_stack_ptr]++;
- has_tag = FALSE;
- encrypted=FALSE;
+ add_attribute(yyextra, yyextra->attr_name, yyextra->attr_id, yyextra->attr_type, yyextra->current_vendor, yyextra->encrypted, yyextra->has_tag, yyextra->current_attr);
+ g_free(yyextra->attr_id);
+ g_free(yyextra->attr_name);
+ yyextra->linenums[yyextra->include_stack_ptr]++;
+ yyextra->has_tag = FALSE;
+ yyextra->encrypted=FALSE;
BEGIN WS_OUT;
}
<ATTR_W_VENDOR>\n {
- add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypted,has_tag,current_attr);
- g_free(attr_id);
- g_free(attr_vendor);
- g_free(attr_name);
- linenums[include_stack_ptr]++;
+ add_attribute(yyextra, yyextra->attr_name, yyextra->attr_id, yyextra->attr_type, yyextra->attr_vendor, yyextra->encrypted, yyextra->has_tag, yyextra->current_attr);
+ g_free(yyextra->attr_id);
+ g_free(yyextra->attr_vendor);
+ g_free(yyextra->attr_name);
+ yyextra->linenums[yyextra->include_stack_ptr]++;
BEGIN WS_OUT;
};
-<VALUE>[0-9a-z_/-]+ { attr_name = g_strdup(yytext); BEGIN VALUE_W_ATTR; }
-<VALUE_W_ATTR>[^[:blank:]]+ { value_repr = g_strdup(yytext); BEGIN VALUE_W_NAME; }
-<VALUE_W_NAME>[0-9]+ { add_value(attr_name,value_repr, (guint32) strtoul(yytext,NULL,10)); g_free(attr_name); g_free(value_repr); BEGIN WS_OUT;}
-<VALUE_W_NAME>0x[0-9a-f]+ { add_value(attr_name,value_repr, (guint32) strtoul(yytext,NULL,16)); g_free(attr_name); g_free(value_repr); BEGIN WS_OUT;}
+<VALUE>[0-9a-z_/-]+ { yyextra->attr_name = g_strdup(yytext); BEGIN VALUE_W_ATTR; }
+<VALUE_W_ATTR>[^[:blank:]]+ { yyextra->value_repr = g_strdup(yytext); BEGIN VALUE_W_NAME; }
+<VALUE_W_NAME>[0-9]+ { add_value(yyextra, yyextra->attr_name,yyextra->value_repr, (guint32) strtoul(yytext,NULL,10)); g_free(yyextra->attr_name); g_free(yyextra->value_repr); BEGIN WS_OUT;}
+<VALUE_W_NAME>0x[0-9a-f]+ { add_value(yyextra, yyextra->attr_name,yyextra->value_repr, (guint32) strtoul(yytext,NULL,16)); g_free(yyextra->attr_name); g_free(yyextra->value_repr); BEGIN WS_OUT;}
<INCLUDE>[^[:blank:]\n]+ {
- if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
- g_string_append_printf(error, "$INCLUDE files nested to deeply\n");
+ if ( yyextra->include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
+ g_string_append_printf(yyextra->error, "$INCLUDE files nested too deeply\n");
yyterminate();
}
- include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
+ yyextra->include_stack[yyextra->include_stack_ptr++] = YY_CURRENT_BUFFER;
- fullpaths[include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
- directory,yytext);
+ yyextra->fullpaths[yyextra->include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
+ yyextra->directory,yytext);
- yyin = ws_fopen( fullpaths[include_stack_ptr], "r" );
+ yyin = ws_fopen( yyextra->fullpaths[yyextra->include_stack_ptr], "r" );
if (!yyin) {
if (errno) {
- g_string_append_printf(error,
+ g_string_append_printf(yyextra->error,
"Could not open file: '%s', error: %s\n",
- fullpaths[include_stack_ptr],
+ yyextra->fullpaths[yyextra->include_stack_ptr],
g_strerror(errno) );
} else {
- g_string_append_printf(error,
+ g_string_append_printf(yyextra->error,
"Could not open file: '%s', no errno\n",
- fullpaths[include_stack_ptr]);
+ yyextra->fullpaths[yyextra->include_stack_ptr]);
}
- g_free(fullpaths[include_stack_ptr]);
- fullpaths[include_stack_ptr] = NULL;
- include_stack_ptr--;
+ g_free(yyextra->fullpaths[yyextra->include_stack_ptr]);
+ yyextra->fullpaths[yyextra->include_stack_ptr] = NULL;
+ yyextra->include_stack_ptr--;
} else {
- linenums[include_stack_ptr] = 1;
- yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
+ yyextra->linenums[yyextra->include_stack_ptr] = 1;
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner), yyscanner);
}
@@ -299,28 +343,28 @@
fclose(yyin);
yyin = NULL;
- if ( --include_stack_ptr < 0 ) {
+ if ( --yyextra->include_stack_ptr < 0 ) {
yyterminate();
} else {
- g_free(fullpaths[include_stack_ptr+1]);
- fullpaths[include_stack_ptr+1] = NULL;
+ g_free(yyextra->fullpaths[yyextra->include_stack_ptr+1]);
+ yyextra->fullpaths[yyextra->include_stack_ptr+1] = NULL;
- yy_delete_buffer( YY_CURRENT_BUFFER );
- yy_switch_to_buffer(include_stack[include_stack_ptr]);
+ Radius__delete_buffer(YY_CURRENT_BUFFER, yyscanner);
+ Radius__switch_to_buffer(yyextra->include_stack[yyextra->include_stack_ptr], yyscanner);
}
BEGIN WS_OUT;
}
-\n { linenums[include_stack_ptr]++; BEGIN WS_OUT; }
+\n { yyextra->linenums[yyextra->include_stack_ptr]++; BEGIN WS_OUT; }
%%
-static void add_vendor(const gchar* name, guint32 id, guint type_octets, guint length_octets, gboolean has_flags) {
+static void add_vendor(Radius_scanner_state_t* state, const gchar* name, guint32 id, guint type_octets, guint length_octets, gboolean has_flags) {
radius_vendor_info_t* v;
- v = (radius_vendor_info_t *)g_hash_table_lookup(dict->vendors_by_id, GUINT_TO_POINTER(id));
+ v = (radius_vendor_info_t *)g_hash_table_lookup(state->dict->vendors_by_id, GUINT_TO_POINTER(id));
if (!v) {
/*
@@ -337,8 +381,8 @@ static void add_vendor(const gchar* name, guint32 id, guint type_octets, guint l
v->length_octets = length_octets;
v->has_flags = has_flags;
- g_hash_table_insert(dict->vendors_by_id,GUINT_TO_POINTER(v->code),v);
- g_hash_table_insert(dict->vendors_by_name, (gpointer) v->name, v);
+ g_hash_table_insert(state->dict->vendors_by_id,GUINT_TO_POINTER(v->code),v);
+ g_hash_table_insert(state->dict->vendors_by_name, (gpointer) v->name, v);
} else {
/*
* This vendor is already in the table.
@@ -367,38 +411,36 @@ static void add_vendor(const gchar* name, guint32 id, guint type_octets, guint l
* Yes. Remove the entry from the by-name hash table
* and re-insert it with the new name.
*/
- g_hash_table_remove(dict->vendors_by_name, (gpointer) v->name);
+ g_hash_table_remove(state->dict->vendors_by_name, (gpointer) v->name);
g_free((gpointer) v->name);
v->name = g_strdup(name);
- g_hash_table_insert(dict->vendors_by_name, (gpointer) v->name, v);
+ g_hash_table_insert(state->dict->vendors_by_name, (gpointer) v->name, v);
}
}
}
-static void add_attribute(const gchar* name, const gchar* codestr, radius_attr_dissector_t type, const gchar* vendor, guint encrypted_flag, gboolean tagged, const gchar* attr) {
+static gboolean add_attribute(Radius_scanner_state_t* state, const gchar* name, const gchar* codestr, radius_attr_dissector_t type, const gchar* vendor, guint encrypted_flag, gboolean tagged, const gchar* attr) {
radius_attr_info_t* a;
GHashTable* by_id;
guint32 code;
if (attr){
- add_tlv(name, codestr, type, attr);
- return;
+ return add_tlv(state, name, codestr, type, attr);
}
if (vendor) {
radius_vendor_info_t* v;
- v = (radius_vendor_info_t *)g_hash_table_lookup(dict->vendors_by_name,vendor);
+ v = (radius_vendor_info_t *)g_hash_table_lookup(state->dict->vendors_by_name,vendor);
if (! v) {
- g_string_append_printf(error, "Vendor: '%s', does not exist in %s:%i \n", vendor, fullpaths[include_stack_ptr], linenums[include_stack_ptr] );
- BEGIN JUNK;
- return;
+ g_string_append_printf(state->error, "Vendor: '%s', does not exist in %s:%i \n", vendor, state->fullpaths[state->include_stack_ptr], state->linenums[state->include_stack_ptr] );
+ return FALSE;
} else {
by_id = v->attrs_by_id;
}
} else {
- by_id = dict->attrs_by_id;
+ by_id = state->dict->attrs_by_id;
}
code= (guint32) strtoul(codestr, NULL, 10);
@@ -426,7 +468,7 @@ static void add_attribute(const gchar* name, const gchar* codestr, radius_attr_
a->ett = -1;
a->tlvs_by_id = NULL;
g_hash_table_insert(by_id, GUINT_TO_POINTER(code),a);
- g_hash_table_insert(dict->attrs_by_name,(gpointer) (a->name),a);
+ g_hash_table_insert(state->dict->attrs_by_name,(gpointer) (a->name),a);
} else {
/*
* This attribute is already in the table.
@@ -454,31 +496,30 @@ static void add_attribute(const gchar* name, const gchar* codestr, radius_attr_
* Yes. Remove the entry from the by-name hash table
* and re-insert it with the new name.
*/
- g_hash_table_remove(dict->attrs_by_name, (gpointer) (a->name));
+ g_hash_table_remove(state->dict->attrs_by_name, (gpointer) (a->name));
g_free((gpointer) a->name);
a->name = g_strdup(name);
- g_hash_table_insert(dict->attrs_by_name, (gpointer) (a->name),a);
+ g_hash_table_insert(state->dict->attrs_by_name, (gpointer) (a->name),a);
}
}
+ return TRUE;
}
-static void add_tlv(const gchar* name, const gchar* codestr, radius_attr_dissector_t type, const gchar* attr) {
+static gboolean add_tlv(Radius_scanner_state_t* state, const gchar* name, const gchar* codestr, radius_attr_dissector_t type, const gchar* attr) {
radius_attr_info_t* a;
radius_attr_info_t* s;
guint32 code;
- a = (radius_attr_info_t*)g_hash_table_lookup(dict->attrs_by_name, attr);
+ a = (radius_attr_info_t*)g_hash_table_lookup(state->dict->attrs_by_name, attr);
if (! a) {
- g_string_append_printf(error, "Attr: '%s', does not exist in %s:%i \n", attr, fullpaths[include_stack_ptr], linenums[include_stack_ptr]);
- BEGIN JUNK;
- return;
+ g_string_append_printf(state->error, "Attr: '%s', does not exist in %s:%i \n", attr, state->fullpaths[state->include_stack_ptr], state->linenums[state->include_stack_ptr]);
+ return FALSE;
}
if (type == radius_tlv) {
- g_string_append_printf(error, "sub-TLV: '%s', sub-TLV's type is specified as tlv in %s:%i \n", name, fullpaths[include_stack_ptr], linenums[include_stack_ptr]);
- BEGIN JUNK;
- return;
+ g_string_append_printf(state->error, "sub-TLV: '%s', sub-TLV's type is specified as tlv in %s:%i \n", name, state->fullpaths[state->include_stack_ptr], state->linenums[state->include_stack_ptr]);
+ return FALSE;
}
@@ -512,7 +553,7 @@ static void add_tlv(const gchar* name, const gchar* codestr, radius_attr_dissec
s->tlvs_by_id = NULL;
g_hash_table_insert(a->tlvs_by_id,GUINT_TO_POINTER(s->code),s);
- g_hash_table_insert(dict->tlvs_by_name,(gpointer) (s->name),s);
+ g_hash_table_insert(state->dict->tlvs_by_name,(gpointer) (s->name),s);
}
/*
@@ -522,17 +563,18 @@ static void add_tlv(const gchar* name, const gchar* codestr, radius_attr_dissec
* one adding some TLV values), and we don't directly add entries
* for TLVs in the RADIUS dissector.
*
- * XXX - report the duplicate entries?
+ * XXX - report the duplicate entries?
*/
+ return TRUE;
}
-void add_value(const gchar* attrib_name, const gchar* repr, guint32 value) {
+void add_value(Radius_scanner_state_t* state, const gchar* attrib_name, const gchar* repr, guint32 value) {
value_string v;
- GArray* a = (GArray*)g_hash_table_lookup(value_strings,attrib_name);
+ GArray* a = (GArray*)g_hash_table_lookup(state->value_strings,attrib_name);
if (! a) {
a = g_array_new(TRUE,TRUE,sizeof(value_string));
- g_hash_table_insert(value_strings,g_strdup(attrib_name),a);
+ g_hash_table_insert(state->value_strings,g_strdup(attrib_name),a);
}
v.value = value;
@@ -541,8 +583,9 @@ void add_value(const gchar* attrib_name, const gchar* repr, guint32 value) {
g_array_append_val(a,v);
}
-static void setup_tlvs(gpointer k _U_, gpointer v, gpointer p _U_) {
+static void setup_tlvs(gpointer k _U_, gpointer v, gpointer p) {
radius_attr_info_t* s = (radius_attr_info_t*)v;
+ Radius_scanner_state_t* state = (Radius_scanner_state_t*)p;
gpointer key;
union {
@@ -550,16 +593,17 @@ static void setup_tlvs(gpointer k _U_, gpointer v, gpointer p _U_) {
gpointer p;
} vs;
- if (g_hash_table_lookup_extended(value_strings, s->name, &key, &vs.p)) {
+ if (g_hash_table_lookup_extended(state->value_strings, s->name, &key, &vs.p)) {
s->vs = (value_string*)(void *)vs.a->data;
g_array_free(vs.a, FALSE);
- g_hash_table_remove(value_strings, key);
+ g_hash_table_remove(state->value_strings, key);
g_free(key);
}
}
-static void setup_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
+static void setup_attrs(gpointer k _U_, gpointer v, gpointer p) {
radius_attr_info_t* a = (radius_attr_info_t*)v;
+ Radius_scanner_state_t* state = (Radius_scanner_state_t*)p;
gpointer key;
union {
@@ -567,10 +611,10 @@ static void setup_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
gpointer p;
} vs;
- if (g_hash_table_lookup_extended(value_strings,a->name,&key,&vs.p) ) {
+ if (g_hash_table_lookup_extended(state->value_strings,a->name,&key,&vs.p) ) {
a->vs = (value_string*)(void *)vs.a->data;
g_array_free(vs.a,FALSE);
- g_hash_table_remove(value_strings,key);
+ g_hash_table_remove(state->value_strings,key);
g_free(key);
}
@@ -599,48 +643,89 @@ static gboolean destroy_value_strings(gpointer k, gpointer v, gpointer p _U_) {
}
gboolean radius_load_dictionary (radius_dictionary_t* d, gchar* dir, const gchar* filename, gchar** err_str) {
+ FILE *in;
+ yyscan_t scanner;
+ Radius_scanner_state_t state;
int i;
- dict = d;
- directory = dir;
+ state.include_stack_ptr = 0;
+
+ state.dict = d;
+ state.value_strings = NULL;
+
+ state.attr_name = NULL;
+ state.attr_id = NULL;
+ state.attr_type = NULL;
+ state.attr_vendor = NULL;
+ state.vendor_name = NULL;
+ state.vendor_id = 0;
+ state.vendor_type_octets = 1;
+ state.vendor_length_octets = 1;
+ state.vendor_has_flags = FALSE;
+ state.value_repr = NULL;
+ state.encrypted = 0;
+ state.has_tag = FALSE;
+ state.current_vendor = NULL;
+ state.current_attr = NULL;
+
+ state.directory = dir;
+
+ state.fullpaths[0] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
+ state.directory,filename);
+ state.linenums[0] = 1;
+ for (i = 1; i < MAX_INCLUDE_DEPTH; i++) {
+ state.fullpaths[i] = NULL;
+ state.linenums[i] = 1;
+ }
- fullpaths[include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
- directory,filename);
+ state.error = g_string_new("");
- error = g_string_new("");
+ in = ws_fopen(state.fullpaths[0],"r");
- yyin = ws_fopen(fullpaths[include_stack_ptr],"r");
+ if (!in) {
+ g_string_append_printf(state.error, "Could not open file: '%s', error: %s\n", state.fullpaths[0], g_strerror(errno));
+ g_free(state.fullpaths[0]);
+ *err_str = g_string_free(state.error,FALSE);
+ return FALSE;
+ }
- if (!yyin) {
- g_string_append_printf(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], g_strerror(errno) );
- g_free(fullpaths[include_stack_ptr]);
- *err_str = g_string_free(error,FALSE);
+ state.value_strings = g_hash_table_new(g_str_hash,g_str_equal);
+
+ if (Radius_lex_init(&scanner) != 0) {
+ g_string_append_printf(state.error, "Can't initialize scanner: %s",
+ strerror(errno));
+ fclose(in);
+ g_free(state.fullpaths[0]);
+ *err_str = g_string_free(state.error,FALSE);
return FALSE;
}
- value_strings = g_hash_table_new(g_str_hash,g_str_equal);
+ Radius_set_in(in, scanner);
- BEGIN WS_OUT;
+ /* Associate the state with the scanner */
+ Radius_set_extra(&state, scanner);
- yylex();
+ Radius_lex(scanner);
- if (yyin != NULL) fclose(yyin);
- yyin = NULL;
+ Radius_lex_destroy(scanner);
+
+ fclose(in);
- for (i=0; i < 10; i++) {
- if (fullpaths[i]) g_free(fullpaths[i]);
+ for (i = 0; i < MAX_INCLUDE_DEPTH; i++) {
+ if (state.fullpaths[i])
+ g_free(state.fullpaths[i]);
}
- g_hash_table_foreach(dict->attrs_by_id,setup_attrs,NULL);
- g_hash_table_foreach(dict->vendors_by_id,setup_vendors,NULL);
- g_hash_table_foreach_remove(value_strings,destroy_value_strings,NULL);
+ g_hash_table_foreach(state.dict->attrs_by_id,setup_attrs,&state);
+ g_hash_table_foreach(state.dict->vendors_by_id,setup_vendors,&state);
+ g_hash_table_foreach_remove(state.value_strings,destroy_value_strings,NULL);
- if (error->len > 0) {
- *err_str = g_string_free(error,FALSE);
+ if (state.error->len > 0) {
+ *err_str = g_string_free(state.error,FALSE);
return FALSE;
} else {
*err_str = NULL;
- g_string_free(error,TRUE);
+ g_string_free(state.error,TRUE);
return TRUE;
}
}
diff --git a/epan/uat_load.l b/epan/uat_load.l
index 149c03226b..a27fb2ff2d 100644
--- a/epan/uat_load.l
+++ b/epan/uat_load.l
@@ -1,4 +1,9 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
* We don't use input, so don't generate code for it.
*/
%option noinput
@@ -19,11 +24,41 @@
%option noyywrap
/*
+ * The type for the state we keep for a scanner.
+ */
+%option extra-type="uat_load_scanner_state_t *"
+
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide our own versions of the routines generated by Flex, which
+ * have a "yes, this is unused, don't complain about it" flag for yyscanner.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
+/*
* Prefix scanner routines with "uat_load_" rather than "yy", so this scanner
* can coexist with other scanners.
*/
%option prefix="uat_load_"
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
%{
/*
* uat_load.l
@@ -62,7 +97,6 @@
#include <glib.h>
#include "uat-int.h"
-#include "uat_load_lex.h"
#include <wsutil/file_util.h>
#ifdef _WIN32
@@ -71,41 +105,44 @@
#pragma warning (disable:4018)
#endif
-static uat_t* uat;
-static gboolean valid_record;
-static guint colnum;
-static gchar* ptrx;
-static guint len;
-static gchar* error;
-static void* record;
-static guint linenum;
-static gchar *parse_str;
-static size_t parse_str_pos;
+typedef struct {
+ uat_t* uat;
+ gchar *parse_str;
+
+ gchar* error;
+ gboolean valid_record;
+ guint colnum;
+ gchar* ptrx;
+ guint len;
+ void* record;
+ guint linenum;
+ size_t parse_str_pos;
+} uat_load_scanner_state_t;
#define ERROR(fmtd) do { \
char* fmt_str = g_strdup_printf fmtd; \
- error = g_strdup_printf("%s:%d: %s",uat->filename,linenum,fmt_str); \
+ yyextra->error = g_strdup_printf("%s:%d: %s",yyextra->uat->filename,yyextra->linenum,fmt_str); \
g_free(fmt_str); \
yyterminate(); \
} while(0)
#define SET_FIELD() \
{ gchar* errx; \
- if (uat->fields[colnum].cb.chk) { \
- if ( ! uat->fields[colnum].cb.chk(record, ptrx, len, uat->fields[colnum].cbdata.chk, uat->fields[colnum].fld_data, &errx) ) { \
- error = g_strdup_printf("%s:%d: %s",uat->filename,linenum,errx); \
+ if (yyextra->uat->fields[yyextra->colnum].cb.chk) { \
+ if ( ! yyextra->uat->fields[yyextra->colnum].cb.chk(yyextra->record, yyextra->ptrx, yyextra->len, yyextra->uat->fields[yyextra->colnum].cbdata.chk, yyextra->uat->fields[yyextra->colnum].fld_data, &errx) ) { \
+ yyextra->error = g_strdup_printf("%s:%d: %s",yyextra->uat->filename,yyextra->linenum,errx); \
g_free(errx); \
- valid_record = FALSE; \
+ yyextra->valid_record = FALSE; \
}\
}\
- uat->fields[colnum].cb.set(record, ptrx, len, uat->fields[colnum].cbdata.chk, uat->fields[colnum].fld_data);\
- g_free(ptrx);\
- colnum++; \
+ yyextra->uat->fields[yyextra->colnum].cb.set(yyextra->record, yyextra->ptrx, yyextra->len, yyextra->uat->fields[yyextra->colnum].cbdata.chk, yyextra->uat->fields[yyextra->colnum].fld_data);\
+ g_free(yyextra->ptrx);\
+ yyextra->colnum++; \
} while(0)
#ifdef DEBUG_UAT_LOAD
#define DUMP_FIELD(str) \
- { guint i; printf("%s: %s='",str,uat->fields[colnum].name); for(i=0;i<len;i++) if (uat->fields[colnum].mode == PT_TXTMOD_HEXBYTES) { printf("%.2x ",((guint8*)ptrx)[i]); } else putc(ptrx[i],stdout); printf("'[%d]\n",len); }
+ { guint i; printf("%s: %s='",str,yyextra->uat->fields[yyextra->colnum].name); for(i=0;i<yyextra->len;i++) if (yyextra->uat->fields[yyextra->colnum].mode == PT_TXTMOD_HEXBYTES) { printf("%.2x ",((guint8*)yyextra->ptrx)[i]); } else putc(yyextra->ptrx[i],stdout); printf("'[%d]\n",yyextra->len); }
#define DUMP(str) printf("%s\n",str)
#else
@@ -115,16 +152,16 @@ static size_t parse_str_pos;
/* Modified version of YY_INPUT generated by Flex 2.91 */
#define YY_INPUT(buf,result,max_size) \
- if ( parse_str ) \
+ if ( yyextra->parse_str ) \
{ \
size_t n = 0; \
- size_t pslen = strlen(parse_str); \
- if (parse_str_pos < pslen) \
+ size_t pslen = strlen(yyextra->parse_str); \
+ if (yyextra->parse_str_pos < pslen) \
{ \
- n = pslen - parse_str_pos; \
+ n = pslen - yyextra->parse_str_pos; \
if (n > max_size) n = max_size; \
- memcpy(buf, parse_str + parse_str_pos, n); \
- parse_str_pos += n; \
+ memcpy(buf, yyextra->parse_str + yyextra->parse_str_pos, n); \
+ yyextra->parse_str_pos += n; \
} \
result = n; \
} \
@@ -148,6 +185,21 @@ static size_t parse_str_pos;
* quoted_string below fails badly on "...\\"
* workarround in uat_save(), using /x5c and /x22
*/
+
+#define YY_USER_INIT BEGIN START_OF_LINE;
+
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
+
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define uat_load_alloc(size, yyscanner) (void *)malloc(size)
+#define uat_load_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define uat_load_free(ptr, yyscanner) free((char *)ptr)
+
%}
quoted_string \042([^\042]|\134\042)*\042
@@ -160,18 +212,18 @@ comment #[^\n]*\n
%x START_OF_LINE NEXT_FIELD SEPARATOR END_OF_RECORD ERRORED
%%
<START_OF_LINE,NEXT_FIELD>{ws} ;
-<START_OF_LINE>{newline} linenum++;
-<START_OF_LINE>{comment} linenum++;
+<START_OF_LINE>{newline} yyextra->linenum++;
+<START_OF_LINE>{comment} yyextra->linenum++;
<START_OF_LINE,NEXT_FIELD>{separator} {
- ptrx = g_strdup("");
- len = 0;
+ yyextra->ptrx = g_strdup("");
+ yyextra->len = 0;
DUMP_FIELD("empty->next");
SET_FIELD();
- if ( colnum >= uat->ncols ) {
+ if ( yyextra->colnum >= yyextra->uat->ncols ) {
ERROR(("more fields than required"));
}
@@ -179,8 +231,8 @@ comment #[^\n]*\n
}
<START_OF_LINE,NEXT_FIELD>{newline} {
- ptrx = g_strdup("");
- len = 0;
+ yyextra->ptrx = g_strdup("");
+ yyextra->len = 0;
BEGIN END_OF_RECORD;
@@ -188,10 +240,10 @@ comment #[^\n]*\n
}
<START_OF_LINE,NEXT_FIELD>{quoted_string} {
- ptrx = uat_undquote(yytext, (guint) yyleng, &len);
+ yyextra->ptrx = uat_undquote(yytext, (guint) yyleng, &yyextra->len);
- if (colnum < uat->ncols - 1) {
+ if (yyextra->colnum < yyextra->uat->ncols - 1) {
DUMP("quoted_str->s");
BEGIN SEPARATOR;
} else {
@@ -201,13 +253,13 @@ comment #[^\n]*\n
}
<START_OF_LINE,NEXT_FIELD>{binstring} {
- ptrx = uat_unbinstring(yytext, (guint) yyleng, &len);
+ yyextra->ptrx = uat_unbinstring(yytext, (guint) yyleng, &yyextra->len);
- if (!ptrx) {
- ERROR(("uneven hexstring for field %s",uat->fields[colnum].name));
+ if (!yyextra->ptrx) {
+ ERROR(("uneven hexstring for field %s",yyextra->uat->fields[yyextra->colnum].name));
}
- if ( colnum < uat->ncols - 1 ) {
+ if ( yyextra->colnum < yyextra->uat->ncols - 1 ) {
DUMP("binstring->s");
BEGIN SEPARATOR;
} else {
@@ -222,7 +274,7 @@ comment #[^\n]*\n
SET_FIELD();
- if ( colnum >= uat->ncols ) {
+ if ( yyextra->colnum >= yyextra->uat->ncols ) {
ERROR(("more fields than required"));
}
@@ -230,12 +282,12 @@ comment #[^\n]*\n
}
<SEPARATOR>{newline} {
- linenum++;
- ERROR(("expecting field %s in previous line",uat->fields[colnum].name));
+ yyextra->linenum++;
+ ERROR(("expecting field %s in previous line",yyextra->uat->fields[yyextra->colnum].name));
}
<SEPARATOR>. {
- ERROR(("unexpected char '%s' while looking for field %s",yytext,uat->fields[colnum].name));
+ ERROR(("unexpected char '%s' while looking for field %s",yytext,yyextra->uat->fields[yyextra->colnum].name));
}
<END_OF_RECORD>{separator} {
@@ -246,28 +298,28 @@ comment #[^\n]*\n
void* rec;
char* err = NULL;
- linenum++;
+ yyextra->linenum++;
DUMP_FIELD("newline->start");
SET_FIELD();
- rec = uat_add_record(uat, record, valid_record);
+ rec = uat_add_record(yyextra->uat, yyextra->record, yyextra->valid_record);
- if ((uat->update_cb) && (rec != NULL)) {
- if (!uat->update_cb(rec,&err)) {
- error = err;
+ if ((yyextra->uat->update_cb) && (rec != NULL)) {
+ if (!yyextra->uat->update_cb(rec,&err)) {
+ yyextra->error = err;
yyterminate();
}
}
- valid_record = TRUE;
- colnum = 0;
- ptrx = NULL;
- len = 0;
+ yyextra->valid_record = TRUE;
+ yyextra->colnum = 0;
+ yyextra->ptrx = NULL;
+ yyextra->len = 0;
/* XXX is this necessary since we free it before reusing anyway? */
- memset(record,0,uat->record_size);
+ memset(yyextra->record,0,yyextra->uat->record_size);
BEGIN START_OF_LINE;
}
@@ -276,10 +328,10 @@ comment #[^\n]*\n
ERROR(("unexpected char while looking for end of line"));
}
-<ERRORED>{newline} { linenum++; BEGIN START_OF_LINE; }
+<ERRORED>{newline} { yyextra->linenum++; BEGIN START_OF_LINE; }
<ERRORED>. ;
-{newline} { linenum++; ERROR(("incomplete record")); }
+{newline} { yyextra->linenum++; ERROR(("incomplete record")); }
. { ERROR(("unexpected input")); }
%%
@@ -288,12 +340,12 @@ comment #[^\n]*\n
gboolean
-uat_load(uat_t *uat_in, char **errx)
+uat_load(uat_t *uat, char **errx)
{
- gchar *fname = uat_get_actual_filename(uat_in, FALSE);
-
- uat = uat_in;
- parse_str = NULL;
+ gchar *fname = uat_get_actual_filename(uat, FALSE);
+ FILE *in;
+ yyscan_t scanner;
+ uat_load_scanner_state_t state;
if (!fname) {
UAT_UPDATE(uat);
@@ -305,33 +357,51 @@ uat_load(uat_t *uat_in, char **errx)
}
- if (!(yyin = ws_fopen(fname,"r"))) {
+ if (!(in = ws_fopen(fname,"r"))) {
*errx = g_strdup(g_strerror(errno));
g_free(fname);
return FALSE;
}
- error = NULL;
- valid_record = TRUE;
- colnum = 0;
- g_free(record);
- record = g_malloc0(uat->record_size);
- linenum = 1;
+ if (uat_load_lex_init(&scanner) != 0) {
+ *errx = g_strdup(g_strerror(errno));
+ fclose(in);
+ g_free(fname);
+ return FALSE;
+ }
+
+ uat_load_set_in(in, scanner);
+
+ state.uat = uat;
+ state.parse_str = NULL; /* we're reading from a file */
+
+ state.error = NULL;
+ state.valid_record = TRUE;
+ state.colnum = 0;
+ state.ptrx = NULL;
+ state.len = 0;
+ state.record = g_malloc0(uat->record_size);
+ state.linenum = 1;
+ state.parse_str_pos = 0;
- BEGIN START_OF_LINE;
DUMP(fname);
g_free(fname); /* we're done with the file name now */
- yylex();
- fclose(yyin);
- yyrestart(NULL);
+ /* Associate the state with the scanner */
+ uat_load_set_extra(&state, scanner);
+
+ uat_load_lex(scanner);
+
+ uat_load_lex_destroy(scanner);
+ g_free(state.record);
+ fclose(in);
uat->changed = FALSE;
uat->loaded = TRUE;
UAT_UPDATE(uat);
- if (error) {
- *errx = error;
+ if (state.error) {
+ *errx = state.error;
return FALSE;
}
@@ -343,34 +413,47 @@ uat_load(uat_t *uat_in, char **errx)
}
gboolean
-uat_load_str(uat_t *uat_in, char *entry, char **err)
+uat_load_str(uat_t *uat, char *entry, char **err)
{
- uat = uat_in;
- parse_str = g_strdup_printf("%s\n", entry); /* Records must end with a newline */
- parse_str_pos = 0;
- yyin = NULL;
-
- error = NULL;
- valid_record = TRUE;
- colnum = 0;
- g_free(record);
- record = g_malloc0(uat->record_size);
- linenum = 1;
+ yyscan_t scanner;
+ uat_load_scanner_state_t state;
+
+ state.uat = uat;
+ state.parse_str = g_strdup_printf("%s\n", entry); /* Records must end with a newline */
+
+ state.error = NULL;
+ state.valid_record = TRUE;
+ state.colnum = 0;
+ state.ptrx = NULL;
+ state.len = 0;
+ state.record = g_malloc0(uat->record_size);
+ state.linenum = 1;
+ state.parse_str_pos = 0;
+
+ if (uat_load_lex_init(&scanner) != 0) {
+ *err = g_strdup(g_strerror(errno));
+ g_free(state.parse_str);
+ g_free(state.record);
+ return FALSE;
+ }
- BEGIN START_OF_LINE;
DUMP(entry);
- yylex();
- yyrestart(NULL);
- g_free(parse_str);
- parse_str = NULL;
+ /* Associate the state with the scanner */
+ uat_load_set_extra(&state, scanner);
+
+ uat_load_lex(scanner);
+
+ uat_load_lex_destroy(scanner);
+ g_free(state.record);
+ g_free(state.parse_str);
uat->changed = TRUE;
uat->loaded = TRUE;
UAT_UPDATE(uat);
- if (error) {
- *err = error;
+ if (state.error) {
+ *err = state.error;
return FALSE;
}
diff --git a/plugins/mate/Makefile.am b/plugins/mate/Makefile.am
index fe1cc4d6ad..26647b445c 100644
--- a/plugins/mate/Makefile.am
+++ b/plugins/mate/Makefile.am
@@ -50,7 +50,8 @@ mate_la_CFLAGS = $(GENERATED_CFLAGS) $(PLUGIN_CFLAGS)
mate_la_LDFLAGS = $(PLUGIN_LDFLAGS)
BUILT_SOURCES = \
- $(LEMON_GENERATED_HEADER_FILES)
+ $(LEMON_GENERATED_HEADER_FILES) \
+ $(FLEX_GENERATED_HEADER_FILES)
CLEANFILES = \
mate \
diff --git a/plugins/mate/mate_parser.l b/plugins/mate/mate_parser.l
index 865b8d138c..706900b839 100644
--- a/plugins/mate/mate_parser.l
+++ b/plugins/mate/mate_parser.l
@@ -1,4 +1,9 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
* We don't use input, so don't generate code for it.
*/
%option noinput
@@ -19,10 +24,28 @@
%option noyywrap
/*
- * Prefix scanner routines with "Mate" rather than "yy", so this scanner
+ * The type for the state we keep for a scanner.
+ */
+%option extra-type="Mate_scanner_state_t *"
+
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
+/*
+ * Prefix scanner routines with "Mate_" rather than "yy", so this scanner
* can coexist with other scanners.
*/
-%option prefix="Mate"
+%option prefix="Mate_"
%{
@@ -52,7 +75,6 @@
#include "mate.h"
#include "mate_grammar.h"
-#include "mate_parser_lex.h"
#include <wsutil/file_util.h>
@@ -72,15 +94,18 @@
void MateParseTrace(FILE*,char*);
#define MAX_INCLUDE_DEPTH 10
- static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
- static int include_stack_ptr = 0;
+typedef struct {
+ mate_config* mc;
- static void* pParser;
- static mate_config_frame* current_frame;
+ mate_config_frame* current_frame;
- static mate_config* mc;
+ void* pParser;
-#define MATE_PARSE(token_type) MateParser(pParser, (token_type), g_strdup(yytext), mc );
+ YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+ int include_stack_ptr;
+} Mate_scanner_state_t;
+
+#define MATE_PARSE(token_type) MateParser(yyextra->pParser, (token_type), g_strdup(yytext), yyextra->mc);
/*
* Flex (v 2.5.35) uses this symbol to "exclude" unistd.h
@@ -94,6 +119,20 @@ static void free_config_frame(mate_config_frame *frame) {
g_free(frame);
}
+#define YY_USER_INIT BEGIN OUTSIDE;
+
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
+
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define Mate_alloc(size, yyscanner) (void *)malloc(size)
+#define Mate_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define Mate_free(ptr, yyscanner) free((char *)ptr)
+
%}
pdu_kw Pdu
@@ -176,36 +215,36 @@ blk_cmnt_stop "*/"
%START OUTSIDE QUOTED INCLUDING COMMENT
%%
-{newline} current_frame->linenum++;
-{whitespace} ;
+{newline} yyextra->current_frame->linenum++;
+{whitespace} ;
-<OUTSIDE>{include} BEGIN INCLUDING;
+<OUTSIDE>{include} BEGIN INCLUDING;
<INCLUDING>{filename} {
- if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
+ if ( yyextra->include_stack_ptr >= MAX_INCLUDE_DEPTH )
g_error("dtd_preparse: include files nested too deeply");
- include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
+ yyextra->include_stack[yyextra->include_stack_ptr++] = YY_CURRENT_BUFFER;
yyin = ws_fopen( yytext, "r" );
if (!yyin) {
- yy_delete_buffer( YY_CURRENT_BUFFER );
+ Mate__delete_buffer(YY_CURRENT_BUFFER, yyscanner);
/* coverity[negative_sink] */
- yy_switch_to_buffer(include_stack[--include_stack_ptr] );
+ Mate__switch_to_buffer(yyextra->include_stack[--yyextra->include_stack_ptr], yyscanner);
if (errno)
- g_string_append_printf(mc->config_error, "Mate parser: Could not open file: '%s': %s", yytext, g_strerror(errno) );
+ g_string_append_printf(yyextra->mc->config_error, "Mate parser: Could not open file: '%s': %s", yytext, g_strerror(errno) );
} else {
- current_frame = (mate_config_frame *)g_malloc(sizeof(mate_config_frame));
- current_frame->filename = g_strdup(yytext);
- current_frame->linenum = 1;
+ yyextra->current_frame = (mate_config_frame *)g_malloc(sizeof(mate_config_frame));
+ yyextra->current_frame->filename = g_strdup(yytext);
+ yyextra->current_frame->linenum = 1;
- g_ptr_array_add(mc->config_stack,current_frame);
+ g_ptr_array_add(yyextra->mc->config_stack,yyextra->current_frame);
- yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
+ Mate__switch_to_buffer(Mate__create_buffer(yyin, YY_BUF_SIZE, yyscanner), yyscanner);
}
BEGIN OUTSIDE;
@@ -213,134 +252,150 @@ blk_cmnt_stop "*/"
<<EOF>> {
/* coverity[check_after_sink] */
- if ( --include_stack_ptr < 0 ) {
+ if ( --yyextra->include_stack_ptr < 0 ) {
yyterminate();
} else {
- yy_delete_buffer( YY_CURRENT_BUFFER );
- yy_switch_to_buffer( include_stack[include_stack_ptr] );
+ Mate__delete_buffer(YY_CURRENT_BUFFER, yyscanner);
+ Mate__switch_to_buffer(yyextra->include_stack[yyextra->include_stack_ptr], yyscanner);
- free_config_frame(current_frame);
- current_frame = (mate_config_frame *)g_ptr_array_remove_index(mc->config_stack,mc->config_stack->len-1);
+ free_config_frame(yyextra->current_frame);
+ yyextra->current_frame = (mate_config_frame *)g_ptr_array_remove_index(yyextra->mc->config_stack,yyextra->mc->config_stack->len-1);
}
}
-<OUTSIDE>{comment} ;
+<OUTSIDE>{comment} ;
-<OUTSIDE>{blk_cmnt_start} BEGIN COMMENT;
+<OUTSIDE>{blk_cmnt_start} BEGIN COMMENT;
<COMMENT>{cmnt_char} ;
<COMMENT>{blk_cmnt_stop} BEGIN OUTSIDE;
-<OUTSIDE>{pdu_kw} MATE_PARSE(TOKEN_PDU_KW);
-<OUTSIDE>{gop_kw} MATE_PARSE(TOKEN_GOP_KW);
-<OUTSIDE>{gog_kw} MATE_PARSE(TOKEN_GOG_KW);
-<OUTSIDE>{transform_kw} MATE_PARSE(TOKEN_TRANSFORM_KW);
-<OUTSIDE>{match_kw} MATE_PARSE(TOKEN_MATCH_KW);
-<OUTSIDE>{strict_kw} MATE_PARSE(TOKEN_STRICT_KW);
-<OUTSIDE>{every_kw} MATE_PARSE(TOKEN_EVERY_KW);
-<OUTSIDE>{loose_kw} MATE_PARSE(TOKEN_LOOSE_KW);
-<OUTSIDE>{replace_kw} MATE_PARSE(TOKEN_REPLACE_KW);
-<OUTSIDE>{insert_kw} MATE_PARSE(TOKEN_INSERT_KW);
-<OUTSIDE>{gop_tree_kw} MATE_PARSE(TOKEN_GOP_TREE_KW);
-<OUTSIDE>{member_kw} MATE_PARSE(TOKEN_MEMBER_KW);
-<OUTSIDE>{on_kw} MATE_PARSE(TOKEN_ON_KW);
-<OUTSIDE>{start_kw} MATE_PARSE(TOKEN_START_KW);
-<OUTSIDE>{stop_kw} MATE_PARSE(TOKEN_STOP_KW);
-<OUTSIDE>{extra_kw} MATE_PARSE(TOKEN_EXTRA_KW);
-<OUTSIDE>{show_tree_kw} MATE_PARSE(TOKEN_SHOW_TREE_KW);
-<OUTSIDE>{show_times_kw} MATE_PARSE(TOKEN_SHOW_TIMES_KW);
-<OUTSIDE>{expiration_kw} MATE_PARSE(TOKEN_EXPIRATION_KW);
-<OUTSIDE>{idle_timeout_kw} MATE_PARSE(TOKEN_IDLE_TIMEOUT_KW);
-<OUTSIDE>{lifetime_kw} MATE_PARSE(TOKEN_LIFETIME_KW);
-<OUTSIDE>{no_tree_kw} MATE_PARSE(TOKEN_NO_TREE_KW);
-<OUTSIDE>{pdu_tree_kw} MATE_PARSE(TOKEN_PDU_TREE_KW);
-<OUTSIDE>{frame_tree_kw} MATE_PARSE(TOKEN_FRAME_TREE_KW);
-<OUTSIDE>{basic_tree_kw} MATE_PARSE(TOKEN_BASIC_TREE_KW);
-<OUTSIDE>{true_kw} MATE_PARSE(TOKEN_TRUE_KW);
-<OUTSIDE>{false_kw} MATE_PARSE(TOKEN_FALSE_KW);
-<OUTSIDE>{proto_kw} MATE_PARSE(TOKEN_PROTO_KW);
-<OUTSIDE>{payload_kw} MATE_PARSE(TOKEN_PAYLOAD_KW);
-<OUTSIDE>{transport_kw} MATE_PARSE(TOKEN_TRANSPORT_KW);
-<OUTSIDE>{criteria_kw} MATE_PARSE(TOKEN_CRITERIA_KW);
-<OUTSIDE>{accept_kw} MATE_PARSE(TOKEN_ACCEPT_KW);
-<OUTSIDE>{reject_kw} MATE_PARSE(TOKEN_REJECT_KW);
-<OUTSIDE>{extract_kw} MATE_PARSE(TOKEN_EXTRACT_KW);
-<OUTSIDE>{from_kw} MATE_PARSE(TOKEN_FROM_KW);
+<OUTSIDE>{pdu_kw} MATE_PARSE(TOKEN_PDU_KW);
+<OUTSIDE>{gop_kw} MATE_PARSE(TOKEN_GOP_KW);
+<OUTSIDE>{gog_kw} MATE_PARSE(TOKEN_GOG_KW);
+<OUTSIDE>{transform_kw} MATE_PARSE(TOKEN_TRANSFORM_KW);
+<OUTSIDE>{match_kw} MATE_PARSE(TOKEN_MATCH_KW);
+<OUTSIDE>{strict_kw} MATE_PARSE(TOKEN_STRICT_KW);
+<OUTSIDE>{every_kw} MATE_PARSE(TOKEN_EVERY_KW);
+<OUTSIDE>{loose_kw} MATE_PARSE(TOKEN_LOOSE_KW);
+<OUTSIDE>{replace_kw} MATE_PARSE(TOKEN_REPLACE_KW);
+<OUTSIDE>{insert_kw} MATE_PARSE(TOKEN_INSERT_KW);
+<OUTSIDE>{gop_tree_kw} MATE_PARSE(TOKEN_GOP_TREE_KW);
+<OUTSIDE>{member_kw} MATE_PARSE(TOKEN_MEMBER_KW);
+<OUTSIDE>{on_kw} MATE_PARSE(TOKEN_ON_KW);
+<OUTSIDE>{start_kw} MATE_PARSE(TOKEN_START_KW);
+<OUTSIDE>{stop_kw} MATE_PARSE(TOKEN_STOP_KW);
+<OUTSIDE>{extra_kw} MATE_PARSE(TOKEN_EXTRA_KW);
+<OUTSIDE>{show_tree_kw} MATE_PARSE(TOKEN_SHOW_TREE_KW);
+<OUTSIDE>{show_times_kw} MATE_PARSE(TOKEN_SHOW_TIMES_KW);
+<OUTSIDE>{expiration_kw} MATE_PARSE(TOKEN_EXPIRATION_KW);
+<OUTSIDE>{idle_timeout_kw} MATE_PARSE(TOKEN_IDLE_TIMEOUT_KW);
+<OUTSIDE>{lifetime_kw} MATE_PARSE(TOKEN_LIFETIME_KW);
+<OUTSIDE>{no_tree_kw} MATE_PARSE(TOKEN_NO_TREE_KW);
+<OUTSIDE>{pdu_tree_kw} MATE_PARSE(TOKEN_PDU_TREE_KW);
+<OUTSIDE>{frame_tree_kw} MATE_PARSE(TOKEN_FRAME_TREE_KW);
+<OUTSIDE>{basic_tree_kw} MATE_PARSE(TOKEN_BASIC_TREE_KW);
+<OUTSIDE>{true_kw} MATE_PARSE(TOKEN_TRUE_KW);
+<OUTSIDE>{false_kw} MATE_PARSE(TOKEN_FALSE_KW);
+<OUTSIDE>{proto_kw} MATE_PARSE(TOKEN_PROTO_KW);
+<OUTSIDE>{payload_kw} MATE_PARSE(TOKEN_PAYLOAD_KW);
+<OUTSIDE>{transport_kw} MATE_PARSE(TOKEN_TRANSPORT_KW);
+<OUTSIDE>{criteria_kw} MATE_PARSE(TOKEN_CRITERIA_KW);
+<OUTSIDE>{accept_kw} MATE_PARSE(TOKEN_ACCEPT_KW);
+<OUTSIDE>{reject_kw} MATE_PARSE(TOKEN_REJECT_KW);
+<OUTSIDE>{extract_kw} MATE_PARSE(TOKEN_EXTRACT_KW);
+<OUTSIDE>{from_kw} MATE_PARSE(TOKEN_FROM_KW);
<OUTSIDE>{drop_unassigned_kw} MATE_PARSE(TOKEN_DROP_UNASSIGNED_KW);
<OUTSIDE>{discard_pdu_data_kw} MATE_PARSE(TOKEN_DISCARD_PDU_DATA_KW);
-<OUTSIDE>{last_pdu_kw} MATE_PARSE(TOKEN_LAST_PDU_KW);
-<OUTSIDE>{done_kw} MATE_PARSE(TOKEN_DONE_KW);
-<OUTSIDE>{filename_kw} MATE_PARSE(TOKEN_FILENAME_KW);
-<OUTSIDE>{debug_kw} MATE_PARSE(TOKEN_DEBUG_KW);
-<OUTSIDE>{level_kw} MATE_PARSE(TOKEN_LEVEL_KW);
-<OUTSIDE>{default_kw} MATE_PARSE(TOKEN_DEFAULT_KW);
-
-<OUTSIDE>{open_parens} MATE_PARSE(TOKEN_OPEN_PARENS);
-<OUTSIDE>{close_parens} MATE_PARSE(TOKEN_CLOSE_PARENS);
-<OUTSIDE>{open_brace} MATE_PARSE(TOKEN_OPEN_BRACE);
-<OUTSIDE>{close_brace} MATE_PARSE(TOKEN_CLOSE_BRACE);
-<OUTSIDE>{comma} MATE_PARSE(TOKEN_COMMA);
-<OUTSIDE>{semicolon} MATE_PARSE(TOKEN_SEMICOLON);
-<OUTSIDE>{slash} MATE_PARSE(TOKEN_SLASH);
-<OUTSIDE>{pipe} MATE_PARSE(TOKEN_PIPE);
-
-<OUTSIDE>{integer} MATE_PARSE(TOKEN_INTEGER);
-<OUTSIDE>{floating} MATE_PARSE(TOKEN_FLOATING);
-<OUTSIDE>{doted_ip} MATE_PARSE(TOKEN_DOTED_IP);
-<OUTSIDE>{colonized} MATE_PARSE(TOKEN_COLONIZED);
-<OUTSIDE>{name} MATE_PARSE(TOKEN_NAME);
-<OUTSIDE>{avp_operator} MATE_PARSE(TOKEN_AVP_OPERATOR);
-
-
-<OUTSIDE>{quote} BEGIN QUOTED;
+<OUTSIDE>{last_pdu_kw} MATE_PARSE(TOKEN_LAST_PDU_KW);
+<OUTSIDE>{done_kw} MATE_PARSE(TOKEN_DONE_KW);
+<OUTSIDE>{filename_kw} MATE_PARSE(TOKEN_FILENAME_KW);
+<OUTSIDE>{debug_kw} MATE_PARSE(TOKEN_DEBUG_KW);
+<OUTSIDE>{level_kw} MATE_PARSE(TOKEN_LEVEL_KW);
+<OUTSIDE>{default_kw} MATE_PARSE(TOKEN_DEFAULT_KW);
+
+<OUTSIDE>{open_parens} MATE_PARSE(TOKEN_OPEN_PARENS);
+<OUTSIDE>{close_parens} MATE_PARSE(TOKEN_CLOSE_PARENS);
+<OUTSIDE>{open_brace} MATE_PARSE(TOKEN_OPEN_BRACE);
+<OUTSIDE>{close_brace} MATE_PARSE(TOKEN_CLOSE_BRACE);
+<OUTSIDE>{comma} MATE_PARSE(TOKEN_COMMA);
+<OUTSIDE>{semicolon} MATE_PARSE(TOKEN_SEMICOLON);
+<OUTSIDE>{slash} MATE_PARSE(TOKEN_SLASH);
+<OUTSIDE>{pipe} MATE_PARSE(TOKEN_PIPE);
+
+<OUTSIDE>{integer} MATE_PARSE(TOKEN_INTEGER);
+<OUTSIDE>{floating} MATE_PARSE(TOKEN_FLOATING);
+<OUTSIDE>{doted_ip} MATE_PARSE(TOKEN_DOTED_IP);
+<OUTSIDE>{colonized} MATE_PARSE(TOKEN_COLONIZED);
+<OUTSIDE>{name} MATE_PARSE(TOKEN_NAME);
+<OUTSIDE>{avp_operator} MATE_PARSE(TOKEN_AVP_OPERATOR);
+
+
+<OUTSIDE>{quote} BEGIN QUOTED;
<QUOTED>{not_quoted} MATE_PARSE(TOKEN_QUOTED);
-<QUOTED>{quote} BEGIN OUTSIDE;
+<QUOTED>{quote} BEGIN OUTSIDE;
%%
-extern gboolean mate_load_config(const gchar* filename, mate_config* matecfg) {
- volatile gboolean state = TRUE;
- mc = matecfg;
+extern gboolean mate_load_config(const gchar* filename, mate_config* mc) {
+ FILE *in;
+ yyscan_t scanner;
+ Mate_scanner_state_t state;
+ volatile gboolean status = TRUE;
- yyin = ws_fopen(filename,"r");
+ in = ws_fopen(filename,"r");
- if (!yyin) {
+ if (!in) {
g_string_append_printf(mc->config_error,"Mate parser: Could not open file: '%s', error: %s", filename, g_strerror(errno) );
return FALSE;
}
+ if (Mate_lex_init(&scanner) != 0) {
+ g_string_append_printf(mc->config_error, "Mate parse: Could not initialize scanner: %s", g_strerror(errno));
+ fclose(in);
+ return FALSE;
+ }
+
+ Mate_set_in(in, scanner);
+
mc->config_stack = g_ptr_array_new();
- current_frame = (mate_config_frame *)g_malloc(sizeof(mate_config_frame));
- current_frame->filename = g_strdup(filename);
- current_frame->linenum = 1;
+ state.mc = mc;
+
+ state.current_frame = (mate_config_frame *)g_malloc(sizeof(mate_config_frame));
+ state.current_frame->filename = g_strdup(filename);
+ state.current_frame->linenum = 1;
+
+ g_ptr_array_add(mc->config_stack,state.current_frame);
+
+ state.pParser = MateParserAlloc(g_malloc);
- g_ptr_array_add(mc->config_stack,current_frame);
+ state.include_stack_ptr = 0;
- pParser = MateParserAlloc(g_malloc);
+ /* Associate the state with the scanner */
+ Mate_set_extra(&state, scanner);
/* MateParserTrace(stdout,""); */
TRY {
- BEGIN OUTSIDE;
-
- yylex();
+ Mate_lex(scanner);
/* Inform parser that end of input has reached. */
- MateParser(pParser, 0, NULL,mc);
-
- yyrestart(NULL);
+ MateParser(state.pParser, 0, NULL, mc);
- MateParserFree(pParser, g_free );
+ MateParserFree(state.pParser, g_free);
} CATCH(MateConfigError) {
- state = FALSE;
+ status = FALSE;
} CATCH_ALL {
- state = FALSE;
+ status = FALSE;
g_string_append_printf(mc->config_error,"An unexpected error occurred");
}
ENDTRY;
+ Mate_lex_destroy(scanner);
+ fclose(in);
+
g_ptr_array_foreach(mc->config_stack, (GFunc)free_config_frame, NULL);
g_ptr_array_free(mc->config_stack, FALSE);
- return state;
+ return status;
}
diff --git a/plugins/wimaxasncp/Makefile.am b/plugins/wimaxasncp/Makefile.am
index e4f4cd7f2f..2e265fbe6f 100644
--- a/plugins/wimaxasncp/Makefile.am
+++ b/plugins/wimaxasncp/Makefile.am
@@ -45,6 +45,10 @@ wimaxasncp_la_CFLAGS = $(GENERATED_CFLAGS) $(PLUGIN_CFLAGS)
wimaxasncp_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+BUILT_SOURCES = \
+ $(LEMON_GENERATED_HEADER_FILES) \
+ $(FLEX_GENERATED_HEADER_FILES)
+
CLEANFILES = \
wimaxasncp \
*~
diff --git a/plugins/wimaxasncp/wimaxasncp_dict.l b/plugins/wimaxasncp/wimaxasncp_dict.l
index cec21a0eed..c34f413154 100644
--- a/plugins/wimaxasncp/wimaxasncp_dict.l
+++ b/plugins/wimaxasncp/wimaxasncp_dict.l
@@ -1,4 +1,9 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
* We don't use input, so don't generate code for it.
*/
%option noinput
@@ -19,6 +24,24 @@
%option noyywrap
/*
+ * The type for the state we keep for a scanner.
+ */
+%option extra-type="WimaxasncpDict_scanner_state_t *"
+
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
+/*
* The language we're scanning is case-insensitive.
*/
%option caseless
@@ -29,10 +52,10 @@
%option stack
/*
- * Prefix scanner routines with "WimaxasncpDict" rather than "yy", so this
+ * Prefix scanner routines with "WimaxasncpDict_" rather than "yy", so this
* scanner can coexist with other scanners.
*/
-%option prefix="WimaxasncpDict"
+%option prefix="WimaxasncpDict_"
%option outfile="wimaxasncp_dict.c"
@@ -73,7 +96,6 @@
#include <wsutil/file_util.h>
#include "wimaxasncp_dict.h"
-#include "wimaxasncp_dict_lex.h"
typedef struct entity_t {
gchar *name;
@@ -81,44 +103,74 @@ typedef struct entity_t {
struct entity_t *next;
} entity_t;
-#define ATTR_UINT(cont) do { D(("attr_uint " #cont "\t" )); attr_uint = &(cont); yy_push_state(GET_UINT_ATTR); } while(0)
-#define ATTR_UINT16(cont) do { D(("attr_uint16 " #cont "\t" )); attr_uint16 = &(cont); yy_push_state(GET_UINT16_ATTR); } while(0)
-#define ATTR_STR(cont) do { D(("attr_str " #cont "\t" )); attr_str = &(cont); yy_push_state(GET_ATTR); } while(0)
-#define ATTR_DECODER(cont) do { D(("attr_decoder " #cont "\t" )); attr_uint = &(cont); yy_push_state(GET_DECODER_ATTR); } while(0)
-#define WIMAXASNCP_IGNORE() do { D(("ignore: %s\t",yytext)); yy_push_state(IGNORE_ATTR); } while(0)
+#define ATTR_UINT(cont) do { D(("attr_uint " #cont "\t" )); yyextra->attr_uint = &(cont); yy_push_state(GET_UINT_ATTR, yyscanner); } while(0)
+#define ATTR_UINT16(cont) do { D(("attr_uint16 " #cont "\t" )); yyextra->attr_uint16 = &(cont); yy_push_state(GET_UINT16_ATTR, yyscanner); } while(0)
+#define ATTR_STR(cont) do { D(("attr_str " #cont "\t" )); yyextra->attr_str = &(cont); yy_push_state(GET_ATTR, yyscanner); } while(0)
+#define ATTR_DECODER(cont) do { D(("attr_decoder " #cont "\t" )); yyextra->attr_uint = &(cont); yy_push_state(GET_DECODER_ATTR, yyscanner); } while(0)
+#define WIMAXASNCP_IGNORE() do { D(("ignore: %s\t",yytext)); yy_push_state(IGNORE_ATTR, yyscanner); } while(0)
#define D(args) wimaxasncp_dict_debug args
#define MAX_INCLUDE_DEPTH 10
-#define YY_INPUT(buf,result,max_size) { result = current_yyinput(buf,max_size); }
+#define YY_INPUT(buf,result,max_size) { result = yyextra->current_yyinput(buf,max_size,yyscanner); }
+#define YY_USER_INIT { \
+ WimaxasncpDict_scanner_state_t *scanner_state = WimaxasncpDict_get_extra(yyscanner); \
+ BEGIN(scanner_state->start_state); \
+}
#define ECHO
-#define APPEND(txt,len) append_to_buffer(txt,(int)len)
-
-static entity_t ents;
-static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
-static int include_stack_ptr = 0;
-static size_t (*current_yyinput)(gchar*,size_t);
-static const gchar *sys_dir;
-static wimaxasncp_dict_t *dict;
-static wimaxasncp_dict_tlv_t *tlv;
-static wimaxasncp_dict_enum_t *enumitem;
-static wimaxasncp_dict_xmlpi_t *xmlpi;
-
-static wimaxasncp_dict_tlv_t *last_tlv;
-static wimaxasncp_dict_enum_t *last_enumitem;
-static wimaxasncp_dict_xmlpi_t *last_xmlpi;
-
-static gchar **attr_str;
-static guint *attr_uint;
-static gint16 *attr_uint16;
+#define APPEND(txt,len) append_to_buffer(txt,(int)len,yyextra)
+
+typedef struct {
+ GString *dict_error;
+
+ const gchar *sys_dir;
+
+ gchar *strbuf;
+ guint size_strbuf;
+ guint len_strbuf;
+
+ gchar *write_ptr;
+ gchar *read_ptr;
+
+ wimaxasncp_dict_t *dict;
+ wimaxasncp_dict_tlv_t *tlv;
+ wimaxasncp_dict_enum_t *enumitem;
+ wimaxasncp_dict_xmlpi_t *xmlpi;
+
+ wimaxasncp_dict_tlv_t *last_tlv;
+ wimaxasncp_dict_enum_t *last_enumitem;
+ wimaxasncp_dict_xmlpi_t *last_xmlpi;
+
+ entity_t *ents;
+
+ YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+ int include_stack_ptr;
+ size_t (*current_yyinput)(gchar*,size_t,yyscan_t);
+
+ gchar **attr_str;
+ guint *attr_uint;
+ gint16 *attr_uint16;
+
+ int start_state;
+} WimaxasncpDict_scanner_state_t;
static guint wimaxasncp_bits(guint bits, char *n);
static gint wimaxasncp_decode_type(const gchar *name);
static void wimaxasncp_dict_debug(const gchar *fmt, ...) G_GNUC_PRINTF(1, 2);
-static void append_to_buffer(const gchar *txt, int len);
+static void append_to_buffer(const gchar *txt, int len, WimaxasncpDict_scanner_state_t *state);
static FILE *wimaxasncp_dict_open(const gchar*, const gchar*);
-static GString *dict_error = NULL;
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
+
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define WimaxasncpDict_alloc(size, yyscanner) (void *)malloc(size)
+#define WimaxasncpDict_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define WimaxasncpDict_free(ptr, yyscanner) free((char *)ptr)
%}
@@ -197,23 +249,23 @@ since_attr since=\042
<LOADING>{xmlpi_start} BEGIN LOADING_XMLPI;
<LOADING_XMLPI>{whitespace} ;
<LOADING_XMLPI>{entityname} {
- xmlpi = g_new(wimaxasncp_dict_xmlpi_t,1);
- xmlpi->name = g_strdup(yytext);
- xmlpi->key = NULL;
- xmlpi->value = NULL;
- xmlpi->next = NULL;
+ yyextra->xmlpi = g_new(wimaxasncp_dict_xmlpi_t,1);
+ yyextra->xmlpi->name = g_strdup(yytext);
+ yyextra->xmlpi->key = NULL;
+ yyextra->xmlpi->value = NULL;
+ yyextra->xmlpi->next = NULL;
- if (!dict->xmlpis) last_xmlpi = dict->xmlpis = xmlpi;
- else last_xmlpi = last_xmlpi->next = xmlpi;
+ if (!yyextra->dict->xmlpis) yyextra->last_xmlpi = yyextra->dict->xmlpis = yyextra->xmlpi;
+ else yyextra->last_xmlpi = yyextra->last_xmlpi->next = yyextra->xmlpi;
BEGIN XMLPI_ATTRS;
}
<XMLPI_ATTRS>{xmlpi_key_attr} BEGIN XMLPI_GETKEY;
-<XMLPI_GETKEY>{ndquot} { xmlpi->key = g_strdup(yytext); BEGIN XMLPI_ATTRS; }
+<XMLPI_GETKEY>{ndquot} { yyextra->xmlpi->key = g_strdup(yytext); BEGIN XMLPI_ATTRS; }
<XMLPI_ATTRS>{xmlpi_value_attr} BEGIN XMLPI_GETVAL;
-<XMLPI_GETVAL>{ndquot} { xmlpi->value = g_strdup(yytext); BEGIN XMLPI_ATTRS; }
+<XMLPI_GETVAL>{ndquot} { yyextra->xmlpi->value = g_strdup(yytext); BEGIN XMLPI_ATTRS; }
<XMLPI_ATTRS>.
<XMLPI_ATTRS>{xmlpi_end} BEGIN LOADING;
@@ -224,14 +276,14 @@ since_attr since=\042
entity_t *e = g_new(entity_t,1);
D(("ENTITY: %s\n",yytext));
e->name = g_strdup(yytext);
- e->next = ents.next;
- ents.next = e;
+ e->next = yyextra->ents;
+ yyextra->ents = e;
BEGIN GET_SYSTEM;
};
<GET_SYSTEM>{system} BEGIN GET_FILE;
<GET_FILE>{ndquot} {
D(("GET_FILE: %s\n",yytext));
- ents.next->file = g_strdup(yytext);
+ yyextra->ents->file = g_strdup(yytext);
BEGIN END_ENTITY;
}
<END_ENTITY>{end_entity} BEGIN LOADING;
@@ -262,23 +314,23 @@ since_attr since=\042
D(("looking for entity: %s\n",yytext));
- if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
- dict_error = g_string_append(
- dict_error, "included files nested too deeply\n");
+ if ( yyextra->include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
+ yyextra->dict_error = g_string_append(
+ yyextra->dict_error, "included files nested too deeply\n");
yyterminate();
}
- include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
+ yyextra->include_stack[yyextra->include_stack_ptr++] = YY_CURRENT_BUFFER;
- for (e = ents.next; e; e = e->next) {
+ for (e = yyextra->ents; e; e = e->next) {
if (strcmp(e->name,yytext) == 0) {
- yyin = wimaxasncp_dict_open(sys_dir,e->file);
+ yyin = wimaxasncp_dict_open(yyextra->sys_dir,e->file);
D(("entity: %s filename: %s yyin: %p\n",e->name,e->file,(void*)yyin));
if (!yyin) {
yyterminate();
} else {
- yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
+ WimaxasncpDict__switch_to_buffer(WimaxasncpDict__create_buffer(yyin, YY_BUF_SIZE, yyscanner), yyscanner);
}
break;
}
@@ -287,7 +339,7 @@ since_attr since=\042
if (!e) {
temp_str = g_strdup_printf(
"cannot find entity: '%s'\n", yytext);
- dict_error = g_string_append(dict_error, temp_str);
+ yyextra->dict_error = g_string_append(yyextra->dict_error, temp_str);
g_free(temp_str);
yyterminate();
}
@@ -298,75 +350,75 @@ since_attr since=\042
if (!yyin) yyterminate();
fclose(yyin);
- D(("closing: %p %i\n",(void*)yyin,include_stack_ptr));
+ D(("closing: %p %i\n",(void*)yyin,yyextra->include_stack_ptr));
- if ( --include_stack_ptr < 0 ) {
+ if ( --yyextra->include_stack_ptr < 0 ) {
D(("DONE READING\n"));
yyin = NULL;
yyterminate();
} else {
- yy_delete_buffer( YY_CURRENT_BUFFER );
- yy_switch_to_buffer(include_stack[include_stack_ptr]);
+ WimaxasncpDict__delete_buffer(YY_CURRENT_BUFFER, yyscanner);
+ WimaxasncpDict__switch_to_buffer(yyextra->include_stack[yyextra->include_stack_ptr], yyscanner);
BEGIN LOADING;
}
}
<GET_ATTR>{ndquot} {
- *attr_str = g_strdup(yytext);
+ *yyextra->attr_str = g_strdup(yytext);
D(("%s\n",yytext));
- attr_str = NULL;
+ yyextra->attr_str = NULL;
BEGIN END_ATTR;
}
<GET_UINT_ATTR>{number} {
- *attr_uint = (guint)strtoul(yytext,NULL,0);
+ *yyextra->attr_uint = (guint)strtoul(yytext,NULL,0);
D(("%s\n",yytext););
- attr_uint = NULL;
+ yyextra->attr_uint = NULL;
BEGIN END_ATTR;
}
<GET_UINT16_ATTR>{number} {
- *attr_uint16 = (gint16) strtol(yytext,NULL,0);
+ *yyextra->attr_uint16 = (gint16) strtol(yytext,NULL,0);
D(("%s\n",yytext););
- attr_uint16 = NULL;
+ yyextra->attr_uint16 = NULL;
BEGIN END_ATTR;
}
<GET_UINT_ATTR>"WIMAXASNCP_BIT32"[ \t]*"(" { BEGIN BIT32; }
<BIT32>[0-9]+ {
- *attr_uint = wimaxasncp_bits(32, yytext);
+ *yyextra->attr_uint = wimaxasncp_bits(32, yytext);
D(("WIMAXASNCP_BIT32(%s)\n",yytext););
- attr_uint = NULL;
+ yyextra->attr_uint = NULL;
}
<GET_UINT_ATTR>"WIMAXASNCP_BIT16"[ \t]*"(" { BEGIN BIT16; }
<BIT16>[0-9]+ {
- *attr_uint = wimaxasncp_bits(16, yytext);
+ *yyextra->attr_uint = wimaxasncp_bits(16, yytext);
D(("WIMAXASNCP_BIT16(%s)\n",yytext););
- attr_uint = NULL;
+ yyextra->attr_uint = NULL;
}
<GET_UINT_ATTR>"WIMAXASNCP_BIT8"[ \t]*"(" { BEGIN BIT8; }
<BIT8>[0-9]+ {
- *attr_uint = wimaxasncp_bits(8, yytext);
+ *yyextra->attr_uint = wimaxasncp_bits(8, yytext);
D(("WIMAXASNCP_BIT8(%s)\n",yytext););
- attr_uint = NULL;
+ yyextra->attr_uint = NULL;
}
<BIT32,BIT16,BIT8>[ \t]*")" { BEGIN END_ATTR; }
<GET_DECODER_ATTR>{ndquot} {
- *attr_uint = wimaxasncp_decode_type(yytext);
+ *yyextra->attr_uint = wimaxasncp_decode_type(yytext);
D(("%s\n",yytext));
- attr_uint = NULL;
+ yyextra->attr_uint = NULL;
BEGIN END_ATTR;
}
-<END_ATTR>{dquot} { yy_pop_state(); }
+<END_ATTR>{dquot} { yy_pop_state(yyscanner); }
<IGNORE_ATTR>. {
/* XXX: should go?*/
@@ -375,7 +427,7 @@ since_attr since=\042
<IGNORE_ATTR>{ignored_quoted} {
D(("=>%s<=\n",yytext));
- yy_pop_state();
+ yy_pop_state(yyscanner);
}
<OUTSIDE>{dictionary_start} {
@@ -387,39 +439,41 @@ since_attr since=\042
<IN_DICT>{tlv_start} {
D(("tlv_start\n"));
- tlv = g_new(wimaxasncp_dict_tlv_t,1);
- tlv->type = 0;
- tlv->name = NULL;
- tlv->description = NULL;
- tlv->decoder = 0;
- tlv->since = 0;
- tlv->hf_root = -1;
- tlv->hf_value = -1;
- tlv->hf_ipv4 = -1;
- tlv->hf_ipv6 = -1;
- tlv->hf_bsid = -1;
- tlv->hf_protocol = -1;
- tlv->hf_port_low = -1;
- tlv->hf_port_high = -1;
- tlv->hf_ipv4_mask = -1;
- tlv->hf_ipv6_mask = -1;
- tlv->hf_vendor_id = -1;
- tlv->hf_vendor_rest_of_info = -1;
- tlv->enum_vs = NULL;
- tlv->enums = NULL;
- tlv->next = NULL;
-
- if (! dict->tlvs ) last_tlv = dict->tlvs = tlv;
- else last_tlv = last_tlv->next = tlv;
+ yyextra->tlv = g_new(wimaxasncp_dict_tlv_t,1);
+ yyextra->tlv->type = 0;
+ yyextra->tlv->name = NULL;
+ yyextra->tlv->description = NULL;
+ yyextra->tlv->decoder = 0;
+ yyextra->tlv->since = 0;
+ yyextra->tlv->hf_root = -1;
+ yyextra->tlv->hf_value = -1;
+ yyextra->tlv->hf_ipv4 = -1;
+ yyextra->tlv->hf_ipv6 = -1;
+ yyextra->tlv->hf_bsid = -1;
+ yyextra->tlv->hf_protocol = -1;
+ yyextra->tlv->hf_port_low = -1;
+ yyextra->tlv->hf_port_high = -1;
+ yyextra->tlv->hf_ipv4_mask = -1;
+ yyextra->tlv->hf_ipv6_mask = -1;
+ yyextra->tlv->hf_vendor_id = -1;
+ yyextra->tlv->hf_vendor_rest_of_info = -1;
+ yyextra->tlv->enum_vs = NULL;
+ yyextra->tlv->enums = NULL;
+ yyextra->tlv->next = NULL;
+
+ if (! yyextra->dict->tlvs )
+ yyextra->last_tlv = yyextra->dict->tlvs = yyextra->tlv;
+ else
+ yyextra->last_tlv = yyextra->last_tlv->next = yyextra->tlv;
BEGIN TLV_ATTRS;
}
-<TLV_ATTRS>{name_attr} { ATTR_STR(tlv->name); }
-<TLV_ATTRS>{description_attr} { ATTR_STR(tlv->description); }
-<TLV_ATTRS>{type_attr} { ATTR_UINT16(tlv->type); }
-<TLV_ATTRS>{decoder_attr} { ATTR_DECODER(tlv->decoder); }
-<TLV_ATTRS>{since_attr} { ATTR_UINT(tlv->since); }
+<TLV_ATTRS>{name_attr} { ATTR_STR(yyextra->tlv->name); }
+<TLV_ATTRS>{description_attr} { ATTR_STR(yyextra->tlv->description); }
+<TLV_ATTRS>{type_attr} { ATTR_UINT16(yyextra->tlv->type); }
+<TLV_ATTRS>{decoder_attr} { ATTR_DECODER(yyextra->tlv->decoder); }
+<TLV_ATTRS>{since_attr} { ATTR_UINT(yyextra->tlv->since); }
<TLV_ATTRS>{stop} { BEGIN IN_TLV; }
<TLV_ATTRS>{stop_end} { BEGIN IN_DICT; }
@@ -427,20 +481,22 @@ since_attr since=\042
<IN_TLV>{enum_start} {
D(("enum_start\n"));
- enumitem = g_new(wimaxasncp_dict_enum_t,1);
- enumitem->name = NULL;
- enumitem->code = 0;
- enumitem->next = NULL;
+ yyextra->enumitem = g_new(wimaxasncp_dict_enum_t,1);
+ yyextra->enumitem->name = NULL;
+ yyextra->enumitem->code = 0;
+ yyextra->enumitem->next = NULL;
- if (!tlv->enums) last_enumitem = tlv->enums = enumitem;
- else last_enumitem = last_enumitem->next = enumitem;
+ if (!yyextra->tlv->enums)
+ yyextra->last_enumitem = yyextra->tlv->enums = yyextra->enumitem;
+ else
+ yyextra->last_enumitem = yyextra->last_enumitem->next = yyextra->enumitem;
BEGIN ENUM_ATTRS;
}
-<ENUM_ATTRS>{name_attr} { ATTR_STR(enumitem->name); }
-<ENUM_ATTRS>{code_attr} { ATTR_UINT(enumitem->code); }
+<ENUM_ATTRS>{name_attr} { ATTR_STR(yyextra->enumitem->name); }
+<ENUM_ATTRS>{code_attr} { ATTR_UINT(yyextra->enumitem->code); }
<ENUM_ATTRS>{stop} { BEGIN IN_TLV; }
<ENUM_ATTRS>{stop_end} { BEGIN IN_TLV; }
@@ -526,38 +582,32 @@ static gint wimaxasncp_decode_type(const gchar *name)
return WIMAXASNCP_TLV_TBD;
}
-static gchar *strbuf = NULL;
-static gchar *write_ptr = NULL;
-static gchar *read_ptr = NULL;
-
-static guint size_strbuf = 8192;
-static guint len_strbuf = 0;
-
-extern void wimaxasncp_dict_unused(void);
-void wimaxasncp_dict_unused(void) {
- yy_top_state();
+extern void wimaxasncp_dict_unused(yyscan_t yyscanner);
+void wimaxasncp_dict_unused(yyscan_t yyscanner) {
+ yy_top_state(yyscanner);
}
-static void append_to_buffer(const gchar *txt, int len) {
+static void append_to_buffer(const gchar *txt, int len, WimaxasncpDict_scanner_state_t *state) {
- if (strbuf == NULL) {
- read_ptr = write_ptr = strbuf = (gchar *)g_malloc(size_strbuf);
+ if (state->strbuf == NULL) {
+ state->read_ptr = state->write_ptr = state->strbuf = (gchar *)g_malloc(state->size_strbuf);
}
- if ( (len_strbuf + len + 1) >= size_strbuf ) {
- read_ptr = strbuf = (gchar *)g_realloc(strbuf,size_strbuf *= 2);
+ if ( (state->len_strbuf + len + 1) >= state->size_strbuf ) {
+ state->read_ptr = state->strbuf = (gchar *)g_realloc(state->strbuf,state->size_strbuf *= 2);
}
- write_ptr = strbuf + len_strbuf;
- strncpy(write_ptr,txt,len);
- len_strbuf += len;
- strbuf[len_strbuf] = '\0';
+ state->write_ptr = state->strbuf + state->len_strbuf;
+ strncpy(state->write_ptr,txt,len);
+ state->len_strbuf += len;
+ state->strbuf[state->len_strbuf] = '\0';
}
-static size_t file_input(gchar *buf, size_t max) {
+static size_t file_input(gchar *buf, size_t max, yyscan_t scanner) {
+ FILE *in = yyget_in(scanner);
size_t read_cnt;
- read_cnt = fread(buf,1,max,yyin);
+ read_cnt = fread(buf,1,max,in);
if ( read_cnt == max ) {
return max;
@@ -569,15 +619,17 @@ static size_t file_input(gchar *buf, size_t max) {
}
-static size_t string_input(gchar *buf, size_t max) {
- if (read_ptr >= write_ptr ) {
+static size_t string_input(gchar *buf, size_t max, yyscan_t scanner) {
+ WimaxasncpDict_scanner_state_t *statep = yyget_extra(scanner);
+
+ if (statep->read_ptr >= statep->write_ptr ) {
return YY_NULL;
- } else if ( read_ptr + max > write_ptr ) {
- max = write_ptr - read_ptr;
+ } else if ( statep->read_ptr + max > statep->write_ptr ) {
+ max = statep->write_ptr - statep->read_ptr;
}
- memcpy(buf,read_ptr,max);
- read_ptr += max;
+ memcpy(buf,statep->read_ptr,max);
+ statep->read_ptr += max;
return max;
}
@@ -612,54 +664,106 @@ wimaxasncp_dict_t *wimaxasncp_dict_scan(
const gchar *system_directory, const gchar *filename, int dbg,
gchar **error) {
+ WimaxasncpDict_scanner_state_t state;
+ FILE *in;
+ yyscan_t scanner;
entity_t *e;
- dict_error = g_string_new("");
-
debugging = dbg;
- sys_dir = system_directory;
+ state.dict_error = g_string_new("");
- write_ptr = NULL;
- read_ptr = NULL;
+ state.sys_dir = system_directory;
- if (dict)
- {
- wimaxasncp_dict_free(dict);
- }
+ state.dict = g_new(wimaxasncp_dict_t,1);
+ state.dict->tlvs = NULL;
+ state.dict->xmlpis = NULL;
- dict = g_new(wimaxasncp_dict_t,1);
- dict->tlvs = NULL;
- dict->xmlpis = NULL;
+ state.strbuf = NULL;
+ state.size_strbuf = 8192;
+ state.len_strbuf = 0;
- tlv = NULL;
- enumitem = NULL;
- xmlpi = NULL;
+ state.write_ptr = NULL;
+ state.read_ptr = NULL;
- last_tlv = NULL;
- last_enumitem = NULL;
- last_xmlpi = NULL;
+ state.tlv = NULL;
+ state.enumitem = NULL;
+ state.xmlpi = NULL;
- ents.next = NULL;
+ state.last_tlv = NULL;
+ state.last_enumitem = NULL;
+ state.last_xmlpi = NULL;
- yyin = wimaxasncp_dict_open(sys_dir,filename);
+ state.ents = NULL;
- if (yyin)
- {
- current_yyinput = file_input;
- BEGIN LOADING;
- yylex();
+ /*
+ * Pass 1.
+ *
+ * Reads the file, does some work, and stores a modified version
+ * of the file contents in memory.
+ */
+ state.current_yyinput = file_input;
+ state.include_stack_ptr = 0;
+
+ in = wimaxasncp_dict_open(system_directory,filename);
+
+ if (in == NULL) {
+ /*
+ * Couldn't open the dictionary.
+ *
+ * Treat all failures other then ENOENT as errors?
+ */
+ *error = NULL;
+ return state.dict;
+ }
+
+ if (WimaxasncpDict_lex_init(&scanner) != 0) {
+ D(("Can't initialize scanner: %s\n", strerror(errno)));
+ fclose(in);
+ g_free(state.dict);
+ return NULL;
+ }
+
+ WimaxasncpDict_set_in(in, scanner);
- D(("\n---------------\n%s\n------- %d -------\n",
- strbuf, len_strbuf));
+ /* Associate the state with the scanner */
+ WimaxasncpDict_set_extra(&state, scanner);
- current_yyinput = string_input;
+ state.start_state = LOADING;
+ WimaxasncpDict_lex(scanner);
- BEGIN OUTSIDE;
- yylex();
+ WimaxasncpDict_lex_destroy(scanner);
+ fclose(in);
+
+ D(("\n---------------\n%s\n------- %d -------\n",
+ state.strbuf, state.len_strbuf));
+
+ /*
+ * Pass 2.
+ *
+ * Reads the modified version of the file contents and does the
+ * rest of the work.
+ */
+ state.current_yyinput = string_input;
+
+ if (WimaxasncpDict_lex_init(&scanner) != 0) {
+ D(("Can't initialize scanner: %s\n", strerror(errno)));
+ fclose(in);
+ g_free(state.dict);
+ g_free(state.strbuf);
+ return NULL;
}
- e = ents.next;
+ /* Associate the state with the scanner */
+ WimaxasncpDict_set_extra(&state, scanner);
+
+ state.start_state = OUTSIDE;
+ WimaxasncpDict_lex(scanner);
+
+ WimaxasncpDict_lex_destroy(scanner);
+ g_free(state.strbuf);
+
+ e = state.ents;
while (e)
{
entity_t *next = e->next;
@@ -669,21 +773,16 @@ wimaxasncp_dict_t *wimaxasncp_dict_scan(
e = next;
}
- g_free(strbuf);
- strbuf = NULL;
- size_strbuf = 8192;
-
- if (dict_error->len > 0)
+ if (state.dict_error->len > 0)
{
- *error = g_string_free(dict_error, FALSE);
+ *error = g_string_free(state.dict_error, FALSE);
}
else
{
*error = NULL;
- g_string_free(dict_error, TRUE);
+ g_string_free(state.dict_error, TRUE);
}
-
- return dict;
+ return state.dict;
}
void wimaxasncp_dict_free(wimaxasncp_dict_t *d) {
diff --git a/tools/runlex.sh b/tools/runlex.sh
index 0592acb318..e78c8b0ed5 100755
--- a/tools/runlex.sh
+++ b/tools/runlex.sh
@@ -2,10 +2,9 @@
#
# runlex.sh
-# Script to run Lex/Flex.
+# Script to run Flex.
# First argument is the (quoted) name of the command; if it's null, that
-# means that neither Flex nor Lex was found, so we report an error and
-# quit.
+# means that Flex wasn't found, so we report an error and quit.
# Second arg is the sed executable
#
# Wireshark - Network traffic analyzer
@@ -30,9 +29,9 @@
#
# Get the name of the command to run, and then shift to get the arguments.
#
-if [ $# -eq 0 ]
+if [ $# -lt 2 ]
then
- echo "Usage: runlex <lex/flex command to run> [ arguments ]" 1>&2
+ echo "Usage: runlex <Flex command to run> <path to sed> [ arguments ]" 1>&2
exit 1
fi
@@ -51,18 +50,18 @@ esac
shift
#
-# Check whether we have it.
+# Check whether we have Flex.
#
if [ -z "${LEX}" ]
then
- echo "Neither lex nor flex was found" 1>&2
+ echo "Flex was not found" 1>&2
exit 1
fi
SED="$1"
shift
#
-# Check whether we have it.
+# Check whether we have sed.
#
if [ -z "${SED}" ]
then
@@ -72,7 +71,7 @@ fi
#
# Process the flags. We don't use getopt because we don't want to
-# embed complete knowledge of what options are supported by Lex/Flex.
+# embed complete knowledge of what options are supported by Flex.
#
flags=""
outfile=lex.yy.c
@@ -105,20 +104,27 @@ do
done
#
-# OK, run it.
+# Construct the name of the header file to generate; if the .c file is
+# .../foo.c, the header file will be .../foo_lex.h.
#
-#echo "Running ${LEX} -o$outfile $flags $@"
-${LEX} -o"$outfile" $flags "$@"
+#echo "Getting header file name"
+header_file=`dirname "$outfile"`/`basename "$outfile" .c`_lex.h
+
+#
+# OK, run Flex.
+#
+#echo "Running ${LEX} -o\"$outfile\" --header-file=\"$header_file\" $flags \"$@\""
+${LEX} -o"$outfile" --header-file="$header_file" $flags "$@"
#
# Did it succeed?
#
-if [ $? -ne 0 ]
+exitstatus=$?
+if [ $exitstatus -ne 0 ]
then
#
# No. Exit with the failing exit status.
#
- exitstatus=$?
echo "${LEX} failed: exit status $exitstatus"
exit $exitstatus
fi
@@ -129,6 +135,9 @@ fi
# This gets in the way of building in a directory different from the
# source directory. Try to work around this.
#
+# XXX - where is this an issue?
+#
+#
# Is the outfile where we think it is?
#
outfile_base=`basename "$outfile"`
@@ -138,6 +147,7 @@ then
# No, it's not, but it is in the current directory. Put it
# where it's supposed to be.
#
+echo "Moving $outfile_base to $outfile"
mv "$outfile_base" "$outfile"
if [ $? -ne 0 ]
then
@@ -145,47 +155,22 @@ then
fi
fi
-echo "Wrote `basename $outfile`"
-
-#
-# OK, now let's generate a header file declaring the relevant functions
-# defined by the .c file; if the .c file is .../foo.c, the header file
-# will be .../foo_lex.h.
#
-# This works around some other Flex suckage, wherein it doesn't declare
-# the lex routine before defining it, causing compiler warnings.
-# XXX - newer versions of Flex support --header-file=, to generate the
-# appropriate header file. With those versions, we should use that option.
-#
-
+# Is the header file where we think it is?
#
-# Get the name of the prefix; scan the source files for a %option prefix
-# line. We use the last one.
-#
-#echo "Getting prefix"
-prefix=`${SED} -n 's/%option[ ][ ]*prefix="\(.*\)".*/\1/p' "$@" | tail -1`
-if [ ! -z "$prefix" ]
+header_file_base=`basename "$header_file"`
+if [ "$header_file_base" != "$header_file" -a \( ! -r "$header_file" \) -a -r "$header_file_base" ]
then
- prefixline="#define yylex ${prefix}lex"
+ #
+ # No, it's not, but it is in the current directory. Put it
+ # where it's supposed to be.
+ #
+echo "Moving $header_file_base to $header_file"
+ mv "$header_file_base" "$header_file"
+ if [ $? -ne 0 ]
+ then
+ echo $?
+ fi
fi
-#
-# Construct the name of the header file.
-#
-#echo "Getting header file name"
-header_file=`dirname "$outfile"`/`basename "$outfile" .c`_lex.h
-
-#
-# Spew out the declaration.
-#
-#echo "Writing $header_file"
-cat <<EOF >$header_file
-/* This is generated by runlex.sh. Do not edit it. */
-$prefixline
-#ifndef YY_DECL
-#define YY_DECL int yylex(void)
-#endif
-YY_DECL;
-EOF
-
-echo "Wrote `basename $header_file`"
+echo "Wrote $outfile and $header_file"
diff --git a/ui/Makefile.am b/ui/Makefile.am
index 61446b5cd7..a1185688bf 100644
--- a/ui/Makefile.am
+++ b/ui/Makefile.am
@@ -28,6 +28,8 @@ AM_CPPFLAGS = $(INCLUDEDIRS) $(WS_CPPFLAGS) -DDOC_DIR=\"$(docdir)\" \
noinst_LIBRARIES = libui.a libui_dirty.a
+BUILT_SOURCES = $(GENERATED_HEADER_FILES)
+
CLEANFILES = \
doxygen-ui.tag \
libui.a \
diff --git a/ui/gtk/file_import_dlg.c b/ui/gtk/file_import_dlg.c
index 83a16fb893..e901b7bd07 100644
--- a/ui/gtk/file_import_dlg.c
+++ b/ui/gtk/file_import_dlg.c
@@ -517,7 +517,12 @@ file_import_open(text_import_info_t *info)
goto end;
}
- text_import(info);
+ err = text_import(info);
+ if (err != 0) {
+ failure_alert_box("Can't initialize scanner: %s", g_strerror(err));
+ fclose(info->import_text_file);
+ goto end;
+ }
if (fclose(info->import_text_file)) {
read_failure_alert_box(info->import_text_filename, errno);
diff --git a/ui/qt/import_text_dialog.cpp b/ui/qt/import_text_dialog.cpp
index 02479472ca..11b0218fb8 100644
--- a/ui/qt/import_text_dialog.cpp
+++ b/ui/qt/import_text_dialog.cpp
@@ -140,7 +140,13 @@ void ImportTextDialog::convertTextFile() {
return;
}
- text_import(&import_info_);
+ err = text_import(&import_info_);
+ if (err != 0) {
+ failure_alert_box("Can't initialize scanner: %s", g_strerror(err));
+ fclose(import_info_.import_text_file);
+ setResult(QDialog::Rejected);
+ return;
+ }
if (fclose(import_info_.import_text_file))
{
diff --git a/ui/text_import.c b/ui/text_import.c
index 9928ddbc1f..45fddbdde2 100644
--- a/ui/text_import.c
+++ b/ui/text_import.c
@@ -126,6 +126,7 @@
#include "text_import.h"
#include "text_import_scanner.h"
+#include "text_import_scanner_lex.h"
/*--- Options --------------------------------------------------------------------*/
@@ -902,9 +903,12 @@ parse_token (token_t token, char *str)
/*----------------------------------------------------------------------
* Import a text file.
*/
-void
+int
text_import(text_import_info_t *info)
{
+ yyscan_t scanner;
+ int ret;
+
packet_buf = (guint8 *)g_malloc(sizeof(HDR_ETHERNET) + sizeof(HDR_IP) +
sizeof(HDR_SCTP) + sizeof(HDR_DATA_CHUNK) +
IMPORT_MAX_PACKET);
@@ -1014,11 +1018,21 @@ text_import(text_import_info_t *info)
max_offset = info->max_frame_length;
- text_importin = info->import_text_file;
+ if (text_import_lex_init(&scanner) != 0) {
+ ret = errno;
+ g_free(packet_buf);
+ return ret;
+ }
+
+ text_import_set_in(info->import_text_file, scanner);
- text_importlex();
+ text_import_lex(scanner);
+
+ text_import_lex_destroy(scanner);
g_free(packet_buf);
+
+ return 0;
}
/*
diff --git a/ui/text_import.h b/ui/text_import.h
index e430205fda..f6612d61dc 100644
--- a/ui/text_import.h
+++ b/ui/text_import.h
@@ -86,7 +86,7 @@ typedef struct
guint max_frame_length;
} text_import_info_t;
-void text_import(text_import_info_t *info);
+int text_import(text_import_info_t *info);
#ifdef __cplusplus
}
diff --git a/ui/text_import_scanner.l b/ui/text_import_scanner.l
index 9af93643e4..740a38ea22 100644
--- a/ui/text_import_scanner.l
+++ b/ui/text_import_scanner.l
@@ -1,9 +1,19 @@
/* -*-mode: flex-*- */
/*
+ * 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 noinput
+%option nounput
/*
* We don't read interactively from the terminal.
@@ -16,10 +26,23 @@
%option noyywrap
/*
- * Prefix scanner routines with "text_import" rather than "yy", so this scanner
+ * Prefix scanner routines with "text_import_" rather than "yy", so this scanner
* can coexist with other scanners.
*/
-%option prefix="text_import"
+%option prefix="text_import_"
+
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
%{
@@ -57,7 +80,6 @@
#include <stdlib.h>
#include "text_import_scanner.h"
-#include "text_import_scanner_lex.h"
/*
* Flex (v 2.5.35) uses this symbol to "exclude" unistd.h
@@ -70,6 +92,18 @@
# pragma warning (disable:4018)
#endif
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
+
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define text_import_alloc(size, yyscanner) (void *)malloc(size)
+#define text_import_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define text_import_free(ptr, yyscanner) free((char *)ptr)
+
%}
hexdigit [0-9A-Fa-f]
diff --git a/wiretap/Makefile.am b/wiretap/Makefile.am
index e30efcfbbe..597e77d27b 100644
--- a/wiretap/Makefile.am
+++ b/wiretap/Makefile.am
@@ -53,6 +53,8 @@ libwiretap_generated_la_SOURCES = \
libwiretap_generated_la_CFLAGS = $(GENERATED_CFLAGS)
+BUILT_SOURCES = $(GENERATED_HEADER_FILES)
+
EXTRA_DIST = \
.editorconfig \
README.airmagnet \
@@ -71,11 +73,9 @@ k12text_lex.h : k12text.c
ascend_scanner_lex.h : ascend_scanner.c
-ascend_scanner.c: ascend.h
-
ascend.h: ascend.c
-ascend.c: ascend.y
+ascend.c: $(srcdir)/ascend.y ascend_scanner_lex.h
@if [ -z "$(YACC)" ]; then \
echo "Neither bison nor byacc has been found"; \
exit 1; \
diff --git a/wiretap/ascend-int.h b/wiretap/ascend-int.h
index 049bf8599d..0d8e70b6d6 100644
--- a/wiretap/ascend-int.h
+++ b/wiretap/ascend-int.h
@@ -27,31 +27,34 @@
#include <glib.h>
#include "ws_symbol_export.h"
-extern const gchar *ascend_parse_error;
-
-/*
- * Pointer to the pseudo-header for the current packet.
- */
-extern struct ascend_phdr *pseudo_header;
-
typedef struct {
time_t inittime;
gboolean adjusted;
gint64 next_packet_seek_start;
} ascend_t;
-/* Here we provide interfaces to make our scanner act and look like lex */
-int ascendlex(void);
-
-void init_parse_ascend(void);
-void ascend_init_lexer(FILE_T fh);
-gboolean check_ascend(FILE_T fh, struct wtap_pkthdr *phdr);
-typedef enum {
- PARSED_RECORD,
- PARSED_NONRECORD,
- PARSE_FAILED
-} parse_t;
-parse_t parse_ascend(ascend_t *ascend, FILE_T fh, struct wtap_pkthdr *phdr,
- Buffer *buf, guint length);
+typedef struct {
+ FILE_T fh;
+ const gchar *ascend_parse_error;
+ int *err;
+ gchar **err_info;
+ struct ascend_phdr *pseudo_header;
+ guint8 *pkt_data;
+
+ gboolean saw_timestamp;
+ guint32 timestamp;
+
+ unsigned int bcur;
+ gint64 first_hexbyte;
+ guint32 wirelen;
+ guint32 caplen;
+ time_t secs;
+ guint32 usecs;
+} ascend_state_t;
+#define YY_EXTRA_TYPE ascend_state_t *
+
+extern int
+run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd,
+ ascend_state_t *parser_state, int *err, gchar **err_info);
#endif /* ! __ASCEND_INT_H__ */
diff --git a/wiretap/ascend.y b/wiretap/ascend.y
index dc30a9e78f..31f9cbc88e 100644
--- a/wiretap/ascend.y
+++ b/wiretap/ascend.y
@@ -1,3 +1,28 @@
+/*
+ * 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.
+ *
+ * We use void * rather than yyscan_t because, at least with some
+ * versions of Flex and Bison, if you use yyscan_t in %parse-param and
+ * %lex-param, you have to include the ascend_lex_scanner.h before
+ * ascend.h to get yyscan_t declared, and you have to include ascend.h
+ * before ascend_lex_scanner.h to get YYSTYPE declared. Using void *
+ * breaks the cycle; the Flex documentation says yyscan_t is just a void *.
+ */
+%parse-param {void *yyscanner}
+%lex-param {void *yyscanner}
+
+/*
+ * And we need to pass the parser state to the scanner.
+ */
+%parse-param {ascend_state_t *parser_state}
+
%{
/* ascend.y
*
@@ -135,22 +160,13 @@ XMIT-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.51) 20 octet
#include <wsutil/buffer.h>
#include "ascendtext.h"
#include "ascend-int.h"
+#include "ascend.h"
+#include "ascend_scanner_lex.h"
#include "file_wrappers.h"
#define NO_USER "<none>"
-int yyparse(FILE_T fh);
-void yyerror(FILE_T fh _U_, const char *);
-
-const gchar *ascend_parse_error;
-
-static unsigned int bcur;
-static guint32 start_time, usecs, caplen, wirelen;
-static time_t secs;
-struct ascend_phdr *pseudo_header;
-static guint8 *pkt_data;
-static gint64 first_hexbyte;
-
+extern void yyerror (void *yyscanner, ascend_state_t *state, FILE_T fh _U_, const char *s);
%}
%union {
@@ -208,19 +224,19 @@ PRI-XMIT-0/2 (task "l1Task" at 0x80152b20, time: 283529.65) 10 octets @
*/
deferred_isdn_hdr: isdn_prefix decnum SLASH_SUFFIX KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen += $11;
- caplen += $11;
- secs = $9;
- usecs = $10;
- if (pseudo_header != NULL) {
- pseudo_header->type = $1;
- pseudo_header->sess = $2;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $7;
+ parser_state->wirelen += $11;
+ parser_state->caplen += $11;
+ parser_state->secs = $9;
+ parser_state->usecs = $10;
+ if (parser_state->pseudo_header != NULL) {
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $2;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $7;
}
/* because we have two data groups */
- first_hexbyte = 0;
+ parser_state->first_hexbyte = 0;
}
;
@@ -230,18 +246,18 @@ PRI-XMIT-19: (task "l1Task" at 0x10216840, time: 274758.67) 4 octets @ 0x1027c1
PRI-RCV-27: (task "idle task" at 0x10123570, time: 560194.01) 4 octets @ 0x1027fb00
*/
isdn_hdr: isdn_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $10;
- caplen = $10;
- secs = $8;
- usecs = $9;
- if (pseudo_header != NULL) {
- pseudo_header->type = $1;
- pseudo_header->sess = $2;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $6;
+ parser_state->wirelen = $10;
+ parser_state->caplen = $10;
+ parser_state->secs = $8;
+ parser_state->usecs = $9;
+ if (parser_state->pseudo_header != NULL) {
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $2;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $6;
}
- first_hexbyte = 0;
+ parser_state->first_hexbyte = 0;
}
;
@@ -251,15 +267,15 @@ ETHER3ND XMIT: (task "_sarTask" at 0x802c6eb0, time: 259848.11) 414 octets @ 0xa
*/
ether_hdr: ether_prefix string KEYWORD string KEYWORD hexnum KEYWORD decnum decnum
decnum KEYWORD HEXNUM {
- wirelen = $10;
- caplen = $10;
- secs = $8;
- usecs = $9;
- if (pseudo_header != NULL) {
- pseudo_header->type = $1;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $6;
+ parser_state->wirelen = $10;
+ parser_state->caplen = $10;
+ parser_state->secs = $8;
+ parser_state->usecs = $9;
+ if (parser_state->pseudo_header != NULL) {
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $6;
}
}
;
@@ -267,17 +283,17 @@ ether_hdr: ether_prefix string KEYWORD string KEYWORD hexnum KEYWORD decnum decn
/* RECV-iguana:241:(task: B02614C0, time: 1975432.85) 49 octets @ 8003BD94 */
/* 1 2 3 4 5 6 7 8 9 10 11 */
wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $9;
- caplen = $9;
- secs = $7;
- usecs = $8;
- if (pseudo_header != NULL) {
- /* pseudo_header->user is set in ascend_scanner.l */
- pseudo_header->type = $1;
- pseudo_header->sess = $3;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $5;
+ parser_state->wirelen = $9;
+ parser_state->caplen = $9;
+ parser_state->secs = $7;
+ parser_state->usecs = $8;
+ if (parser_state->pseudo_header != NULL) {
+ /* parser_state->pseudo_header->user is set in ascend_scanner.l */
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $3;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $5;
}
}
;
@@ -285,17 +301,17 @@ wds_hdr: wds_prefix string decnum KEYWORD hexnum KEYWORD decnum decnum decnum KE
/* RECV-Max7:20: (task "_brouterControlTask" at 0xb094ac20, time: 1481.50) 20 octets @ 0x8000d198 */
/* 1 2 3 4 5 6 7 8 9 10 11 12 13 */
wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $11;
- caplen = $11;
- secs = $9;
- usecs = $10;
- if (pseudo_header != NULL) {
- /* pseudo_header->user is set in ascend_scanner.l */
- pseudo_header->type = $1;
- pseudo_header->sess = $3;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $7;
+ parser_state->wirelen = $11;
+ parser_state->caplen = $11;
+ parser_state->secs = $9;
+ parser_state->usecs = $10;
+ if (parser_state->pseudo_header != NULL) {
+ /* parser_state->pseudo_header->user is set in ascend_scanner.l */
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $3;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $7;
}
}
;
@@ -303,17 +319,17 @@ wds8_hdr: wds_prefix string decnum KEYWORD string KEYWORD hexnum KEYWORD decnum
/* RECV-187:(task: B050B480, time: 18042248.03) 100 octets @ 800012C0 */
/* 1 2 3 4 5 6 7 8 9 10 */
wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $8;
- caplen = $8;
- secs = $6;
- usecs = $7;
- if (pseudo_header != NULL) {
- /* pseudo_header->user is set in ascend_scanner.l */
- pseudo_header->type = $1;
- pseudo_header->sess = $2;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $4;
+ parser_state->wirelen = $8;
+ parser_state->caplen = $8;
+ parser_state->secs = $6;
+ parser_state->usecs = $7;
+ if (parser_state->pseudo_header != NULL) {
+ /* parser_state->pseudo_header->user is set in ascend_scanner.l */
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $2;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $4;
}
}
;
@@ -321,17 +337,17 @@ wdp7_hdr: wds_prefix decnum KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD
/* XMIT-44: (task "freedm_task" at 0xe051fd10, time: 6258.66) 29 octets @ 0x606d1f00 */
/* 1 2 3 4 5 6 7 8 9 10 11 12 */
wdp8_hdr: wds_prefix decnum KEYWORD string KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $10;
- caplen = $10;
- secs = $8;
- usecs = $9;
- if (pseudo_header != NULL) {
- /* pseudo_header->user is set in ascend_scanner.l */
- pseudo_header->type = $1;
- pseudo_header->sess = $2;
- pseudo_header->call_num[0] = '\0';
- pseudo_header->chunk = 0;
- pseudo_header->task = $6;
+ parser_state->wirelen = $10;
+ parser_state->caplen = $10;
+ parser_state->secs = $8;
+ parser_state->usecs = $9;
+ if (parser_state->pseudo_header != NULL) {
+ /* parser_state->pseudo_header->user is set in ascend_scanner.l */
+ parser_state->pseudo_header->type = $1;
+ parser_state->pseudo_header->sess = $2;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ parser_state->pseudo_header->chunk = 0;
+ parser_state->pseudo_header->task = $6;
}
}
;
@@ -356,7 +372,8 @@ wdd_date: WDD_DATE decnum decnum decnum KEYWORD decnum decnum decnum KEYWORD str
wddt.tm_year = ($4 > 1970) ? $4 - 1900 : 70;
wddt.tm_isdst = -1;
- start_time = (guint32) mktime(&wddt);
+ parser_state->timestamp = (guint32) mktime(&wddt);
+ parser_state->saw_timestamp = TRUE;
}
;
@@ -366,17 +383,17 @@ WD_DIALOUT_DISP: chunk 2515EE type IP.
*/
/* 1 2 3 4 5 6 7 8 9 10 11*/
wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KEYWORD HEXNUM {
- wirelen = $9;
- caplen = $9;
- secs = $7;
- usecs = $8;
- if (pseudo_header != NULL) {
- /* pseudo_header->call_num is set in ascend_scanner.l */
- pseudo_header->type = ASCEND_PFX_WDD;
- pseudo_header->user[0] = '\0';
- pseudo_header->sess = 0;
- pseudo_header->chunk = $2;
- pseudo_header->task = $5;
+ parser_state->wirelen = $9;
+ parser_state->caplen = $9;
+ parser_state->secs = $7;
+ parser_state->usecs = $8;
+ if (parser_state->pseudo_header != NULL) {
+ /* parser_state->pseudo_header->call_num is set in ascend_scanner.l */
+ parser_state->pseudo_header->type = ASCEND_PFX_WDD;
+ parser_state->pseudo_header->user[0] = '\0';
+ parser_state->pseudo_header->sess = 0;
+ parser_state->pseudo_header->chunk = $2;
+ parser_state->pseudo_header->task = $5;
}
}
;
@@ -384,16 +401,16 @@ wdd_hdr: WDD_CHUNK hexnum KEYWORD KEYWORD hexnum KEYWORD decnum decnum decnum KE
byte: HEXBYTE {
/* remember the position of the data group in the trace, to tip
off ascend_seek() as to where to look for the next header. */
- if (first_hexbyte == 0)
- first_hexbyte = file_tell(fh);
+ if (parser_state->first_hexbyte == 0)
+ parser_state->first_hexbyte = file_tell(fh);
- if (bcur < caplen) {
- pkt_data[bcur] = $1;
- bcur++;
+ if (parser_state->bcur < parser_state->caplen) {
+ parser_state->pkt_data[parser_state->bcur] = $1;
+ parser_state->bcur++;
}
/* arbitrary safety maximum... */
- if (bcur >= ASCEND_MAX_PKT_LEN)
+ if (parser_state->bcur >= ASCEND_MAX_PKT_LEN)
YYACCEPT;
}
;
@@ -431,27 +448,42 @@ datagroup: dataln
%%
-void
-init_parse_ascend(void)
-{
- start_time = 0; /* we haven't see a date/time yet */
-}
-
/* Run the parser. */
-static int
-run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd)
+int
+run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd,
+ ascend_state_t *parser_state, int *err, gchar **err_info)
{
- /* yydebug = 1; */
+ yyscan_t scanner = NULL;
int retval;
- ascend_init_lexer(fh);
- pseudo_header = &phdr->pseudo_header.ascend;
- pkt_data = pd;
+ if (ascendlex_init(&scanner) != 0) {
+ /* errno is set if this fails */
+ *err = errno;
+ *err_info = NULL;
+ return 1;
+ }
+ /* Associate the parser state with the lexical analyzer state */
+ ascendset_extra(parser_state, scanner);
+ parser_state->fh = fh;
+ parser_state->ascend_parse_error = NULL;
+ parser_state->err = err;
+ parser_state->err_info = err_info;
+ parser_state->pseudo_header = &phdr->pseudo_header.ascend;
+ parser_state->pkt_data = pd;
+
+ /*
+ * We haven't seen a time stamp yet.
+ */
+ parser_state->saw_timestamp = FALSE;
+ parser_state->timestamp = 0;
- bcur = 0;
- first_hexbyte = 0;
- wirelen = 0;
- caplen = 0;
+ parser_state->bcur = 0;
+ parser_state->first_hexbyte = 0;
+ parser_state->wirelen = 0;
+ parser_state->caplen = 0;
+
+ parser_state->secs = 0;
+ parser_state->usecs = 0;
/*
* Not all packets in a "wdd" dump necessarily have a "Cause an
@@ -464,125 +496,16 @@ run_ascend_parser(FILE_T fh, struct wtap_pkthdr *phdr, guint8 *pd)
* phone number from the last call, and remember that for use
* when doing random access.
*/
- pseudo_header->call_num[0] = '\0';
-
- retval = yyparse(fh);
-
- caplen = bcur;
+ parser_state->pseudo_header->call_num[0] = '\0';
+ retval = yyparse(scanner, parser_state, fh);
+ if (retval == 0)
+ parser_state->caplen = parser_state->bcur;
return retval;
}
-/* Parse the capture file.
- Returns:
- TRUE if we got a packet
- FALSE otherwise. */
-gboolean
-check_ascend(FILE_T fh, struct wtap_pkthdr *phdr)
-{
- guint8 buf[ASCEND_MAX_PKT_LEN];
-
- run_ascend_parser(fh, phdr, buf);
-
- /* if we got at least some data, return success even if the parser
- reported an error. This is because the debug header gives the number
- of bytes on the wire, not actually how many bytes are in the trace.
- We won't know where the data ends until we run into the next packet. */
- return (caplen != 0);
-}
-
-/* Parse the capture file.
- Returns:
- PARSED_RECORD if we got a packet
- PARSED_NONRECORD if the parser succeeded but didn't see a packet
- PARSE_FAILED if the parser failed. */
-parse_t
-parse_ascend(ascend_t *ascend, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
- guint length)
-{
- int retval;
-
- ws_buffer_assure_space(buf, length);
- retval = run_ascend_parser(fh, phdr, ws_buffer_start_ptr(buf));
-
- /* did we see any data (hex bytes)? if so, tip off ascend_seek()
- as to where to look for the next packet, if any. If we didn't,
- maybe this record was broken. Advance so we don't get into
- an infinite loop reading a broken trace. */
- if (first_hexbyte) {
- ascend->next_packet_seek_start = first_hexbyte;
- } else {
- /* Sometimes, a header will be printed but the data will be omitted, or
- worse -- two headers will be printed, followed by the data for each.
- Because of this, we need to be fairly tolerant of what we accept
- here. If we didn't find any hex bytes, skip over what we've read so
- far so we can try reading a new packet. */
- ascend->next_packet_seek_start = file_tell(fh);
- retval = 0;
- }
-
- /* if we got at least some data, return success even if the parser
- reported an error. This is because the debug header gives the number
- of bytes on the wire, not actually how many bytes are in the trace.
- We won't know where the data ends until we run into the next packet. */
- if (caplen) {
- if (! ascend->adjusted) {
- ascend->adjusted = TRUE;
- if (start_time != 0) {
- /*
- * Capture file contained a date and time.
- * We do this only if this is the very first packet we've seen -
- * i.e., if "ascend->adjusted" is false - because
- * if we get a date and time after the first packet, we can't
- * go back and adjust the time stamps of the packets we've already
- * processed, and basing the time stamps of this and following
- * packets on the time stamp from the file text rather than the
- * ctime of the capture file means times before this and after
- * this can't be compared.
- */
- ascend->inittime = start_time;
- }
- if (ascend->inittime > secs)
- ascend->inittime -= secs;
- }
- phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
- phdr->ts.secs = secs + ascend->inittime;
- phdr->ts.nsecs = usecs * 1000;
- phdr->caplen = caplen;
- phdr->len = wirelen;
-
- /*
- * For these types, the encapsulation we use is not WTAP_ENCAP_ASCEND,
- * so set the pseudo-headers appropriately for the type (WTAP_ENCAP_ISDN
- * or WTAP_ENCAP_ETHERNET).
- */
- switch(phdr->pseudo_header.ascend.type) {
- case ASCEND_PFX_ISDN_X:
- phdr->pseudo_header.isdn.uton = TRUE;
- phdr->pseudo_header.isdn.channel = 0;
- break;
-
- case ASCEND_PFX_ISDN_R:
- phdr->pseudo_header.isdn.uton = FALSE;
- phdr->pseudo_header.isdn.channel = 0;
- break;
-
- case ASCEND_PFX_ETHER:
- phdr->pseudo_header.eth.fcs_len = 0;
- break;
- }
- return PARSED_RECORD;
- }
-
- /* Didn't see any data. Still, perhaps the parser was happy. */
- if (retval)
- return PARSE_FAILED;
- else
- return PARSED_NONRECORD;
-}
-
void
-yyerror (FILE_T fh _U_, const char *s)
+yyerror (void *yyscanner, ascend_state_t *state _U_, FILE_T fh _U_, const char *s)
{
- ascend_parse_error = s;
+ ascendget_extra(yyscanner)->ascend_parse_error = s;
}
diff --git a/wiretap/ascend_scanner.l b/wiretap/ascend_scanner.l
index 950df9fd3d..24b539e512 100644
--- a/wiretap/ascend_scanner.l
+++ b/wiretap/ascend_scanner.l
@@ -1,4 +1,15 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
+ * We want to generate code that can be used by a reentrant parser
+ * generated by Bison or Berkeley YACC.
+ */
+%option bison-bridge
+
+/*
* We don't read interactively from the terminal.
*/
%option never-interactive
@@ -14,6 +25,19 @@
*/
%option prefix="ascend"
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
%{
/* ascend_scanner.l
*
@@ -42,14 +66,24 @@
#include "wtap-int.h"
#include "ascendtext.h"
-#include "ascend.h"
#include "ascend-int.h"
+#include "ascend.h"
#include "file_wrappers.h"
-#include "ascend_scanner_lex.h"
-FILE_T yy_fh;
-#define YY_INPUT(buf,result,max_size) { int c = file_getc(yy_fh); \
-result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); }
+#define YY_INPUT(buf,result,max_size) { \
+ ascend_state_t *parser_state = ascendget_extra(yyscanner); \
+ int c = file_getc(parser_state->fh); \
+ if (c == EOF) { \
+ *(parser_state->err) = file_error(parser_state->fh, \
+ parser_state->err_info); \
+ if (*(parser_state->err) == 0) \
+ *(parser_state->err) = WTAP_ERR_SHORT_READ; \
+ result = YY_NULL; \
+ } else { \
+ buf[0] = c; \
+ result = 1; \
+ } \
+}
#define NO_USER "<none>"
@@ -57,6 +91,17 @@ result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); }
#define YY_NO_UNISTD_H
#endif
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
+
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define ascendtext_alloc(size, yyscanner) (void *)malloc(size)
+#define ascendtext_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define ascendtext_free(ptr, yyscanner) free((char *)ptr)
%}
@@ -110,43 +155,43 @@ WDD_TYPE "type "[^\n\r\t ]+
<INITIAL,sc_gen_byte>{ETHER_PFX} {
BEGIN(sc_ether_direction);
- ascendlval.d = ASCEND_PFX_ETHER;
+ yylval->d = ASCEND_PFX_ETHER;
return ETHER_PREFIX;
}
<INITIAL,sc_gen_byte>{ISDN_XPFX} {
BEGIN(sc_isdn_call);
- ascendlval.d = ASCEND_PFX_ISDN_X;
+ yylval->d = ASCEND_PFX_ISDN_X;
return ISDN_PREFIX;
}
<INITIAL,sc_gen_byte>{ISDN_RPFX} {
BEGIN(sc_isdn_call);
- ascendlval.d = ASCEND_PFX_ISDN_R;
+ yylval->d = ASCEND_PFX_ISDN_R;
return ISDN_PREFIX;
}
<INITIAL,sc_gen_byte>{WAN_XPFX} {
BEGIN(sc_wds_user);
- ascendlval.d = ASCEND_PFX_WDS_X;
+ yylval->d = ASCEND_PFX_WDS_X;
return WDS_PREFIX;
}
<INITIAL,sc_gen_byte>{WAN_RPFX} {
BEGIN(sc_wds_user);
- ascendlval.d = ASCEND_PFX_WDS_R;
+ yylval->d = ASCEND_PFX_WDS_R;
return WDS_PREFIX;
}
<INITIAL,sc_gen_byte>{PPP_XPFX} {
BEGIN(sc_wds_user);
- ascendlval.d = ASCEND_PFX_WDS_X;
+ yylval->d = ASCEND_PFX_WDS_X;
return WDS_PREFIX;
}
<INITIAL,sc_gen_byte>{PPP_RPFX} {
BEGIN(sc_wds_user);
- ascendlval.d = ASCEND_PFX_WDS_R;
+ yylval->d = ASCEND_PFX_WDS_R;
return WDS_PREFIX;
}
@@ -161,26 +206,26 @@ WDD_TYPE "type "[^\n\r\t ]+
}
<sc_wds_user>[^:]{2,20} {
- char *atcopy = g_strdup(ascendtext);
- char colon = input();
- char after = input();
+ char *atcopy = g_strdup(yytext);
+ char colon = input(yyscanner);
+ char after = input(yyscanner);
int retval = STRING;
unput(after); unput(colon);
if (after != '(' && after != ' ') {
BEGIN(sc_wds_sess);
- if (pseudo_header != NULL) {
- g_strlcpy(pseudo_header->user, atcopy, ASCEND_MAX_STR_LEN);
+ if (yyextra->pseudo_header != NULL) {
+ g_strlcpy(yyextra->pseudo_header->user, atcopy, ASCEND_MAX_STR_LEN);
}
} else { /* We have a version 7 file */
BEGIN(sc_gen_task);
- if (pseudo_header != NULL) {
- g_strlcpy(pseudo_header->user, NO_USER, ASCEND_MAX_STR_LEN);
+ if (yyextra->pseudo_header != NULL) {
+ g_strlcpy(yyextra->pseudo_header->user, NO_USER, ASCEND_MAX_STR_LEN);
}
/* Are valid values ever > 2^32? If so we need to adjust YYSTYPE and a lot of */
/* upstream code accordingly. */
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
retval = DECNUM;
}
g_free (atcopy);
@@ -189,13 +234,13 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_wds_sess>{D}* {
BEGIN(sc_gen_task);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_gen_task>(0x|0X)?{H}{2,8} {
BEGIN(sc_gen_time_s);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 16);
+ yylval->d = (guint32) strtoul(yytext, NULL, 16);
return HEXNUM;
}
@@ -205,24 +250,24 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_gen_time_s>{D}{1,10} {
BEGIN(sc_gen_time_u);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_gen_time_u>{D}{1,6} {
- char *atcopy = g_strdup(ascendtext);
+ char *atcopy = g_strdup(yytext);
BEGIN(sc_gen_octets);
/* only want the most significant 2 digits. convert to usecs */
if (strlen(atcopy) > 2)
atcopy[2] = '\0';
- ascendlval.d = (guint32) strtoul(atcopy, NULL, 10) * 10000;
+ yylval->d = (guint32) strtoul(atcopy, NULL, 10) * 10000;
g_free(atcopy);
return DECNUM;
}
<sc_gen_octets>{D}{1,10} {
BEGIN(sc_gen_counter);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
@@ -232,7 +277,7 @@ WDD_TYPE "type "[^\n\r\t ]+
}
<sc_gen_byte>{H}{2} {
- ascendlval.b = (guint8)(guint32) strtoul(ascendtext, NULL, 16);
+ yylval->b = (guint8)(guint32) strtoul(yytext, NULL, 16);
return HEXBYTE;
}
@@ -251,19 +296,19 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_wdd_date_d>{D}{2} {
BEGIN(sc_wdd_date_m);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_wdd_date_m>{D}{2} {
BEGIN(sc_wdd_date_y);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_wdd_date_y>{D}{4} {
BEGIN(sc_wdd_time);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
@@ -274,19 +319,19 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_wdd_time_h>{D}{2} {
BEGIN(sc_wdd_time_m);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_wdd_time_m>{D}{2} {
BEGIN(sc_wdd_time_s);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
<sc_wdd_time_s>{D}{2} {
BEGIN(sc_wdd_cause);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 10);
+ yylval->d = (guint32) strtoul(yytext, NULL, 10);
return DECNUM;
}
@@ -297,8 +342,8 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_wdd_callnum>{WDD_CALLNUM} {
BEGIN(sc_wdd_chunk);
- if (pseudo_header != NULL) {
- g_strlcpy(pseudo_header->call_num, ascendtext, ASCEND_MAX_STR_LEN);
+ if (yyextra->pseudo_header != NULL) {
+ g_strlcpy(yyextra->pseudo_header->call_num, yytext, ASCEND_MAX_STR_LEN);
}
return STRING;
}
@@ -310,7 +355,7 @@ WDD_TYPE "type "[^\n\r\t ]+
<sc_wdd_chunknum>{H}{1,8} {
BEGIN(sc_wdd_type);
- ascendlval.d = (guint32) strtoul(ascendtext, NULL, 16);
+ yylval->d = (guint32) strtoul(yytext, NULL, 16);
return HEXNUM;
}
@@ -330,12 +375,3 @@ task:|task|at|time:|octets { return KEYWORD; }
<<EOF>> { yyterminate(); }
(.|\n) ;
-
-%%
-
-void ascend_init_lexer(FILE_T fh)
-{
- yyrestart(0);
- yy_fh = fh;
- BEGIN(INITIAL);
-}
diff --git a/wiretap/ascendtext.c b/wiretap/ascendtext.c
index 7697c45e40..7259fa94bf 100644
--- a/wiretap/ascendtext.c
+++ b/wiretap/ascendtext.c
@@ -220,6 +220,8 @@ found:
wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info)
{
gint64 offset;
+ guint8 buf[ASCEND_MAX_PKT_LEN];
+ ascend_state_t parser_state;
ws_statb64 statbuf;
ascend_t *ascend;
@@ -236,8 +238,19 @@ wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info)
}
/* Do a trial parse of the first packet just found to see if we might really have an Ascend file */
- init_parse_ascend();
- if (!check_ascend(wth->fh, &wth->phdr)) {
+ if (run_ascend_parser(wth->fh, &wth->phdr, buf, &parser_state, err, err_info) != 0) {
+ if (*err != 0) {
+ /* An I/O error. */
+ return WTAP_OPEN_ERROR;
+ }
+ }
+
+ /* if we got at least some data, and didn't get an I/O error, return
+ success even if the parser reported an error. This is because the
+ debug header gives the number of bytes on the wire, not actually
+ how many bytes are in the trace. We won't know where the data ends
+ until we run into the next packet. */
+ if (parser_state.caplen == 0) {
return WTAP_OPEN_NOT_MINE;
}
@@ -280,11 +293,113 @@ wtap_open_return_val ascend_open(wtap *wth, int *err, gchar **err_info)
ascend->adjusted = FALSE;
wth->file_tsprec = WTAP_TSPREC_USEC;
- init_parse_ascend();
-
return WTAP_OPEN_MINE;
}
+typedef enum {
+ PARSED_RECORD,
+ PARSED_NONRECORD,
+ PARSE_FAILED
+} parse_t;
+
+/* Parse the capture file.
+ Returns:
+ PARSED_RECORD if we got a packet
+ PARSED_NONRECORD if the parser succeeded but didn't see a packet
+ PARSE_FAILED if the parser failed. */
+static parse_t
+parse_ascend(ascend_t *ascend, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
+ guint length, int *err, gchar **err_info)
+{
+ ascend_state_t parser_state;
+ int retval;
+
+ ws_buffer_assure_space(buf, length);
+ retval = run_ascend_parser(fh, phdr, ws_buffer_start_ptr(buf), &parser_state,
+ err, err_info);
+
+ /* did we see any data (hex bytes)? if so, tip off ascend_seek()
+ as to where to look for the next packet, if any. If we didn't,
+ maybe this record was broken. Advance so we don't get into
+ an infinite loop reading a broken trace. */
+ if (parser_state.first_hexbyte) {
+ ascend->next_packet_seek_start = parser_state.first_hexbyte;
+ } else {
+ /* Sometimes, a header will be printed but the data will be omitted, or
+ worse -- two headers will be printed, followed by the data for each.
+ Because of this, we need to be fairly tolerant of what we accept
+ here. If we didn't find any hex bytes, skip over what we've read so
+ far so we can try reading a new packet. */
+ ascend->next_packet_seek_start = file_tell(fh);
+ retval = 0;
+ }
+
+ /* if we got at least some data, return success even if the parser
+ reported an error. This is because the debug header gives the number
+ of bytes on the wire, not actually how many bytes are in the trace.
+ We won't know where the data ends until we run into the next packet. */
+ if (parser_state.caplen) {
+ if (! ascend->adjusted) {
+ ascend->adjusted = TRUE;
+ if (parser_state.saw_timestamp) {
+ /*
+ * Capture file contained a date and time.
+ * We do this only if this is the very first packet we've seen -
+ * i.e., if "ascend->adjusted" is false - because
+ * if we get a date and time after the first packet, we can't
+ * go back and adjust the time stamps of the packets we've already
+ * processed, and basing the time stamps of this and following
+ * packets on the time stamp from the file text rather than the
+ * ctime of the capture file means times before this and after
+ * this can't be compared.
+ */
+ ascend->inittime = parser_state.timestamp;
+ }
+ if (ascend->inittime > parser_state.secs)
+ ascend->inittime -= parser_state.secs;
+ }
+ phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
+ phdr->ts.secs = parser_state.secs + ascend->inittime;
+ phdr->ts.nsecs = parser_state.usecs * 1000;
+ phdr->caplen = parser_state.caplen;
+ phdr->len = parser_state.wirelen;
+
+ /*
+ * For these types, the encapsulation we use is not WTAP_ENCAP_ASCEND,
+ * so set the pseudo-headers appropriately for the type (WTAP_ENCAP_ISDN
+ * or WTAP_ENCAP_ETHERNET).
+ */
+ switch(phdr->pseudo_header.ascend.type) {
+ case ASCEND_PFX_ISDN_X:
+ phdr->pseudo_header.isdn.uton = TRUE;
+ phdr->pseudo_header.isdn.channel = 0;
+ break;
+
+ case ASCEND_PFX_ISDN_R:
+ phdr->pseudo_header.isdn.uton = FALSE;
+ phdr->pseudo_header.isdn.channel = 0;
+ break;
+
+ case ASCEND_PFX_ETHER:
+ phdr->pseudo_header.eth.fcs_len = 0;
+ break;
+ }
+ return PARSED_RECORD;
+ }
+
+ /* Didn't see any data. Still, perhaps the parser was happy. */
+ if (retval) {
+ if (*err == 0) {
+ /* Not a bad record, so a parse error. Return WTAP_ERR_BAD_FILE,
+ with the parse error as the error string. */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup((parser_state.ascend_parse_error != NULL) ? parser_state.ascend_parse_error : "parse error");
+ }
+ return PARSE_FAILED;
+ } else
+ return PARSED_NONRECORD;
+}
+
/* Read the next packet; called from wtap_read(). */
static gboolean ascend_read(wtap *wth, int *err, gchar **err_info,
gint64 *data_offset)
@@ -304,11 +419,8 @@ static gboolean ascend_read(wtap *wth, int *err, gchar **err_info,
if (offset == -1)
return FALSE;
if (parse_ascend(ascend, wth->fh, &wth->phdr, wth->frame_buffer,
- wth->snapshot_length) != PARSED_RECORD) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error");
+ wth->snapshot_length, err, err_info) != PARSED_RECORD)
return FALSE;
- }
*data_offset = offset;
return TRUE;
@@ -323,11 +435,8 @@ static gboolean ascend_seek_read(wtap *wth, gint64 seek_off,
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
if (parse_ascend(ascend, wth->random_fh, phdr, buf,
- wth->snapshot_length) != PARSED_RECORD) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error");
+ wth->snapshot_length, err, err_info) != PARSED_RECORD)
return FALSE;
- }
return TRUE;
}
diff --git a/wiretap/k12text.l b/wiretap/k12text.l
index 3ff7ca8610..4cdea9c951 100644
--- a/wiretap/k12text.l
+++ b/wiretap/k12text.l
@@ -1,4 +1,9 @@
/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
* We don't use input, so don't generate code for it.
*/
%option noinput
@@ -19,10 +24,15 @@
%option noyywrap
/*
- * Prefix scanner routines with "K12Text_" rather than "yy", so this scanner
+ * The type for the state we keep for a scanner.
+ */
+%option extra-type="k12text_state_t *"
+
+/*
+ * Prefix scanner routines with "k12text_" rather than "yy", so this scanner
* can coexist with other scanners.
*/
-%option prefix="K12Text_"
+%option prefix="k12text_"
%option outfile="k12text.c"
@@ -45,6 +55,19 @@
/* %option noline */
/* %option debug */
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
%{
/* k12text.l
*
@@ -82,41 +105,64 @@
#include "file_wrappers.h"
#include <wsutil/buffer.h>
#include "k12.h"
-#include "k12text_lex.h"
#ifndef HAVE_UNISTD_H
#define YY_NO_UNISTD_H
#endif
-static guint g_h;
-static guint g_m;
-static guint g_s;
-static guint g_ms;
-static guint g_ns;
-static gint g_encap;
-static guint8 bb[WTAP_MAX_PACKET_SIZE];
-static guint ii;
-static gboolean is_k12text;
-static gboolean at_eof;
-static guint junk_chars;
-static void finalize_frame(void);
-static gchar* error_str;
-static guint64 file_bytes_read;
-static gboolean ok_frame;
-static FILE_T yy_fh;
-
-#define KERROR(text) do { error_str = g_strdup(text); yyterminate(); } while(0)
-#define SET_HOURS(text) g_h = (guint) strtoul(text,NULL,10)
-#define SET_MINUTES(text) g_m = (guint) strtoul(text,NULL,10)
-#define SET_SECONDS(text) g_s = (guint) strtoul(text,NULL,10)
-#define SET_MS(text) g_ms = (guint) strtoul(text,NULL,10)
-#define SET_NS(text) g_ns = (guint) strtoul(text,NULL,10)
-#define ADD_BYTE(text) do {if (ii >= WTAP_MAX_PACKET_SIZE) {KERROR("frame too large");} bb[ii++] = (guint8)strtoul(text,NULL,16); } while(0)
-#define FINALIZE_FRAME() finalize_frame()
+/*
+ * State kept by the scanner.
+ */
+typedef struct {
+ FILE_T fh;
+ int *err;
+ gchar **err_info;
+ int start_state;
+
+ guint g_h;
+ guint g_m;
+ guint g_s;
+ guint g_ms;
+ guint g_ns;
+ gint g_encap;
+ guint8 bb[WTAP_MAX_PACKET_SIZE];
+ guint ii;
+ gboolean is_k12text;
+ gboolean at_eof;
+ guint junk_chars;
+ gchar* error_str;
+ guint64 file_bytes_read;
+ gboolean ok_frame;
+} k12text_state_t;
+
+#define KERROR(text) do { yyextra->error_str = g_strdup(text); yyterminate(); } while(0)
+#define SET_HOURS(text) yyextra->g_h = (guint) strtoul(text,NULL,10)
+#define SET_MINUTES(text) yyextra->g_m = (guint) strtoul(text,NULL,10)
+#define SET_SECONDS(text) yyextra->g_s = (guint) strtoul(text,NULL,10)
+#define SET_MS(text) yyextra->g_ms = (guint) strtoul(text,NULL,10)
+#define SET_NS(text) yyextra->g_ns = (guint) strtoul(text,NULL,10)
+#define ADD_BYTE(text) do {if (yyextra->ii >= WTAP_MAX_PACKET_SIZE) {KERROR("frame too large");} yyextra->bb[yyextra->ii++] = (guint8)strtoul(text,NULL,16); } while(0)
+#define FINALIZE_FRAME() do { yyextra->ok_frame = TRUE; } while (0)
/*~ #define ECHO*/
-#define YY_USER_ACTION file_bytes_read += yyleng;
-#define YY_INPUT(buf,result,max_size) { int c = file_getc(yy_fh); result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); }
-
+#define YY_USER_ACTION yyextra->file_bytes_read += yyleng;
+#define YY_USER_INIT { \
+ k12text_state_t *scanner_state = k12text_get_extra(yyscanner); \
+ BEGIN(scanner_state->start_state); \
+}
+#define YY_INPUT(buf,result,max_size) { \
+ k12text_state_t *scanner_state = k12text_get_extra(yyscanner); \
+ int c = file_getc(scanner_state->fh); \
+ if (c == EOF) { \
+ *(scanner_state->err) = file_error(scanner_state->fh, \
+ scanner_state->err_info); \
+ if (*(scanner_state->err) == 0) \
+ *(scanner_state->err) = WTAP_ERR_SHORT_READ; \
+ result = YY_NULL; \
+ } else { \
+ buf[0] = c; \
+ result = 1; \
+ } \
+}
#define MAX_JUNK 400000
#define ECHO
@@ -134,6 +180,19 @@ typedef struct {
*/
gint64 next_frame_offset;
} k12text_t;
+
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
+
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define k12text_alloc(size, yyscanner) (void *)malloc(size)
+#define k12text_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define k12text_free(ptr, yyscanner) free((char *)ptr)
+
%}
start_timestamp \053[\055]{9}\053[\055]{15,100}\053[\055]{10,100}\053
oneormoredigits [0-9]+:
@@ -153,9 +212,9 @@ hdlc HDLC
%START MAGIC NEXT_FRAME HOURS MINUTES M2S SECONDS S2M MS M2N NS ENCAP STARTBYTES BYTE
%%
-<MAGIC>{start_timestamp} { is_k12text = TRUE; yyterminate(); }
+<MAGIC>{start_timestamp} { yyextra->is_k12text = TRUE; yyterminate(); }
-<MAGIC>. { if (++ junk_chars > MAX_JUNK) { is_k12text = FALSE; yyterminate(); } }
+<MAGIC>. { if (++ yyextra->junk_chars > MAX_JUNK) { yyextra->is_k12text = FALSE; yyterminate(); } }
<NEXT_FRAME>{start_timestamp} {BEGIN(HOURS); }
<HOURS>{oneormoredigits} { SET_HOURS(yytext); BEGIN(MINUTES); }
@@ -166,42 +225,39 @@ hdlc HDLC
<MS>{threedigits} { SET_MS(yytext); BEGIN(M2N); }
<M2N>{comma} { BEGIN(NS); }
<NS>{threedigits} { SET_NS(yytext); BEGIN(ENCAP);}
-<ENCAP>{eth} {g_encap = WTAP_ENCAP_ETHERNET; BEGIN(STARTBYTES); }
-<ENCAP>{mtp2} {g_encap = WTAP_ENCAP_MTP2; BEGIN(STARTBYTES); }
-<ENCAP>{sscop} {g_encap = WTAP_ENCAP_ATM_PDUS; BEGIN(STARTBYTES); }
-<ENCAP>{sscfnni} {g_encap = WTAP_ENCAP_MTP3; BEGIN(STARTBYTES); }
-<ENCAP>{hdlc} {g_encap = WTAP_ENCAP_CHDLC; BEGIN(STARTBYTES); }
+<ENCAP>{eth} {yyextra->g_encap = WTAP_ENCAP_ETHERNET; BEGIN(STARTBYTES); }
+<ENCAP>{mtp2} {yyextra->g_encap = WTAP_ENCAP_MTP2; BEGIN(STARTBYTES); }
+<ENCAP>{sscop} {yyextra->g_encap = WTAP_ENCAP_ATM_PDUS; BEGIN(STARTBYTES); }
+<ENCAP>{sscfnni} {yyextra->g_encap = WTAP_ENCAP_MTP3; BEGIN(STARTBYTES); }
+<ENCAP>{hdlc} {yyextra->g_encap = WTAP_ENCAP_CHDLC; BEGIN(STARTBYTES); }
<ENCAP,STARTBYTES>{start_bytes} { BEGIN(BYTE); }
<BYTE>{byte} { ADD_BYTE(yytext); }
<BYTE>{bytes_junk} ;
<BYTE>{end_bytes} { FINALIZE_FRAME(); yyterminate(); }
-. { if (++junk_chars > MAX_JUNK) { KERROR("too much junk"); } }
-<<EOF>> { at_eof = TRUE; yyterminate(); }
+. { if (++yyextra->junk_chars > MAX_JUNK) { KERROR("too much junk"); } }
+<<EOF>> { yyextra->at_eof = TRUE; yyterminate(); }
%%
-static void finalize_frame(void) {
- ok_frame = TRUE;
-}
-
/* Fill in pkthdr */
static gboolean
-k12text_set_headers(struct wtap_pkthdr *phdr, int *err, gchar **err_info)
+k12text_set_headers(struct wtap_pkthdr *phdr, k12text_state_t *state,
+ int *err, gchar **err_info)
{
phdr->rec_type = REC_TYPE_PACKET;
phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
- phdr->ts.secs = 946681200 + (3600*g_h) + (60*g_m) + g_s;
- phdr->ts.nsecs = 1000000*g_ms + 1000*g_ns;
+ phdr->ts.secs = 946681200 + (3600*state->g_h) + (60*state->g_m) + state->g_s;
+ phdr->ts.nsecs = 1000000*state->g_ms + 1000*state->g_ns;
- phdr->caplen = phdr->len = ii;
+ phdr->caplen = phdr->len = state->ii;
- phdr->pkt_encap = g_encap;
+ phdr->pkt_encap = state->g_encap;
/* The file-encap is WTAP_ENCAP_PER_PACKET */
- switch(g_encap) {
+ switch(state->g_encap) {
case WTAP_ENCAP_ETHERNET:
phdr->pseudo_header.eth.fcs_len = 0;
break;
@@ -236,30 +292,54 @@ k12text_set_headers(struct wtap_pkthdr *phdr, int *err, gchar **err_info)
/* used even when multiple files are open simultaneously (as for */
/* a file merge). */
-static void
-k12text_reset(FILE_T fh)
+static gboolean
+k12text_run_scanner(k12text_state_t *state, FILE_T fh, int start_state,
+ int *err, gchar **err_info)
{
- yy_fh = fh;
- yyrestart(0);
- g_encap = WTAP_ENCAP_UNKNOWN;
- ok_frame = FALSE;
- is_k12text = FALSE;
- at_eof = FALSE;
- junk_chars = 0;
- error_str = NULL;
- file_bytes_read=0;
- g_h=0;
- g_m=0;
- g_s=0;
- g_ns=0;
- g_ms=0;
- ii=0;
+ yyscan_t scanner = NULL;
+
+ if (yylex_init(&scanner) != 0) {
+ /* errno is set if this fails */
+ *err = errno;
+ *err_info = NULL;
+ return FALSE;
+ }
+ state->fh = fh;
+ state->err = err;
+ state->err_info = err_info;
+ state->start_state = start_state;
+
+ state->g_encap = WTAP_ENCAP_UNKNOWN;
+ state->ok_frame = FALSE;
+ state->is_k12text = FALSE;
+ state->at_eof = FALSE;
+ state->junk_chars = 0;
+ state->error_str = NULL;
+ state->file_bytes_read=0;
+ state->g_h=0;
+ state->g_m=0;
+ state->g_s=0;
+ state->g_ns=0;
+ state->g_ms=0;
+ state->ii=0;
+
+ /* Associate the state with the scanner */
+ k12text_set_extra(state, scanner);
+
+ yylex(scanner);
+ yylex_destroy(scanner);
+ if (*err != 0 && *err != WTAP_ERR_SHORT_READ) {
+ /* I/O error. */
+ return FALSE;
+ }
+ return TRUE;
}
static gboolean
k12text_read(wtap *wth, int *err, char ** err_info, gint64 *data_offset)
{
k12text_t *k12text = (k12text_t *)wth->priv;
+ k12text_state_t state;
/*
* We seek to the file position after the end of the previous frame
@@ -273,30 +353,29 @@ k12text_read(wtap *wth, int *err, char ** err_info, gint64 *data_offset)
if ( file_seek(wth->fh, k12text->next_frame_offset, SEEK_SET, err) == -1) {
return FALSE;
}
- k12text_reset(wth->fh); /* init lexer buffer and vars set by lexer */
-
- BEGIN(NEXT_FRAME);
- yylex();
+ if (!k12text_run_scanner(&state, wth->fh, NEXT_FRAME, err, err_info)) {
+ return FALSE;
+ }
- if (ok_frame == FALSE) {
- if (at_eof) {
+ if (state.ok_frame == FALSE) {
+ if (state.at_eof) {
*err = 0;
*err_info = NULL;
} else {
*err = WTAP_ERR_BAD_FILE;
- *err_info = error_str;
+ *err_info = state.error_str;
}
return FALSE;
}
- *data_offset = k12text->next_frame_offset; /* file position for beginning of this frame */
- k12text->next_frame_offset += file_bytes_read; /* file position after end of this frame */
+ *data_offset = k12text->next_frame_offset; /* file position for beginning of this frame */
+ k12text->next_frame_offset += state.file_bytes_read; /* file position after end of this frame */
- if (!k12text_set_headers(&wth->phdr, err, err_info))
+ if (!k12text_set_headers(&wth->phdr, &state, err, err_info))
return FALSE;
ws_buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
- memcpy(ws_buffer_start_ptr(wth->frame_buffer), bb, wth->phdr.caplen);
+ memcpy(ws_buffer_start_ptr(wth->frame_buffer), state.bb, wth->phdr.caplen);
return TRUE;
}
@@ -304,30 +383,31 @@ k12text_read(wtap *wth, int *err, char ** err_info, gint64 *data_offset)
static gboolean
k12text_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, Buffer *buf, int *err, char **err_info)
{
+ k12text_state_t state;
+
if ( file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) {
return FALSE;
}
- k12text_reset(wth->random_fh); /* init lexer buffer and vars set by lexer */
-
- BEGIN(NEXT_FRAME);
- yylex();
+ if (!k12text_run_scanner(&state, wth->random_fh, NEXT_FRAME, err, err_info)) {
+ return FALSE;
+ }
- if (ok_frame == FALSE) {
+ if (state.ok_frame == FALSE) {
*err = WTAP_ERR_BAD_FILE;
- if (at_eof) {
+ if (state.at_eof) {
/* What happened ? The desired frame was previously read without a problem */
*err_info = g_strdup("Unexpected EOF (program error ?)");
} else {
- *err_info = error_str;
+ *err_info = state.error_str;
}
return FALSE;
}
- if (!k12text_set_headers(phdr, err, err_info))
+ if (!k12text_set_headers(phdr, &state, err, err_info))
return FALSE;
ws_buffer_assure_space(buf, phdr->caplen);
- memcpy(ws_buffer_start_ptr(buf), bb, phdr->caplen);
+ memcpy(ws_buffer_start_ptr(buf), state.bb, phdr->caplen);
return TRUE;
}
@@ -336,13 +416,17 @@ wtap_open_return_val
k12text_open(wtap *wth, int *err, gchar **err_info _U_)
{
k12text_t *k12text;
+ k12text_state_t state;
- k12text_reset(wth->fh); /* init lexer buffer and vars set by lexer */
-
- BEGIN(MAGIC);
- yylex();
+ if (!k12text_run_scanner(&state, wth->fh, MAGIC, err, err_info)) {
+ return WTAP_OPEN_ERROR;
+ }
- if (! is_k12text) return WTAP_OPEN_NOT_MINE;
+ if (!state.is_k12text) {
+ /* *err might have been set to WTAP_ERR_SHORT_READ */
+ *err = 0;
+ return WTAP_OPEN_NOT_MINE;
+ }
if ( file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
return WTAP_OPEN_ERROR;