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