diff options
Diffstat (limited to 'epan')
-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 |
10 files changed, 1064 insertions, 629 deletions
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; } |