pytest.ini: declare minimum version requirement
[metze/wireshark/wip.git] / epan / dtd_preparse.l
index 1d43095e7db8b11e5cdb3757ff00722fcc3b95bf..669d1472969980d9d4691582a2a835e4c5f88245 100644 (file)
-%option noyywrap
+%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
-%option prefix="Dtd_PreParse_"
+
+/*
+ * 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 caseless
+
+/*
+ * Prefix scanner routines with "Dtd_PreParse_" rather than "yy", so this
+ * scanner can coexist with other scanners.
+ */
+%option prefix="Dtd_PreParse_"
+
 %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 ethereal 
+        * 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@gmail.com>
         *
-        * $Id$
+        * Copyright 2004, Luis E. Garcia Ontanon <luis@ontanon.org>
         *
-        * Ethereal - Network traffic analyzer
-        * By Gerald Combs <gerald@ethereal.com>
+        * Wireshark - Network traffic analyzer
+        * By Gerald Combs <gerald@wireshark.org>
         * Copyright 1998 Gerald Combs
         *
         * This program is free software; you can redistribute it and/or
         * modify it under the terms of the GNU General Public License
         * as published by the Free Software Foundation; either version 2
         * of the License, or (at your option) any later version.
-        * 
+        *
         * This program is distributed in the hope that it will be useful,
         * but WITHOUT ANY WARRANTY; without even the implied warranty of
         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
         * GNU General Public License for more details.
-        * 
+        *
         * You should have received a copy of the GNU General Public License
         * along with this program; if not, write to the Free Software
-        * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+        * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
         */
-                       
+
 #include <glib.h>
 #include <string.h>
 #include <errno.h>
 #include <stdio.h>
 #include "dtd.h"
+#include <wsutil/file_util.h>
+
+/*
+ * Disable diagnostics in the code generated by Flex.
+ */
+DIAG_OFF_FLEX
+
+#define ECHO g_string_append(yyextra->current,yytext);
 
-#define ECHO g_string_append(current,yytext);
+struct _dtd_preparse_scanner_state {
+       const gchar* dtd_dirname;
+       const gchar* filename;
+       guint linenum;
 
-GString* current;
-GString* output;
-GHashTable* entities;
-gchar* entity_name;
-GString* error;
+       GString* error;
 
-const gchar* dirname;
-const gchar* filename;
-guint linenum;
+       GHashTable* entities;
+       GString* current;
+       GString* output;
+       gchar* entity_name;
+};
 
-GString* textstr;
+static const gchar* replace_entity(Dtd_PreParse_scanner_state_t* state, gchar* s);
+
+#define YY_USER_INIT { \
+       BEGIN OUTSIDE; \
+}
 
-static gchar* replace_entity(gchar* s);
-static const gchar* location(void);
+/*
+ * Flex (v 2.5.35) uses this symbol to "exclude" unistd.h
+ */
+#ifdef _WIN32
+#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_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 "<?"
@@ -93,104 +174,127 @@ newline    \n
 %%
 
 
-{entity}                                               if (current) g_string_sprintfa(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; }
-       
-{newline}                                              {
-       linenum++;
-       if (current) g_string_sprintfa(current,"%s\n",location());
+<OUTSIDE>{comment_start}               { yyextra->current = NULL; BEGIN IN_COMMENT; }
+<IN_COMMENT>[^-]?                      |
+<IN_COMMENT>[-]                                ;
+<IN_COMMENT>{comment_stop}             { yyextra->current = yyextra->output; BEGIN OUTSIDE; }
+
+{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_sprintfa(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_sprintfa(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);
-    
-       loc = g_strdup_printf("<? ethereal:location %s:%u ?>", filename, linenum);
-       
+
+       g_free(loc);
+
+       if (!state) return NULL;
+
+       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);
-    
-       dirname = dname;
-       filename = fname;
-       linenum = 1;
-
-       yyin = fopen(fullname,"r");
-       
-       if (!yyin) {
+       FILE *in;
+       yyscan_t scanner;
+       Dtd_PreParse_scanner_state_t state;
+
+       in = ws_fopen(fullname,"r");
+
+       if (!in) {
                if (err)
-                       g_string_sprintfa(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;
-       
-       entities = g_hash_table_new(g_str_hash,g_str_equal);
-       current = output = g_string_new(location());
-       
-       BEGIN OUTSIDE;
 
-       yylex();
-               
-       yyrestart(NULL);
+       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;
+
+       state.error = err;
+
+       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;
+
+       /* Associate the state with the scanner */
+       Dtd_PreParse_set_extra(&state, scanner);
+
+       Dtd_PreParse_lex(scanner);
+
+       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);
+       g_free(fullname);
 
-       return output;
+       return state.output;
 }