diff options
-rw-r--r-- | cmake/modules/FindLEX.cmake | 10 | ||||
-rw-r--r-- | epan/Makefile.am | 3 | ||||
-rw-r--r-- | epan/dfilter/dfilter-int.h | 8 | ||||
-rw-r--r-- | epan/dfilter/dfilter.c | 37 | ||||
-rw-r--r-- | epan/dfilter/scanner.l | 75 | ||||
-rw-r--r-- | epan/diam_dict.l | 537 | ||||
-rw-r--r-- | epan/dtd_parse.h | 1 | ||||
-rw-r--r-- | epan/dtd_parse.l | 151 | ||||
-rw-r--r-- | epan/dtd_preparse.l | 165 | ||||
-rw-r--r-- | epan/radius_dict.l | 449 | ||||
-rw-r--r-- | epan/uat_load.l | 267 | ||||
-rw-r--r-- | plugins/mate/Makefile.am | 3 | ||||
-rw-r--r-- | plugins/mate/mate_parser.l | 275 | ||||
-rw-r--r-- | plugins/wimaxasncp/Makefile.am | 4 | ||||
-rw-r--r-- | plugins/wimaxasncp/wimaxasncp_dict.l | 447 | ||||
-rwxr-xr-x | tools/runlex.sh | 91 | ||||
-rw-r--r-- | ui/Makefile.am | 2 | ||||
-rw-r--r-- | ui/gtk/file_import_dlg.c | 7 | ||||
-rw-r--r-- | ui/qt/import_text_dialog.cpp | 8 | ||||
-rw-r--r-- | ui/text_import.c | 20 | ||||
-rw-r--r-- | ui/text_import.h | 2 | ||||
-rw-r--r-- | ui/text_import_scanner.l | 42 | ||||
-rw-r--r-- | wiretap/Makefile.am | 6 | ||||
-rw-r--r-- | wiretap/ascend-int.h | 43 | ||||
-rw-r--r-- | wiretap/ascend.y | 395 | ||||
-rw-r--r-- | wiretap/ascend_scanner.l | 126 | ||||
-rw-r--r-- | wiretap/ascendtext.c | 133 | ||||
-rw-r--r-- | wiretap/k12text.l | 268 |
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; |