From Bjørn Mork:
[metze/wireshark/wip.git] / epan / radius_dict.l
index 4ced501ff75622c59d66ed6134e12e115e1694c8..916cdc001452dde709815a796fb27b899e8ad76e 100644 (file)
@@ -1,21 +1,35 @@
-%option noyywrap
-
+/*
+ * We don't use unput, so don't generate code for it.
+ */
 %option nounput
+
+/*
+ * We don't read from the terminal.
+ */
 %option never-interactive
-%option prefix="Radius"
+
+/*
+ * The language we're scanning is case-insensitive.
+ */
 %option caseless
 
+/*
+ * Prefix scanner routines with "Radius" rather than "yy", so this scanner
+ * can coexist with other scanners.
+ */
+%option prefix="Radius"
+
 %option outfile="radius_dict.c"
 
 %{
-       /* packet-radius.c
+       /* radius_dict.l
        *
        * RADIUS dictionary parser
        *
        * $Id$
        *
-       * 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
        *
        * 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.
        */
-       
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
-       
+
 #include <glib.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <epan/packet.h>
 #include <epan/dissectors/packet-radius.h>
-#define DIR_SEPARATOR '/'
+#include "radius_dict_lex.h"
+#include <wsutil/file_util.h>
+
+#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
+
 #define ECHO
 #define MAX_INCLUDE_DEPTH 10
 
-       void add_vendor(gchar* name, guint32 vendor_id);
-       void add_value(gchar* attrib_name, gchar* value_repr, long value);
-       void add_attribute(gchar*, gchar*, radius_attr_dissector_t, gchar*, gboolean, gboolean);
-       
+       void add_vendor(const gchar* name, guint32 vendor_id);
+       void add_value(const gchar* attrib_name,const  gchar* value_repr, long value);
+       void add_attribute(const gchar*,const  gchar*, radius_attr_dissector_t,const  gchar*, gboolean, gboolean);
+
        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 gboolean encrypted = FALSE;
        static gboolean has_tag = FALSE;
        static gchar* current_vendor = 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};
-       
+
 %}
 
-%START OUT VENDOR VENDOR_W_NAME ATTR ATTR_W_NAME ATTR_W_ID ATTR_W_TYPE ATTR_W_VENDOR VALUE VALUE_W_ATTR VALUE_W_NAME INCLUDE JUNK BEGIN_VENDOR END_VENDOR
+%START WS_OUT VENDOR VENDOR_W_NAME ATTR ATTR_W_NAME ATTR_W_ID ATTR_W_TYPE ATTR_W_VENDOR VALUE VALUE_W_ATTR VALUE_W_NAME INCLUDE JUNK BEGIN_VENDOR END_VENDOR
 %%
 [:blank:]   ;
 #[^\n]*                ;
 
 <JUNK>.*\qn            ;
 
-<OUT>VENDOR { BEGIN VENDOR; }
-<OUT>ATTRIBUTE { BEGIN ATTR; }
-<OUT>VALUE { BEGIN VALUE; }
-<OUT>\$INCLUDE { BEGIN INCLUDE; }
-<OUT>BEGIN-VENDOR { BEGIN BEGIN_VENDOR; }
-<OUT>END-VENDOR { BEGIN END_VENDOR; }
-
-<BEGIN_VENDOR>[0-9a-z_-]+ {current_vendor = g_strdup(yytext); BEGIN OUT; }
-<END_VENDOR>[^\n]* {if (current_vendor) { g_free(current_vendor); current_vendor = NULL; } BEGIN OUT; }
+<WS_OUT>VENDOR { BEGIN VENDOR; }
+<WS_OUT>ATTRIBUTE { BEGIN ATTR; }
+<WS_OUT>VALUE { BEGIN VALUE; }
+<WS_OUT>\$INCLUDE { BEGIN INCLUDE; }
+<WS_OUT>BEGIN-VENDOR { BEGIN BEGIN_VENDOR; }
+<WS_OUT>END-VENDOR { BEGIN END_VENDOR; }
+
+<BEGIN_VENDOR>[0-9a-z_-]+ {
+    if (current_vendor) {
+        g_free(current_vendor);
+    }
+    current_vendor = g_strdup(yytext);
+    BEGIN WS_OUT;
+}
+<END_VENDOR>[^\n]* {
+    if (current_vendor) {
+        g_free(current_vendor);
+        current_vendor = NULL;
+    }
+    BEGIN WS_OUT;
+}
 
 <VENDOR>[0-9a-z_-]+   { vendor_name = g_strdup(yytext); BEGIN VENDOR_W_NAME; }
-<VENDOR_W_NAME>[0-9]+   { add_vendor(vendor_name,strtol(yytext,NULL,10)); BEGIN OUT; }
-<VENDOR_W_NAME>0x[0-9a-f]+   { add_vendor(vendor_name,strtol(yytext,NULL,16)); BEGIN OUT; }
-
-<ATTR>[0-9a-z_-]+                                      { attr_name = g_strdup(yytext); encrypted = FALSE; 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>date                                                { attr_type = radius_date;  BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ipv6addr                                    { attr_type = radius_ipv6addr;  BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ifid                                                { attr_type = radius_ifid;  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_vendor = NULL;  BEGIN ATTR_W_VENDOR; }
-<ATTR_W_TYPE>encrypt=1[,]?                     { encrypted=TRUE;  attr_vendor = NULL;  BEGIN ATTR_W_VENDOR; }
-<ATTR_W_TYPE>[,0-9a-z_-]+=([^\n]+)     { /* ignore other parameters */  attr_vendor = NULL;  BEGIN ATTR_W_VENDOR; }
-<ATTR_W_TYPE>[0-9a-z_-]+                       { attr_vendor = g_strdup(yytext);  add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypted,has_tag); attr_vendor = NULL;  BEGIN OUT; }
-<ATTR_W_TYPE>\n                                                { add_attribute(attr_name,attr_id,attr_type,current_vendor ? g_strdup(current_vendor) : NULL ,encrypted,has_tag); linenums[include_stack_ptr]++;  BEGIN OUT; }
-<ATTR_W_VENDOR>\n                                      { add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypted,has_tag); linenums[include_stack_ptr]++; BEGIN OUT; };
-
-<VALUE>[0-9a-z-]+                                      { attr_name = g_strdup(yytext); BEGIN VALUE_W_ATTR; }
+<VENDOR_W_NAME>[0-9]+   {
+    add_vendor(vendor_name,strtol(yytext,NULL,10));
+    g_free(vendor_name);
+    BEGIN WS_OUT;
+}
+<VENDOR_W_NAME>0x[0-9a-f]+   {
+    add_vendor(vendor_name,strtol(yytext,NULL,16));
+    g_free(vendor_name);
+    BEGIN WS_OUT;
+}
+
+<ATTR>[0-9a-z_/-]+                     { attr_name = g_strdup(yytext); encrypted = FALSE; 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>ifid                                { attr_type = radius_ifid;  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=1[,]?             { encrypted=TRUE; }
+<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);
+    g_free(attr_id);
+    g_free(attr_vendor);
+    g_free(attr_name);
+    attr_id = NULL;
+    attr_vendor = NULL;
+    attr_name = NULL;
+    BEGIN WS_OUT;
+}
+<ATTR_W_TYPE>\n                                                {
+    add_attribute(attr_name,attr_id,attr_type,current_vendor,encrypted,has_tag);
+    g_free(attr_id);
+    g_free(attr_name);
+    linenums[include_stack_ptr]++;
+    has_tag = FALSE;
+    encrypted=FALSE;
+    BEGIN WS_OUT;
+}
+<ATTR_W_VENDOR>\n                                      {
+    add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypted,has_tag);
+    g_free(attr_id);
+    g_free(attr_vendor);
+    g_free(attr_name);
+    linenums[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,strtol(yytext,NULL,10));  BEGIN OUT;}
-<VALUE_W_NAME>0x[0-9a-f]+                      { add_value(attr_name,value_repr,strtol(yytext,NULL,16));  BEGIN OUT;}
+<VALUE_W_NAME>[0-9]+                           { add_value(attr_name,value_repr,strtol(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,strtol(yytext,NULL,16));  g_free(attr_name); g_free(value_repr); BEGIN WS_OUT;}
 
 <INCLUDE>[^[:blank:]\n]+   {
        if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
-               g_string_sprintfa(error, "$INCLUDE files nested to deeply\n");
+               g_string_append_printf(error, "$INCLUDE files nested to deeply\n");
                yyterminate();
        }
-       
+
        include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
-       
-       fullpaths[include_stack_ptr] = g_strdup_printf("%s%c%s",directory,DIR_SEPARATOR,yytext);
 
-       yyin = fopen( fullpaths[include_stack_ptr], "r" );
-       
+       fullpaths[include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
+           directory,yytext);
+
+       yyin = ws_fopen( fullpaths[include_stack_ptr], "r" );
+
        if (!yyin) {
                if (errno) {
-                       g_string_sprintfa(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
+                       g_string_append_printf(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
                        yyterminate();
                }
        } else {
                linenums[include_stack_ptr] = 1;
                yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
        }
-       
 
-       BEGIN OUT;
+
+       BEGIN WS_OUT;
 }
 
 <<EOF>> {
-       
+
+       fclose(yyin);
+       yyin = NULL;
+
        if ( --include_stack_ptr < 0 ) {
                yyterminate();
        } else {
                g_free(fullpaths[include_stack_ptr+1]);
                fullpaths[include_stack_ptr+1] = NULL;
-               
+
                yy_delete_buffer( YY_CURRENT_BUFFER );
                yy_switch_to_buffer(include_stack[include_stack_ptr]);
        }
 
-       BEGIN OUT;
+       BEGIN WS_OUT;
 }
 
-\n     { linenums[include_stack_ptr]++; BEGIN OUT; }
+\n     { linenums[include_stack_ptr]++; BEGIN WS_OUT; }
 
 
 %%
 
-void add_vendor(gchar* name, guint32 vendor_id) {
-       radius_vendor_info_t* v = g_malloc(sizeof(radius_vendor_info_t));
-       
-       v->name = name;
-       v->code = vendor_id;
-       v->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
-       
+void add_vendor(const gchar* name, guint32 vendor_id) {
+       radius_vendor_info_t* v;
+
+       v=g_hash_table_lookup(dict->vendors_by_id, GUINT_TO_POINTER(vendor_id));
+
+       if (!v) {
+               v = g_malloc(sizeof(radius_vendor_info_t));
+               v->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
+               v->code = vendor_id;
+               v->ett = -1;
+               v->name = NULL;
+       }
+
+       if (v->name)
+               g_free((gpointer) v->name);
+       v->name = g_strdup(name);
+
        g_hash_table_insert(dict->vendors_by_id,GUINT_TO_POINTER(v->code),v);
-       g_hash_table_insert(dict->vendors_by_name,v->name,v);
+       g_hash_table_insert(dict->vendors_by_name, (gpointer) v->name, v);
 }
 
-void add_attribute(gchar* name, gchar* code, radius_attr_dissector_t type, gchar* vendor_name, gboolean crypt, gboolean tagged) {
-       radius_attr_info_t* a = g_malloc(sizeof(radius_attr_info_t));
+void add_attribute(const gchar* name, const  gchar* codestr, radius_attr_dissector_t type, const  gchar* vendor_name, gboolean crypt, gboolean tagged) {
+       radius_attr_info_t* a;
        GHashTable* by_id;
-       
+       guint32 code;
+
        if (vendor_name) {
                radius_vendor_info_t* v;
                v = g_hash_table_lookup(dict->vendors_by_name,vendor_name);
-               
+
                if (! v) {
-                       g_string_sprintfa(error, "Vendor: '%s', does not exist in %s:%i \n", vendor_name, fullpaths[include_stack_ptr], linenums[include_stack_ptr] );
-                       g_free(name);
-                       g_free(code);
-                       g_free(vendor_name);
+                       g_string_append_printf(error, "Vendor: '%s', does not exist in %s:%i \n", vendor_name, fullpaths[include_stack_ptr], linenums[include_stack_ptr] );
                        BEGIN JUNK;
                        return;
                } else {
@@ -198,36 +278,48 @@ void add_attribute(gchar* name, gchar* code, radius_attr_dissector_t type, gchar
        } else {
                by_id = dict->attrs_by_id;
        }
-       
-       a->name = name;
-       a->code = strtol(code,NULL,10); g_free(code);
+
+       code=strtol(codestr, NULL, 10);
+
+       a=g_hash_table_lookup(by_id, GUINT_TO_POINTER(code));
+
+       if (!a) {
+               a = g_malloc(sizeof(radius_attr_info_t));
+               a->name = NULL;
+               a->dissector = NULL;
+       }
+
+       a->code = code;
        a->encrypt = crypt;
        a->tagged =  tagged;
        a->type = type;
-       a->dissector = NULL;
        a->vs = NULL;
        a->hf = -1;
        a->hf64 = -1;
        a->hf_tag = -1;
        a->hf_len = -1;
        a->ett = -1;
-       
-       g_hash_table_insert(by_id,GUINT_TO_POINTER(a->code),a);
-       g_hash_table_insert(dict->attrs_by_name,a->name,a);
+
+       if (a->name)
+               g_free((gpointer) a->name);
+       a->name = g_strdup(name);
+
+       g_hash_table_insert(by_id, GUINT_TO_POINTER(code),a);
+       g_hash_table_insert(dict->attrs_by_name,(gpointer) (a->name),a);
 }
 
-void add_value(gchar* attrib_name, gchar* value_repr, long value) {
+void add_value(const gchar* attrib_name, const gchar* value_repr, long value) {
        value_string v;
        GArray* a = g_hash_table_lookup(value_strings,attrib_name);
-       
+
        if (! a) {
                a = g_array_new(TRUE,TRUE,sizeof(value_string));
-               g_hash_table_insert(value_strings,attrib_name,a);
+               g_hash_table_insert(value_strings,g_strdup(attrib_name),a);
        }
-       
+
        v.value = value;
-       v.strptr = value_repr;
-       
+       v.strptr = g_strdup(value_repr);
+
        g_array_append_val(a,v);
 }
 
@@ -235,12 +327,12 @@ void add_value(gchar* attrib_name, gchar* value_repr, long value) {
 static void setup_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
        radius_attr_info_t* a = v;
        gpointer key;
-       
+
        union {
                GArray* a;
                gpointer p;
        } vs;
-       
+
        if (g_hash_table_lookup_extended(value_strings,a->name,&key,&vs.p) ) {
                a->vs = (value_string*) vs.a->data;
                g_array_free(vs.a,FALSE);
@@ -251,21 +343,28 @@ static void setup_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
 
 static void setup_vendors(gpointer k _U_, gpointer v, gpointer p) {
        radius_vendor_info_t* vnd = v;
-       
-       g_hash_table_foreach(vnd->attrs_by_id,setup_attrs,p);   
+
+       g_hash_table_foreach(vnd->attrs_by_id,setup_attrs,p);
 }
 
-static gboolean destroy_values(gpointer k, gpointer v, gpointer p _U_) {
+static gboolean destroy_value_strings(gpointer k, gpointer v, gpointer p _U_) {
+    value_string* vs = (value_string*)(((GArray*)v)->data);
+
        g_free(k);
-       g_array_free(v,FALSE);
+
+    for (;vs->strptr;vs++) {
+        g_free((void*)vs->strptr);
+    }
+
+       g_array_free(v,TRUE);
        return TRUE;
 }
 
 static gboolean destroy_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
        radius_attr_info_t* a = v;
        int i;
-       
-       g_free(a->name);
+
+       g_free((gpointer) (a->name));
        if (a->vs) {
                for(i=0; a->vs[i].strptr; i++) {
                        g_free((void *)a->vs[i].strptr);
@@ -278,7 +377,7 @@ static gboolean destroy_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
 
 static gboolean destroy_vendors(gpointer k _U_, gpointer v, gpointer p) {
        radius_vendor_info_t* vnd = v;
-       g_free(vnd->name);
+       g_free( (gpointer) vnd->name);
        g_hash_table_foreach_remove(vnd->attrs_by_id,destroy_attrs,p);
        g_hash_table_destroy(vnd->attrs_by_id);
        g_free(vnd);
@@ -287,7 +386,7 @@ static gboolean destroy_vendors(gpointer k _U_, gpointer v, gpointer p) {
 
 static void destroy_dict(radius_dictionary_t* d) {
        g_hash_table_foreach_remove(d->attrs_by_id,destroy_attrs,NULL);
-       g_hash_table_foreach_remove(d->vendors_by_id,destroy_vendors,NULL);     
+       g_hash_table_foreach_remove(d->vendors_by_id,destroy_vendors,NULL);
        g_hash_table_destroy(d->vendors_by_id);
        g_hash_table_destroy(d->attrs_by_id);
        g_hash_table_destroy(d->vendors_by_name);
@@ -295,53 +394,63 @@ static void destroy_dict(radius_dictionary_t* d) {
        g_free(d);
 }
 
-radius_dictionary_t* radius_load_dictionary (gchar* dir, gchar* filename, gchar** err_str) {
+gboolean radius_load_dictionary (radius_dictionary_t* d, gchar* dir, const gchar* filename, gchar** err_str) {
        int i;
-       
+
+       dict = d;
        directory = dir;
-       
-       fullpaths[include_stack_ptr] = g_strdup_printf("%s%c%s",directory,DIR_SEPARATOR,filename);
-       
+
+       fullpaths[include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
+           directory,filename);
+
        error = g_string_new("");
 
-       yyin = fopen(fullpaths[include_stack_ptr],"r");
-       
+       yyin = ws_fopen(fullpaths[include_stack_ptr],"r");
+
        if (!yyin) {
-               g_string_sprintfa(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
+               g_string_append_printf(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
                g_free(fullpaths[include_stack_ptr]);
                *err_str = error->str;
                g_string_free(error,FALSE);
-               return NULL;
+               return FALSE;
        }
 
-       dict = g_malloc(sizeof(radius_dictionary_t));
-       dict->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
-       dict->attrs_by_name = g_hash_table_new(g_str_hash,g_str_equal);
-       dict->vendors_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
-       dict->vendors_by_name = g_hash_table_new(g_str_hash,g_str_equal);
-       
        value_strings = g_hash_table_new(g_str_hash,g_str_equal);
-       
-       BEGIN OUT;
+
+       BEGIN WS_OUT;
 
        yylex();
 
+       if (yyin != NULL) fclose(yyin);
+       yyin = NULL;
+
        for (i=0; i < 10; i++) {
                if (fullpaths[i]) g_free(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_values,NULL);
-       
+       g_hash_table_foreach(dict->vendors_by_id,setup_vendors,NULL);
+       g_hash_table_foreach_remove(value_strings,destroy_value_strings,NULL);
+
        if (error->len > 0) {
                 *err_str = error->str;
                g_string_free(error,FALSE);
                destroy_dict(dict);
-               return NULL;
+               return FALSE;
        } else {
                *err_str = NULL;
                g_string_free(error,TRUE);
-               return dict;
+               return TRUE;
        }
 }
+
+/*
+ * 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).
+ */
+
+int yywrap(void) {
+    return 1;
+}