pytest.ini: declare minimum version requirement
[metze/wireshark/wip.git] / epan / dtd_preparse.l
index 276b19d0babfb64074068624640e22adf362864d..669d1472969980d9d4691582a2a835e4c5f88245 100644 (file)
@@ -1,13 +1,38 @@
+%top {
+/* Include this before everything else, for various large-file definitions */
+#include "config.h"
+}
+
+/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
+ * We don't use input, so don't generate code for it.
+ */
+%option noinput
+
 /*
  * We don't use unput, so don't generate code for it.
  */
 %option nounput
 
 /*
- * We don't read from the terminal.
+ * We don't read interactively from the terminal.
  */
 %option never-interactive
 
+/*
+ * We want to stop processing when we get to the end of the input.
+ */
+%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 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>
         *
-        * $Id$
-        *
         * Wireshark - Network traffic analyzer
         * By Gerald Combs <gerald@wireshark.org>
         * Copyright 1998 Gerald Combs
 #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);
+/*
+ * Disable diagnostics in the code generated by Flex.
+ */
+DIAG_OFF_FLEX
+
+#define ECHO g_string_append(yyextra->current,yytext);
 
-static GString* current;
-static GString* output;
-static GHashTable* entities;
-static gchar* entity_name;
-static GString* error;
+struct _dtd_preparse_scanner_state {
+       const gchar* dtd_dirname;
+       const gchar* filename;
+       guint linenum;
 
-static const gchar* dtd_dirname;
-static const gchar* filename;
-static guint linenum;
+       GString* error;
 
-static gchar* replace_entity(gchar* s);
-static const gchar* location(void);
+       GHashTable* entities;
+       GString* current;
+       GString* output;
+       gchar* entity_name;
+};
+
+static const gchar* replace_entity(Dtd_PreParse_scanner_state_t* state, gchar* s);
+
+#define YY_USER_INIT { \
+       BEGIN OUTSIDE; \
+}
 
 /*
  * Flex (v 2.5.35) uses this symbol to "exclude" unistd.h
@@ -84,11 +130,17 @@ static const gchar* location(void);
 #define YY_NO_UNISTD_H
 #endif
 
-#ifdef _WIN32
-/* disable Windows VC compiler warning "signed/unsigned mismatch" associated  */
-/* with YY_INPUT code generated by flex versions such as 2.5.35.              */
-#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 "<?"
@@ -122,117 +174,127 @@ 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),dtd_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",dtd_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(dtd_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);
-    yyterminate();
+       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 gchar* replace_entity(gchar* entity) {
+/*
+ * Turn diagnostics back on, so we check the code that we've written.
+ */
+DIAG_ON_FLEX
+
+static const gchar* replace_entity(Dtd_PreParse_scanner_state_t* state, gchar* entity) {
        GString* replacement;
 
        *entity = '%';
 
-       replacement = 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) {
+const gchar* dtd_location(Dtd_PreParse_scanner_state_t* state) {
        static gchar* loc = NULL;
 
-       if (loc) g_free(loc);
+       g_free(loc);
+
+       if (!state) return NULL;
 
-       loc = g_strdup_printf("<? wireshark:location %s:%u ?>", filename, linenum);
+       loc = g_strdup_printf("<? wireshark:location %s:%u ?>", state->filename, state->linenum);
 
        return loc;
 }
 
 static gboolean free_gstring_hash_items(gpointer k,gpointer v,gpointer p _U_) {
        g_free(k);
-       g_string_free(v,TRUE);
+       g_string_free((GString*)v,TRUE);
        return TRUE;
 }
 
 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,strerror(errno));
+                       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;
+       }
 
-       entities = g_hash_table_new(g_str_hash,g_str_equal);
-       current = output = g_string_new(location());
+       Dtd_PreParse_set_in(in, scanner);
 
-       BEGIN OUTSIDE;
+       state.dtd_dirname = dname;
+       state.filename = fname;
+       state.linenum = 1;
 
-       yylex();
+       state.error = err;
 
-       fclose(yyin);
+       state.entities = g_hash_table_new(g_str_hash,g_str_equal);
+       state.current = state.output = g_string_new(dtd_location(&state));
+       state.entity_name = NULL;
 
-       yyrestart(NULL);
+       /* Associate the state with the scanner */
+       Dtd_PreParse_set_extra(&state, scanner);
 
-       g_hash_table_foreach_remove(entities,free_gstring_hash_items,NULL);
-       g_hash_table_destroy(entities);
+       Dtd_PreParse_lex(scanner);
 
-    g_free(fullname);
+       Dtd_PreParse_lex_destroy(scanner);
+       fclose(in);
 
-       return output;
-}
+       g_hash_table_foreach_remove(state.entities,free_gstring_hash_items,NULL);
+       g_hash_table_destroy(state.entities);
 
-/*
- * We want to stop processing when we get to the end of the input.
- * (%option noyywrap is not used because if used then
- * some flex versions (eg: 2.5.35) generate code which causes
- * warnings by the Windows VC compiler).
- */
+       g_free(fullname);
 
-int yywrap(void) {
-    return 1;
+       return state.output;
 }