check in new directory for the files for autogenerating dcerpc interfaces
authorsahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 4 Feb 2005 04:37:47 +0000 (04:37 +0000)
committersahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 4 Feb 2005 04:37:47 +0000 (04:37 +0000)
and the prototype idl compiler.

this is not ready for wide use yet but is useful with a svn area where we can sync our changes to the compiler.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@13280 f5534014-38df-0310-8fa8-9805f1628bb7

epan/dissectors/dcerpc/idl2eth.c [new file with mode: 0644]

diff --git a/epan/dissectors/dcerpc/idl2eth.c b/epan/dissectors/dcerpc/idl2eth.c
new file mode 100644 (file)
index 0000000..a895736
--- /dev/null
@@ -0,0 +1,3086 @@
+/* 
+TODO
+   check that every cnf defined type,hffield,rename,... has been referenced
+   at least once and if not,   abort with an error
+
+   need to distinguish between NTTIME (absolute time) and relative time 
+
+   prune_xxx should only act inside of '[' ']'
+
+   add support for bool8,16,32,64 with tfs strings
+
+   add the remaining array type  (uvarray)
+
+   add code to verify that union tag length is correct
+*/
+/* All field dissectors that call a normal type 
+   (i.e. not a pointer, not an array)
+   has a local variable  guint param declared which is passed on to the
+   type dissector.
+   The default value is 0 but the PARAM_VALUE conformance tag can be used to
+   change it.
+   This is only meaningful if the called type dissector actually does anything
+   with this parameter.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+FILE *fh, *tfh, *eth_code, *eth_hdr, *eth_hf, *eth_hfarr, *eth_ett, *eth_ettarr, *eth_ft, *eth_handoff;
+char *uuid=NULL;
+char *version=NULL;
+char *pointer_default=NULL;
+char *ifname=NULL;
+char hf_status[256];
+int lineno,linepos;
+char line[1024];
+
+
+#define FPRINTF(fh, ...) \
+       {\
+               fprintf(stderr, __VA_ARGS__ );\
+               if(fh)fprintf(fh, __VA_ARGS__ );\
+       }
+
+
+typedef struct _pointer_item_t {
+       struct _pointer_item_t *next;
+       char *type;
+} pointer_item_t;
+
+#define BI_CASE                        0x00000001
+#define BI_CASE_DEFAULT                0x00000002
+#define BI_IN                  0x00000004
+#define BI_OUT                 0x00000008
+#define BI_SIZE_IS             0x00000010
+#define BI_LENGTH_IS           0x00000020
+#define BI_POINTER             0x00000040
+#define BI_BITMAP32            0x00000100
+typedef struct _bracket_item_t {
+       long int flags;
+       char *case_name;
+       pointer_item_t *pointer_list;
+} bracket_item_t;
+
+typedef struct _no_emit_item_t {
+       struct _no_emit_item_t *next;
+       char *name;
+} no_emit_item_t;
+no_emit_item_t *no_emit_list=NULL;
+
+typedef struct _hf_rename_item_t {
+       struct _hf_rename_item_t *next;
+       char *old_name;
+       char *new_name;
+} hf_rename_item_t;
+hf_rename_item_t *hf_rename_list=NULL;
+
+typedef struct _enum_list_t {
+       struct _enum_list_t *next;
+       char *name;
+       int val;
+} enum_list_t;
+
+
+typedef struct _token_item_t {
+       struct _token_item_t *next;
+       char *str;
+} token_item_t;
+token_item_t *token_list=NULL;
+token_item_t *last_token_item=NULL;
+
+
+typedef struct _type_item_t {
+       struct _type_item_t *next;
+       char *name;
+       char *dissector;
+       char *ft_type;
+       char *base_type;
+       char *mask;
+       char *vals;
+       int alignment;
+} type_item_t;
+type_item_t *type_list=NULL;
+
+typedef struct _union_tag_size_item_t {
+       struct _union_tag_size_item_t *next;
+       char *name;
+       int size;
+} union_tag_size_item_t;
+union_tag_size_item_t *union_tag_size_list=NULL;
+
+typedef struct _hf_field_item_t {
+       struct _hf_field_item_t *next;
+       char *name;
+       char *ft_type;
+} hf_field_item_t;
+hf_field_item_t *hf_field_list=NULL;
+
+typedef struct _dissector_param_value_t {
+       struct _dissector_param_value_t *next;
+       char *name;
+       char *value;
+} dissector_param_value_t;
+dissector_param_value_t *dissector_param_list=NULL;
+
+void
+register_dissector_param_value(char *name, char *value)
+{
+       dissector_param_value_t *dpv;
+       dpv=malloc(sizeof(dissector_param_value_t));
+       dpv->next=dissector_param_list;
+       dissector_param_list=dpv;
+       dpv->name=strdup(name);
+       dpv->value=strdup(value);
+}
+
+char *
+find_dissector_param_value(char *name)
+{
+       dissector_param_value_t *dpv;
+       for(dpv=dissector_param_list;dpv;dpv=dpv->next){
+               if(!strcmp(name,dpv->name)){
+                       return dpv->value;
+               }
+       }
+       return "0";
+}
+
+pointer_item_t *
+prepend_pointer_list(pointer_item_t *ptrs, int num_pointers)
+{
+       pointer_item_t *pi;
+
+       pi=ptrs;
+       while(pi){
+               if(num_pointers)num_pointers--;
+               pi=pi->next;
+       }
+       if(!pi)pi=ptrs;
+       while(num_pointers--){
+               pi=malloc(sizeof(pointer_item_t));
+               pi->next=ptrs;
+               pi->type=pointer_default;
+               ptrs=pi;
+       }
+       ptrs=pi;
+
+       return ptrs;
+}
+
+char *
+ptr_to_define(char *pointer_type)
+{
+       if(!strcmp(pointer_type, "unique")){
+               return "NDR_POINTER_UNIQUE";
+       } else if(!strcmp(pointer_type, "ref")){
+               return "NDR_POINTER_REF";
+       } else if(!strcmp(pointer_type, "ptr")){
+               return "NDR_POINTER_PTR";
+       }
+
+       fprintf(stderr, "prt_to_define,     weirdo pointer :%s\n", pointer_type);
+       exit(10);
+}
+
+int
+get_union_tag_size(char *name)
+{
+       union_tag_size_item_t *utsi;
+       for(utsi=union_tag_size_list;utsi;utsi=utsi->next){
+               if(!strcmp(name, utsi->name)){
+                       return utsi->size;
+               }
+       }
+       fprintf(stderr, "ERROR: size of tag for union:%s is not known\n", name);
+       fprintf(stderr, "  use the UNION_TAG_SIZE directive to specify it in teh conformance file\n", name);
+       exit(10);
+}
+
+
+/* this function will add an entry to the hf_rename list */
+void
+register_hf_rename(char *old_name, char *new_name)
+{
+       hf_rename_item_t *new_item;
+       new_item=malloc(sizeof(hf_rename_item_t));
+       new_item->next=hf_rename_list;
+       hf_rename_list=new_item;
+       new_item->old_name=strdup(old_name);
+       new_item->new_name=strdup(new_name);
+}
+
+hf_field_item_t *
+find_hf_field(char *name)
+{
+       hf_field_item_t *hfi;
+
+       for(hfi=hf_field_list;hfi;hfi=hfi->next){
+               if(!strcmp(hfi->name, name)){
+                       return hfi;
+               }
+       }
+       fprintf(stderr, "find_hf_field:  unknown hf_field:%s\n",name);
+       Exit(10);
+}
+
+
+/* this function will create the code required for a hf field.
+   it MIGTH rename the field so a user MUST use the name returned
+   from this function.
+   for fields that are to be renamed  no code is generated
+*/
+char *
+register_hf_field(char *hf_name, char *title, char *filter_name, char *ft_type, char *base_type, char *valsstring, char *mask, char *blurb)
+{
+       hf_field_item_t *hfi;
+       hf_rename_item_t *hri;
+
+       /* dont generate code for renamed hf fields  just return the new name*/
+       for(hri=hf_rename_list;hri;hri=hri->next){
+               if(!strcmp(hf_name, hri->old_name)){
+                       hfi=find_hf_field(hri->new_name);
+                       if(strcmp(ft_type, hfi->ft_type)){
+                               fprintf(stderr, "register_hf_field:  hf_fields %s and %s have different types %s %s\n",hf_name,hfi->name,ft_type,hfi->ft_type);
+                               Exit(10);
+                       }
+                       return hri->new_name;
+               }
+       }
+
+       hfi=malloc(sizeof(hf_field_item_t));
+       hfi->next=hf_field_list;
+       hf_field_list=hfi;
+       hfi->name=strdup(hf_name);
+       hfi->ft_type=strdup(ft_type);
+
+       FPRINTF(eth_hf, "static int %s = -1;\n", hf_name);
+       FPRINTF(eth_hfarr, "        { &%s,\n", hf_name);
+       FPRINTF(eth_hfarr, "          { \"%s\", \"%s\", %s, %s,\n", title, filter_name, ft_type, base_type);
+       FPRINTF(eth_hfarr, "          %s, %s,\n", valsstring, mask);
+       FPRINTF(eth_hfarr, "         \"%s\", HFILL }},\n", blurb);
+       FPRINTF(eth_hfarr, "\n");
+
+       return hf_name;
+}
+
+/* this function will parse the no emit list and decide whether code should 
+   be generated for this dissector or if we should only register the type.
+*/
+int
+check_if_to_emit(char *name)
+{
+       no_emit_item_t *nel;
+
+       for(nel=no_emit_list;nel;nel=nel->next){
+               if(!strcmp(name, nel->name)){
+                       FPRINTF(NULL, "SKIPPED emitting of %s\n",name);
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+
+void
+prune_keywords(char *name)
+{
+       token_item_t *ti, *prevti;
+
+       for(ti=token_list;ti;ti=ti->next){
+               if(!ti->next){
+                       break;
+               }
+               if(!strcmp(ti->next->str, name)){
+                       if(!strcmp(ti->next->next->str, ",")){
+                               ti->next=ti->next->next->next;
+                       } else {
+                               ti->next=ti->next->next;
+                       }
+               }
+       }
+}
+void
+rename_tokens(char *old_name, char *new_name)
+{
+       token_item_t *ti;
+
+       for(ti=token_list;ti;ti=ti->next){
+               if(!strcmp(ti->str, old_name)){
+                       ti->str=strdup(new_name);
+               }
+       }
+}
+
+void
+prune_keyword_parameters(char *name)
+{
+       token_item_t *ti, *tmpti;
+
+       for(ti=token_list;ti;ti=ti->next){
+               if(!strcmp(ti->str, name)){
+                       if(!strcmp(ti->next->str, "(")){
+                               tmpti=ti;
+                               while(1){
+                                       if(!strcmp(tmpti->str, ")")){
+                                               ti->next=tmpti->next;
+                                               break;
+                                       }
+                                       tmpti=tmpti->next;
+                               }
+                       }
+               }
+       }
+}
+
+/* this function will parse a bracket item
+       [ ... ]
+   it will return the token of the next item following the ']'
+*/
+token_item_t *
+parsebrackets(token_item_t *ti, bracket_item_t **bracket){
+       bracket_item_t *br;
+
+       if(strcmp(ti->str, "[")){
+               fprintf(stderr, "ERROR: parsebrackets first token is not '['\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       br=malloc(sizeof(bracket_item_t));
+       *bracket=br;
+       br->flags=0;
+       br->case_name=NULL;
+       br->pointer_list=NULL;
+
+       while(ti){
+               if( !strcmp(ti->str, "{")
+                 ||!strcmp(ti->str, "}")){
+                       fprintf(stderr, "ERROR: parsebrackets '{' '}' inside bracket item\n");
+                       Exit(10);
+               }
+
+               if(!strcmp(ti->str, "[")){
+                       fprintf(stderr, "ERROR: parsebrackets '[' inside bracket item\n");
+                       Exit(10);
+               }
+
+               /* finished */
+               if(!strcmp(ti->str, "]")){
+                       /* check for [ ... ] [ ...] */
+                       ti=ti->next;
+
+                       if(!strcmp(ti->str, "[")){
+                               ti=ti->next;
+                               continue;
+                       }
+                       return ti;
+               }
+
+               /* just ignore all ',' */
+               if(!strcmp(ti->str, ",")){
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* case '(' tag ')' */
+               if(!strcmp(ti->str, "case")){
+                       br->flags|=BI_CASE;
+                       ti=ti->next;
+
+                       if(strcmp(ti->str, "(")){
+                               fprintf(stderr, "ERROR: parsebrackets case not followed by '('\n");
+                               Exit(10);
+                       }
+                       ti=ti->next;
+
+                       /* name */
+                       br->case_name=ti->str;
+                       ti=ti->next;
+
+                       if(strcmp(ti->str, ")")){
+                               fprintf(stderr, "ERROR: parsebrackets case does not end with ')'\n");
+                               Exit(10);
+                       }
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* default */
+               if(!strcmp(ti->str, "default")){
+                       br->flags|=BI_CASE;
+                       br->flags|=BI_CASE_DEFAULT;
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* in */
+               if(!strcmp(ti->str, "in")){
+                       br->flags|=BI_IN;
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* out */
+               if(!strcmp(ti->str, "out")){
+                       br->flags|=BI_OUT;
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* public : we dont care about this one */
+               if(!strcmp(ti->str, "public")){
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* switch_is */
+               if(!strcmp(ti->str, "switch_is")){
+                       fprintf(stderr, "WARNING: parsebrackets can not handle switch_is properly yet  so we can not verify the tag size\n");
+                       while(ti){
+                               if(!strcmp(ti->str, ")")){
+                                       ti=ti->next;
+                                       break;
+                               }
+                               ti=ti->next;
+                       }
+                       continue;
+               }
+
+               /* switch_is */
+               if(!strcmp(ti->str, "subcontext")){
+                       while(ti){
+                               if(!strcmp(ti->str, ")")){
+                                       ti=ti->next;
+                                       break;
+                               }
+                               ti=ti->next;
+                       }
+                       continue;
+               }
+
+               /* value   we dont care about this one so just skip it */
+               if(!strcmp(ti->str, "value")){
+                       int level;
+                       ti=ti->next;
+                       if( strcmp(ti->str, "(") ){
+                               fprintf(stderr, "WARNING: parsebrackets value was not followed by '('\n");
+                               Exit(10);
+                       }
+                       level=0;
+                       while(ti){
+                               if(!strcmp(ti->str, "(")){
+                                       ti=ti->next;
+                                       level++;
+                                       continue;
+                               }
+                               if(!strcmp(ti->str, ")")){
+                                       ti=ti->next;
+                                       level--;
+                                       if(level){
+                                               continue;
+                                       }
+                                       break;
+                               }
+                               ti=ti->next;
+                       }
+                       continue;
+               }
+
+               /* range   we dont care about this one so just skip it */
+               if(!strcmp(ti->str, "range")){
+                       int level;
+                       ti=ti->next;
+                       if( strcmp(ti->str, "(") ){
+                               fprintf(stderr, "WARNING: parsebrackets range was not followed by '('\n");
+                               Exit(10);
+                       }
+                       level=0;
+                       while(ti){
+                               if(!strcmp(ti->str, "(")){
+                                       ti=ti->next;
+                                       level++;
+                                       continue;
+                               }
+                               if(!strcmp(ti->str, ")")){
+                                       ti=ti->next;
+                                       level--;
+                                       if(level){
+                                               continue;
+                                       }
+                                       break;
+                               }
+                               ti=ti->next;
+                       }
+                       continue;
+               }
+
+               /* flag   we dont care about this one so just skip it */
+               if(!strcmp(ti->str, "flag")){
+                       int level;
+                       ti=ti->next;
+                       if( strcmp(ti->str, "(") ){
+                               fprintf(stderr, "WARNING: parsebrackets flag was not followed by '('\n");
+                               Exit(10);
+                       }
+                       level=0;
+                       while(ti){
+                               if(!strcmp(ti->str, "(")){
+                                       ti=ti->next;
+                                       level++;
+                                       continue;
+                               }
+                               if(!strcmp(ti->str, ")")){
+                                       ti=ti->next;
+                                       level--;
+                                       if(level){
+                                               continue;
+                                       }
+                                       break;
+                               }
+                               ti=ti->next;
+                       }
+                       continue;
+               }
+
+               /* size_is */
+               if(!strcmp(ti->str, "size_is")){
+                       br->flags|=BI_SIZE_IS;
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* length_is */
+               if(!strcmp(ti->str, "length_is")){
+                       br->flags|=BI_LENGTH_IS;
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* bitmap32bit */
+               if(!strcmp(ti->str, "bitmap32bit")){
+                       br->flags|=BI_BITMAP32;
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* ref, unique or ptr */
+               if(!strcmp(ti->str, "ref")
+               || !strcmp(ti->str, "unique")
+               || !strcmp(ti->str, "ptr")){
+                       pointer_item_t *newpi;
+
+                       br->flags|=BI_POINTER;
+                       newpi=malloc(sizeof(pointer_item_t));
+                       newpi->next=NULL;
+                       newpi->type=ti->str;
+                       newpi->next=br->pointer_list;
+                       br->pointer_list=newpi;
+                       ti=ti->next;
+                       continue;
+               }
+
+               fprintf(stderr, "ERROR: parsebrackets should not be reached  unknown tag:%s\n", ti->str);
+               Exit(10);
+       }
+}
+                       
+/* this function will register a new type learnt from the IDL file
+*/
+static type_item_t * 
+register_new_type(char *name, char *dissectorname, char *ft_type, char *base_type, char *mask, char *valsstring, int alignment){
+       type_item_t *new_type;
+
+FPRINTF(NULL,"XXX new type:%s dissector:%s Type:%s Base:%s Mask:%s Vals:%s alignment:%d\n", name, dissectorname, ft_type, base_type, mask, valsstring, alignment);
+
+       new_type=malloc(sizeof(type_item_t));
+       new_type->next=type_list;
+       new_type->name=strdup(name);
+       new_type->dissector=strdup(dissectorname);
+       new_type->ft_type=strdup(ft_type);
+       new_type->base_type=strdup(base_type);
+       new_type->mask=strdup(mask);
+       new_type->vals=strdup(valsstring);
+       new_type->alignment=alignment;
+       type_list=new_type;
+
+       return new_type;
+}
+
+
+/* this function will print the remaining content of the token list
+*/
+void printtokenlist(int count)
+{
+       token_item_t *ti;
+       fprintf(stderr, "TOKENLIST:\n");
+       for(ti=token_list;ti&&count;count--,ti=ti->next){
+               fprintf(stderr, "Token \"%s\"\n",ti->str);
+       }
+       if(!count){
+               fprintf(stderr, "    ...\n");
+       }
+}
+
+
+/* this function will parse the header and pick up the fields
+ * we are interested in.
+ * the header is supposed to start at the very first token and look like
+ * [ <fields> ] inteface <ifname> {
+ *
+ * we are interested in the fields:
+ *     uuid
+ *     version
+ *     pointer_default
+ *
+ * this function will also remove the header from the token list
+ */
+void parseheader(void)
+{
+       char filter_name[256];
+       token_item_t *ti;
+       int level=0;
+       int major, minor;
+
+       ti=token_list;
+       if(!ti){
+               fprintf(stderr, "ERRO: no tokens\n");
+               Exit(10);
+       }
+
+       /* first token must be '[' */
+       if( strcmp(ti->str, "[") ){
+               fprintf(stderr, "ERROR: first token is not '['\n");
+               Exit(10);
+       }
+
+       for(ti=token_list;ti;ti=ti->next){
+               if( !strcmp(ti->str, "[")){
+                       level++;
+                       continue;
+               }
+               if( !strcmp(ti->str, "]")){
+                       level--;
+                       if(!level){
+                               token_list=ti->next;
+                               break;
+                       }
+               }
+               if(level==1){
+                       if( !strcmp(ti->str, "uuid")){
+                               uuid=ti->next->next->str;
+                               FPRINTF(NULL,"UUID:%s\n",uuid);
+                       }
+                       if( !strcmp(ti->str, "version")){
+                               version=ti->next->next->str;
+                               FPRINTF(NULL,"VERSION:%s\n",version);
+                       }
+                       if( !strcmp(ti->str, "pointer_default")){
+                               if(!strcmp(ti->next->next->str, "unique")){
+                                       pointer_default="unique";
+                               } else if(!strcmp(ti->next->next->str, "ptr")){
+                                       pointer_default="ptr";
+                               } else {
+                                       fprintf(stderr, "ERROR: unknown pointer type\n");
+                                       Exit(10);
+                               }
+                               FPRINTF(NULL,"POINTER_DEFAULT:%s\n",pointer_default);
+                       }
+               }
+       }
+       if(!token_list){
+               fprintf(stderr, "ERROR: ran outof tokens inside header\n");
+               Exit(10);
+       }
+       /* interface */
+       if(strcmp(token_list->str, "interface")){
+               fprintf(stderr, "ERROR: interface not found\n");
+               Exit(10);
+       }
+       token_list=token_list->next;
+       /* interface name */
+       ifname=token_list->str;
+       token_list=token_list->next;
+       FPRINTF(NULL,"Interface:%s\n",ifname);
+
+       /* opnum */
+       sprintf(hf_status, "hf_%s_opnum", ifname);
+       sprintf(filter_name, "%s.opnum", ifname);
+       register_hf_field(hf_status, "Operation", filter_name, "FT_UINT16", "BASE_DEC", "NULL", "0", "");
+
+       /* status */
+       sprintf(hf_status, "hf_%s_rc", ifname);
+       sprintf(filter_name, "%s.rc", ifname);
+       register_hf_field(hf_status, "Return code", filter_name, "FT_UINT32", "BASE_HEX", "VALS(NT_errors)", "0", "");
+
+       FPRINTF(eth_ett, "static gint ett_%s = -1;\n", ifname);
+       FPRINTF(eth_ettarr, "        &ett_%s,\n", ifname);
+
+       /* the body must start with { */
+       if(strcmp(token_list->str, "{")){
+               fprintf(stderr, "ERROR: body does not start with '{'\n");
+               Exit(10);
+       }
+
+       /* skip the initial '{' */
+       token_list=token_list->next;
+
+       if(!uuid){
+               fprintf(stderr, "ERROR: no uuid found\n");
+               Exit(10);
+       }
+       FPRINTF(eth_code,"static e_uuid_t uuid_dcerpc_%s = {\n", ifname);
+       FPRINTF(eth_code,"    0x%c%c%c%c%c%c%c%c, 0x%c%c%c%c, 0x%c%c%c%c,\n",uuid[1],uuid[2],uuid[3],uuid[4],uuid[5],uuid[6],uuid[7],uuid[8],uuid[10],uuid[11],uuid[12],uuid[13],uuid[15],uuid[16],uuid[17],uuid[18]);
+       FPRINTF(eth_code,"    { 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c}\n",uuid[20],uuid[21],uuid[22],uuid[23],uuid[25],uuid[26],uuid[27],uuid[28],uuid[29],uuid[30],uuid[31],uuid[32],uuid[33],uuid[34],uuid[35],uuid[36]);
+       FPRINTF(eth_code,"};\n");
+       FPRINTF(eth_code,"\n");
+
+       sscanf(version, "%d.%d", &major, &minor);
+       FPRINTF(eth_code,"static guint16 ver_%s = %d;\n", ifname, major);
+       FPRINTF(eth_code,"\n");
+
+       FPRINTF(eth_handoff, "    dcerpc_init_uuid(proto_%s, ett_%s,\n", ifname, ifname);
+       FPRINTF(eth_handoff, "        &uuid_dcerpc_%s, ver_%s,\n", ifname, ifname);
+       FPRINTF(eth_handoff, "        function_dissectors, hf_%s_opnum);\n", ifname);
+}
+
+
+
+/* this helper function is called by the tokenizer and will just append the 
+   current token to the linked list
+*/
+void pushtoken(char *token)
+{
+       token_item_t *new_token_item;
+       new_token_item=malloc(sizeof(token_item_t));
+       new_token_item->next=NULL;
+       new_token_item->str=token;
+       if(!token_list){
+               token_list=new_token_item;
+       } else {
+               last_token_item->next=new_token_item;
+       }
+       last_token_item=new_token_item;
+}
+
+/* this function reads the idl file and translates it into tokens.
+   the tokens are stored in a linked list  token_list of type token_item_t
+*/
+void tokenize(void)
+{
+       int ch;
+       int fullinecomment=0;
+       int normalcomment=0;
+       int insidequote=0;
+       char qs[1024];
+       int qspos;
+       int insidetoken=0;
+       char token[1024];
+       int tokenpos;
+
+       while(!feof(fh)){
+               ch=fgetc(fh);
+
+               /* full line comment */
+               if(fullinecomment){
+                       if( (ch=='\n')||(ch=='\r') ){
+                               fullinecomment=0;
+                               linepos=0;
+                       }
+                       continue;
+               }
+               if( (ch=='#')&&(linepos==0) ){
+                       fullinecomment=1;
+                       continue;
+               }
+
+               /* normal comment */
+               if(normalcomment==0){
+                       if(ch=='/'){
+                               int nextch;
+                               nextch=fgetc(fh);
+                               if(nextch=='*'){
+                                       normalcomment=1;
+                                       continue;
+                               } 
+                               ungetc(nextch, fh);
+                       }
+               } else {
+                       if(ch=='*'){
+                               int nextch;
+                               nextch=fgetc(fh);
+                               if(nextch=='/'){
+                                       normalcomment=0;
+                                       continue;
+                               } 
+                               ungetc(nextch, fh);
+                       }
+                       continue;
+               }
+
+               /* quoted string */
+               if(insidequote){
+                       if(ch=='"'){
+                               insidequote=0;
+                               qs[qspos++]='"';
+                               qs[qspos]=0;
+                               pushtoken(strdup(qs));
+                               continue;
+                       } else {
+                               qs[qspos++]=(char)ch;
+                               continue;
+                       }
+               } else {
+                       if(ch=='"'){
+                               insidequote=1;
+                               qs[0]='"';
+                               qspos=1;
+                               continue;
+                       }
+               }
+
+
+               switch(ch){
+               case '\n':
+               case '\r':
+                       if(insidetoken){
+                               insidetoken=0;
+                               token[tokenpos]=0;
+                               pushtoken(strdup(token));
+                       }
+                       line[linepos]=0;
+/*printf("line %d [%s]\n",lineno,line);*/
+                       linepos=0;
+                       lineno++;
+                       break;
+               case '\t':
+               case ' ':
+                       if(insidetoken){
+                               insidetoken=0;
+                               token[tokenpos]=0;
+                               pushtoken(strdup(token));
+                       }
+                       break;
+               case '[':
+               case ']':
+               case '(':
+               case ')':
+               case ',':
+               case ';':
+               case '*':
+               case '=':
+                       if(insidetoken){
+                               insidetoken=0;
+                               token[tokenpos]=0;
+                               pushtoken(strdup(token));
+                       }
+                       token[0]=(char)ch;
+                       token[1]=0;
+                       pushtoken(strdup(token));
+                       break;
+               default:
+                       if(!insidetoken){
+                               tokenpos=0;
+                       }
+                       insidetoken=1;
+                       token[tokenpos++]=(char)ch;
+                       line[linepos++]=(char)ch;
+                       break;
+               }
+
+       }
+}
+
+
+static type_item_t *
+find_type(char *name)
+{
+       type_item_t *tmptype;
+       for(tmptype=type_list;tmptype;tmptype=tmptype->next){
+               if(!strcmp(tmptype->name, name)){
+                       break;
+               }
+       }
+       /* autogenerate built in types */
+       if(!tmptype){
+               char dissectorname[256];
+               if(!strcmp(name,"uint16")){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uint16(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("uint16", dissectorname, "FT_UINT16", "BASE_DEC", "0", "NULL", 2);
+               } else if(!strcmp(name,"int16")){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uint16(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("int16", dissectorname, "FT_INT16", "BASE_DEC", "0", "NULL", 2);
+               } else if(!strcmp(name,"uint32")){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("uint32", dissectorname, "FT_UINT32", "BASE_DEC", "0", "NULL", 4);
+               } else if( (!strcmp(name,"int32"))
+                       || (!strcmp(name,"long")) ){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("int32", dissectorname, "FT_INT32", "BASE_DEC", "0", "NULL", 4);
+                       tmptype=register_new_type("long", dissectorname, "FT_INT32", "BASE_DEC", "0", "NULL", 4);
+               } else if( (!strcmp(name,"uint8")) ){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uint8(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("uint8", dissectorname, "FT_UINT8", "BASE_DEC", "0", "NULL", 1);
+               } else if( (!strcmp(name,"int8"))
+                       || (!strcmp(name, "char")) ){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uint8(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("int8", dissectorname, "FT_INT8", "BASE_DEC", "0", "NULL", 1);
+                       tmptype=register_new_type("char", dissectorname, "FT_INT8", "BASE_DEC", "0", "NULL", 1);
+               } else if(!strcmp(name,"bool8")){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uint8(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("bool8", dissectorname, "FT_INT8", "BASE_DEC", "0", "NULL", 1);
+               } else if(!strcmp(name,"unistr")){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep, 2, hf_index, FALSE, NULL);\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("unistr", dissectorname, "FT_STRING", "BASE_DEC", "0", "NULL", 4);
+               } else if(!strcmp(name,"ascstr")){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep, 1, hf_index, FALSE, NULL);\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("ascstr", dissectorname, "FT_STRING", "BASE_DEC", "0", "NULL", 4);
+               } else if(!strcmp(name,"GUID")
+                       ||!strcmp(name,"uuid_t")){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uuid_t(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type(name, dissectorname, "FT_STRING", "BASE_NONE", "0", "NULL", 4);
+               } else if(!strcmp(name,"policy_handle")){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static e_ctx_hnd policy_hnd;\n");
+                       FPRINTF(eth_code, "static proto_item *hnd_item;\n");
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,\n");
+                       FPRINTF(eth_code, "                   hf_index, &policy_hnd, &hnd_item,\n");
+                       FPRINTF(eth_code, "                   param&0x01, param&0x02);\n");
+
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("policy_handle", dissectorname, "FT_BYTES", "BASE_NONE", "0", "NULL", 4);
+               } else if(!strcmp(name,"NTTIME")){
+                       /* 8 bytes, aligned to 4 bytes */
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep, hf_index);\n");
+
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("NTTIME", dissectorname, "FT_ABSOLUTE_TIME", "BASE_NONE", "0", "NULL", 4);
+               } else if(!strcmp(name,"NTTIME_hyper")){
+                       /* 8 bytes, aligned to 8 bytes */
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    ALIGN_TO_8_BYTES;\n");
+                       FPRINTF(eth_code, "    offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep, hf_index);\n");
+
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("NTTIME_hyper", dissectorname, "FT_ABSOLUTE_TIME", "BASE_NONE", "0", "NULL", 4);
+               } else if(!strcmp(name,"udlong")){
+                       /* 8 bytes, aligned to 4 bytes */
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_duint32(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("udlong", dissectorname, "FT_UINT64", "BASE_DEC", "0", "NULL", 4);
+               } else if(!strcmp(name,"dlong")){
+                       /* 8 bytes, aligned to 4 bytes */
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_duint32(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("dlong", dissectorname, "FT_INT64", "BASE_DEC", "0", "NULL", 4);
+               } else if(!strcmp(name,"uint64")){
+                       /* 8 bytes, aligned to 8 bytes */
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    \n");
+                       FPRINTF(eth_code, "    ALIGN_TO_8_BYTES;\n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uint64(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("uint64", dissectorname, "FT_UINT64", "BASE_DEC", "0", "NULL", 8);
+               } else if(!strcmp(name,"time_t")){
+                       sprintf(dissectorname, "%s_dissect_%s", ifname, name);
+                       FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    \n");
+                       FPRINTF(eth_code, "    offset=dissect_ndr_time_t(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+                       tmptype=register_new_type("time_t", dissectorname, "FT_ABSOLUTE_TIME", "BASE_DEC", "0", "NULL", 4);
+               }
+       }
+
+       return tmptype;
+}
+
+
+/* this function will skip past an entire declare ... ; statement */
+void skipdeclare(void)
+{
+       token_item_t *ti;
+
+       /* first must be the keyword const */
+       ti=token_list;
+       if(strcmp(ti->str, "declare")){
+               fprintf(stderr, "ERROR: skipdeclare  first token is not 'declare'\n");
+               Exit(10);
+       }
+       while(strcmp(ti->str, ";")){
+               ti=ti->next;
+       }
+       ti=ti->next;
+
+       token_list=ti;
+}
+
+/* this function will parse a
+       const
+   and generate the appropriate code
+   const must be followed by a suitable keyword [uint16|uint32|...]
+   the const will later be removed from the token list
+   the function assumes that the const is the first object in the token_list
+*/
+void parseconst(void)
+{
+       token_item_t *ti;
+       type_item_t *type_item;
+       char *name, *value;
+
+       /* first must be the keyword const */
+       ti=token_list;
+       if(strcmp(ti->str, "const")){
+               fprintf(stderr, "ERROR: const  first token is not 'const'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       /* just skip second token */            
+       ti=ti->next;
+
+       /* third is a variable and not a type */
+       if(find_type(ti->str)){
+               fprintf(stderr, "ERROR: const, not a variable name:%s\n", ti->str);
+               Exit(10);
+       }
+       name=ti->str;
+       ti=ti->next;
+       
+       /* fourth is '=' */
+       if(strcmp(ti->str, "=")){
+               fprintf(stderr, "ERROR: const  fourth token is not '='\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       /* fifth is the value */
+       value=ti->str;
+       ti=ti->next;
+
+       /* sixth is ';' */
+       if(strcmp(ti->str, ";")){
+               fprintf(stderr, "ERROR: const  sixth token is not ';'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       FPRINTF(NULL,"\nCONST:%s\n-------\n",name);
+
+       FPRINTF(eth_hdr, "#define %s            %s\n", name, value);
+
+       FPRINTF(NULL,"\n----------\nEND CONST:%s\n",name);
+
+       token_list=ti;
+}
+
+/* this function will parse a
+       typedef struct {
+   construct and generate the appropriate code.
+   the typedef will be removed from the token_list once it has been processed
+   the function assumes that the typedef is the first object in the token_list
+   the function will be called twice, once with pass=0 and once with pass=1
+   which controls whether subdissectors are to be generated or whether the 
+   struct dissector itself is to be generated 
+*/
+void parsetypedefstruct(int pass)
+{
+       token_item_t *ti, *tmpti;
+       char *struct_name;
+       char dissectorname[256];
+       char tmpstr[256], *ptmpstr;
+       int level, num_pointers;
+       static int alignment;
+       type_item_t *type_item;
+       char hf_index[256];
+       bracket_item_t *bi=NULL;
+       pointer_item_t *pi;
+       char *pointer_type;
+       char *field_name;
+       int fixed_array_size;
+       int is_array_of_pointers;
+
+       ti=token_list;
+       if(strcmp(ti->str, "typedef")){
+               fprintf(stderr, "ERROR: typedefstruct  first token is not 'typedef'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       if(!strcmp(ti->str, "[")){
+               ti=parsebrackets(ti, &bi);
+       }
+       /* check that we know how to handle the bracket thing */
+       if(bi){
+               if(bi->flags){
+                       fprintf(stderr, "ERROR: typedefstruct unknown bracket flags encountered : 0x%08x\n",bi->flags);
+                       Exit(10);
+               }
+       }
+
+       if(strcmp(ti->str, "struct")){
+               fprintf(stderr, "ERROR: typedefstruct  second token is not 'struct'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       if(strcmp(ti->str, "{")){
+               fprintf(stderr, "ERROR: typedefstruct  third token is not '{'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       /* search forward until the '}' so we can find the name of the struct */
+       for(tmpti=ti,level=0;tmpti;tmpti=tmpti->next){
+               if(!strcmp(tmpti->str, "{")){
+                       level++;
+                       continue;
+               }
+               if(!strcmp(tmpti->str, "}")){
+                       if(!level){
+                               break;
+                       }
+                       level--;
+                       continue;
+               }
+       }
+       struct_name=tmpti->next->str;
+       sprintf(dissectorname, "%s_dissect_%s", ifname, struct_name);
+
+       FPRINTF(NULL,"\nSTRUCT:%s pass:%d\n-------\n",struct_name,pass);
+
+       if(!check_if_to_emit(dissectorname)){
+               ti=tmpti;
+               goto typedef_struct_finished;
+       }
+
+       /* this is pass 0  so reset alignment to zero and update as items are
+          processed. we need alignment when pass 1 is run */
+       if(pass==0){
+               alignment=0;
+       }
+       /* pass 1  generate header for the struct dissector */
+       if(pass==1){
+               FPRINTF(eth_ett, "static gint ett_%s_%s = -1;\n", ifname, struct_name);
+               FPRINTF(eth_ettarr, "        &ett_%s_%s,\n", ifname, struct_name);
+               FPRINTF(eth_hdr, "int %s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param);\n", dissectorname);
+               FPRINTF(eth_code, "\n");
+               FPRINTF(eth_code, "int\n");
+               FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+               FPRINTF(eth_code, "{\n");
+               FPRINTF(eth_code, "    proto_item *item=NULL;\n");
+               FPRINTF(eth_code, "    proto_tree *tree=NULL;\n");
+               FPRINTF(eth_code, "    int old_offset;\n");
+               FPRINTF(eth_code, "\n");
+               switch(alignment){
+               case 1:
+                       break;
+               case 2:
+                       FPRINTF(eth_code, "    ALIGN_TO_2_BYTES;\n");
+                       FPRINTF(eth_code, "\n");
+                       break;
+               case 4:
+                       FPRINTF(eth_code, "    ALIGN_TO_4_BYTES;\n");
+                       FPRINTF(eth_code, "\n");
+                       break;
+               case 8:
+                       FPRINTF(eth_code, "    ALIGN_TO_8_BYTES;\n");
+                       FPRINTF(eth_code, "\n");
+                       break;
+               default:
+                       fprintf(stderr, "ERROR: can not handle alignment:%d\n",alignment);
+                       Exit(10);
+               }
+               FPRINTF(eth_code, "    old_offset=offset;\n");
+               FPRINTF(eth_code, "    if(parent_tree){\n");
+               FPRINTF(eth_code, "        item=proto_tree_add_item(parent_tree, hf_index, tvb, offset, -1, TRUE);\n");
+               FPRINTF(eth_code, "        tree=proto_item_add_subtree(item, ett_%s_%s);\n", ifname, struct_name);
+               FPRINTF(eth_code, "    }\n");
+               FPRINTF(eth_code, "\n");
+       }
+
+       /* scan the struct and create all subdissectors */
+       level=0;
+       while(ti){
+               if(!strcmp(ti->str, "{")){
+                       level++;
+                       ti=ti->next;
+                       continue;
+               }
+               if(!strcmp(ti->str, "}")){
+                       if(!level){
+                               break;
+                       }
+                       level--;
+                       ti=ti->next;
+                       continue;
+               }
+               if(!strcmp(ti->str, "[")){
+                       ti=parsebrackets(ti, &bi);
+                       continue;
+               }
+
+               /* check that we know how to handle the bracket thing */
+               if(bi){
+                       if(bi->flags&(~(BI_SIZE_IS|BI_LENGTH_IS|BI_POINTER))){
+                               fprintf(stderr, "ERROR: typedefstruct unknown bracket flags encountered : 0x%08x\n",bi->flags);
+                               Exit(10);
+                       }
+               }
+               
+               /* handle the type, verify that we KNOW this type */
+               type_item=find_type(ti->str);
+               if(!type_item){
+                       fprintf(stderr, "ERROR : typedefstruct unknown type %s\n",ti->str);
+                       Exit(10);
+               }
+               ti=ti->next;
+               /* count the levels of pointers */
+               for(num_pointers=0;!strcmp(ti->str, "*");ti=ti->next){
+                       num_pointers++;
+                       /* poitners are aligned at 4 byte boundaries */
+                       if(alignment<4){
+                               alignment=4;
+                       }
+               }
+               /* now that we know how many real poitner there were we must
+                  prepend default pointers to the list so it has the right
+                  length.
+               */
+               pi=prepend_pointer_list(bi?bi->pointer_list:NULL, num_pointers);
+               /* keep track of alignment */
+               if(alignment<type_item->alignment){
+                       alignment=type_item->alignment;
+               }
+
+               field_name=ti->str;
+               ti=ti->next;
+
+               /* see if it is a fixed array */
+               fixed_array_size=0;
+               is_array_of_pointers=0;
+               if(!strcmp(ti->str, "[")){
+                       char fss[256];
+
+                       /* this might be a fixed array */
+                       ti=ti->next;
+
+                       fixed_array_size=atoi(ti->str);
+                       sprintf(fss, "%d", fixed_array_size);
+
+                       if(!strcmp("*", ti->str)){
+                               if(bi && !(bi->flags|BI_POINTER)){
+                                       pi=prepend_pointer_list(pi, 1);
+                               }
+                               fixed_array_size=0;
+                               is_array_of_pointers=1;
+                       } else if(strcmp(fss, ti->str)){
+                               fprintf(stderr, "ERROR: typedefstruct (%s) fixed array size looks different to calculated one %s!=%s\n", struct_name, fss, ti->str);
+                               Exit(10);
+                       }
+                       ti=ti->next;
+
+                       if(strcmp(ti->str, "]")){
+                               fprintf(stderr, "ERROR: typedefstruct  fixed array does not end with ']''\n");
+                               Exit(10);
+                       }
+                       ti=ti->next;
+               }
+
+               sprintf(hf_index, "hf_%s_%s_%s", ifname, struct_name, field_name);
+               /* pass 0  generate subdissectors */
+               if(pass==0){
+                       char filter_name[256];
+                       char *hf;
+
+                       sprintf(tmpstr, "%s_dissect_%s_%s", ifname, struct_name, field_name);
+                       ptmpstr=strdup(tmpstr);
+                       sprintf(filter_name, "%s.%s.%s", ifname, struct_name, field_name);
+                       hf=register_hf_field(hf_index, field_name, filter_name, type_item->ft_type, type_item->base_type, type_item->vals, type_item->mask, "");
+
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", ptmpstr);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    guint32 param=%s;\n",find_dissector_param_value(ptmpstr));
+                       FPRINTF(eth_code, "    offset=%s(tvb, offset, pinfo, tree, drep, %s, param);\n", type_item->dissector, hf);
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+
+                       if(is_array_of_pointers){
+                               pointer_type=pi->type;
+                               pi=pi->next;
+                               sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr);
+                               FPRINTF(eth_code, "static int\n");
+                               FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr);
+                               FPRINTF(eth_code, "{\n");
+                               FPRINTF(eth_code, "    offset=dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, %s, %s, \"%s\", -1);\n", ptmpstr, ptr_to_define(pointer_type), field_name);
+                               FPRINTF(eth_code, "    return offset;\n");
+                               FPRINTF(eth_code, "}\n");
+                               FPRINTF(eth_code, "\n");
+                               
+                               ptmpstr=strdup(tmpstr);
+                       } else if(fixed_array_size){
+                               sprintf(tmpstr, "fixedarray_%s", ptmpstr);
+                               FPRINTF(eth_code, "static int\n");
+                               FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr);
+                               FPRINTF(eth_code, "{\n");
+                               FPRINTF(eth_code, "    int count=%d;\n",fixed_array_size);
+                               FPRINTF(eth_code, "    while(count--){\n");
+                               FPRINTF(eth_code, "        offset=%s(tvb, offset, pinfo, tree, drep);\n", ptmpstr);
+                               FPRINTF(eth_code, "    }\n");
+                               FPRINTF(eth_code, "\n");
+                               FPRINTF(eth_code, "    return offset;\n");
+                               FPRINTF(eth_code, "}\n");
+                               FPRINTF(eth_code, "\n");
+                               ptmpstr=strdup(tmpstr);
+                       }
+
+                       /* handle switch_is */
+                       if(bi){
+                         switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){
+                         case 0:
+                           break;
+                         case BI_SIZE_IS:
+                           sprintf(tmpstr, "ucarray_%s", ptmpstr);
+                           FPRINTF(eth_code, "static int\n");
+                           FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr);
+                           FPRINTF(eth_code, "{\n");
+                           FPRINTF(eth_code, "    offset=dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep, %s);\n", ptmpstr);
+                           FPRINTF(eth_code, "    return offset;\n");
+                           FPRINTF(eth_code, "}\n");
+                           FPRINTF(eth_code, "\n");
+                           ptmpstr=strdup(tmpstr);
+                           break;
+                         case BI_SIZE_IS|BI_LENGTH_IS:
+                           sprintf(tmpstr, "ucvarray_%s", ptmpstr);
+                           FPRINTF(eth_code, "static int\n");
+                           FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr);
+                           FPRINTF(eth_code, "{\n");
+                           FPRINTF(eth_code, "    offset=dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep, %s);\n", ptmpstr);
+                           FPRINTF(eth_code, "    return offset;\n");
+                           FPRINTF(eth_code, "}\n");
+                           FPRINTF(eth_code, "\n");
+                           ptmpstr=strdup(tmpstr);
+                           break;
+                         default:
+                           fprintf(stderr, "ERROR: typedefstruct can not handle this combination of sizeis/lengthis\n");
+                           Exit(10);
+                         }
+                       }
+
+                       /* handle pointers */
+                       while(num_pointers--){
+                               pointer_type=pi->type;
+                               pi=pi->next;
+                               sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr);
+                               FPRINTF(eth_code, "static int\n");
+                               FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr);
+                               FPRINTF(eth_code, "{\n");
+                               FPRINTF(eth_code, "    offset=dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, %s, %s, \"%s\", -1);\n", ptmpstr, ptr_to_define(pointer_type), field_name);
+                               FPRINTF(eth_code, "    return offset;\n");
+                               FPRINTF(eth_code, "}\n");
+                               FPRINTF(eth_code, "\n");
+                               
+                               ptmpstr=strdup(tmpstr);
+                       }
+               }
+
+               if(pass==1){
+                       sprintf(tmpstr, "%s_dissect_%s_%s", ifname, struct_name, field_name);
+                       ptmpstr=strdup(tmpstr);
+
+                       /* handle fixedsizearrays */
+                       if(is_array_of_pointers){
+                               pointer_type=pi->type;
+                               pi=pi->next;
+                               sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr);
+                               ptmpstr=strdup(tmpstr);
+                       } else if(fixed_array_size){
+                               sprintf(tmpstr, "fixedarray_%s", ptmpstr);
+                               ptmpstr=strdup(tmpstr);
+                       }
+
+                       /* handle switch_is */
+                       if(bi){
+                         switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){
+                         case 0:
+                           break;
+                         case BI_SIZE_IS:
+                           sprintf(tmpstr, "ucarray_%s", ptmpstr);
+                           ptmpstr=strdup(tmpstr);
+                           break;
+                         case BI_SIZE_IS|BI_LENGTH_IS:
+                           sprintf(tmpstr, "ucvarray_%s", ptmpstr);
+                           ptmpstr=strdup(tmpstr);
+                           break;
+                         default:
+                           fprintf(stderr, "ERROR: typedefstruct can not handle this combination of sizeis/lengthis\n");
+                           Exit(10);
+                         }
+                       }
+
+                       /* handle pointers */
+                       while(num_pointers--){
+                               pointer_type=pi->type;
+                               pi=pi->next;
+                               sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr);
+                               ptmpstr=strdup(tmpstr);
+                       }
+                               
+                       FPRINTF(eth_code, "    offset=%s(tvb, offset, pinfo, tree, drep);\n", ptmpstr);
+                       FPRINTF(eth_code, "\n");
+               }
+
+               if(strcmp(ti->str,";")){
+                       fprintf(stderr, "ERROR: field does not en with ';'\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+               bi=NULL; /* clear bi before we start on the next field */
+       }
+
+       if(pass==1){
+               FPRINTF(eth_code, "    proto_item_set_len(item, offset-old_offset);\n");
+               FPRINTF(eth_code, "\n");
+               FPRINTF(eth_code, "    return offset;\n");
+               FPRINTF(eth_code, "}\n");
+               register_new_type(struct_name, dissectorname, "FT_NONE", "BASE_NONE", "0", "NULL", alignment);
+       }
+
+
+typedef_struct_finished:
+       FPRINTF(NULL,"\nEND STRUCT:%s pass:%d\n-------\n",struct_name,pass);
+       
+       /* only advance token_list for pass==1
+          ti now points to the '}' token
+       */
+       if(pass==1){
+               if(strcmp(ti->str,"}")){
+                       fprintf(stderr, "ERROR: struct does not end with '}'\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+
+               /* just skip the name */
+               ti=ti->next;
+
+               if(strcmp(ti->str,";")){
+                       fprintf(stderr, "ERROR: struct does not end with ';'\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+               
+               token_list=ti;
+       }
+}
+
+/* this function will parse a
+       typedef bitmap {
+   construct and generate the appropriate code.
+   the typedef will be removed from the token_list once it has been processed
+   the function assumes that the typedef is the first object in the token_list
+   the function will be called twice, once with pass=0 and once with pass=1
+   which controls whether subdissectors are to be generated or whether the 
+   bitmap dissector itself is to be generated 
+
+   bitmaps are by default 32 bits
+*/
+void parsetypedefbitmap(int pass)
+{
+       token_item_t *ti, *tmpti;
+       char *bitmap_name;
+       char dissectorname[256], hf_bitname[256];
+       int alignment, val;
+       char *name, *value;
+       bracket_item_t *bi=NULL;
+
+       char tmpstr[256], *ptmpstr;
+       type_item_t *type_item;
+       char hf_index[256];
+
+       ti=token_list;
+       if(strcmp(ti->str, "typedef")){
+               fprintf(stderr, "ERROR: typedefbitmap  first token is not 'typedef'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       alignment=4;  /* default size is 32 bits */
+       
+       if(!strcmp(ti->str, "[")){
+               ti=parsebrackets(ti, &bi);
+       }
+       /* check that we know how to handle the bracket thing */
+       if(bi){
+               if(bi->flags&(~(BI_BITMAP32))){
+                       fprintf(stderr, "ERROR: typedefbitmap unknown bracket flags encountered : 0x%08x\n",bi->flags);
+                       Exit(10);
+               }
+               if(bi->flags&BI_BITMAP32){
+                       alignment=4;
+               }
+       }
+               
+
+       if(strcmp(ti->str, "bitmap")){
+               fprintf(stderr, "ERROR: typedefbitmap  second token is not 'bitmap'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       if(strcmp(ti->str, "{")){
+               fprintf(stderr, "ERROR: typedefbitmap  third token is not '{'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       /* search forward until the '}' so we can find the name of the bitmap */
+       for(tmpti=ti;tmpti;tmpti=tmpti->next){
+               if(!strcmp(tmpti->str, "{")){
+                       fprintf(stderr, "ERROR: typedefbitmap '{' encountered inside bitmap\n");
+                       Exit(10);
+               }
+               if(!strcmp(tmpti->str, "}")){
+                       break;
+               }
+       }
+       bitmap_name=tmpti->next->str;
+       sprintf(dissectorname, "%s_dissect_%s", ifname, bitmap_name);
+
+       FPRINTF(NULL,"\nBITMAP:%s pass:%d\n-------\n",bitmap_name,pass);
+
+       /* pass 1  generate header for the struct dissector */
+       if(pass==1){
+               FPRINTF(eth_ett, "static gint ett_%s_%s = -1;\n", ifname, bitmap_name);
+               FPRINTF(eth_ettarr, "        &ett_%s_%s,\n", ifname, bitmap_name);
+               FPRINTF(eth_hdr, "int %s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param);\n", dissectorname);
+               FPRINTF(eth_code, "\n");
+               FPRINTF(eth_code, "int\n");
+               FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+               FPRINTF(eth_code, "{\n");
+               FPRINTF(eth_code, "    proto_item *item=NULL;\n");
+               FPRINTF(eth_code, "    proto_tree *tree=NULL;\n");
+               switch(alignment){
+               case 4:
+                       FPRINTF(eth_code, "    guint32 flags;\n");
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "    ALIGN_TO_4_BYTES;\n");
+                       break;
+               default:
+                       fprintf(stderr, "ERROR: typedefbitmap can not handle alignment:%d\n",alignment);
+                       Exit(10);
+               }
+               FPRINTF(eth_code, "\n");
+               FPRINTF(eth_code, "    if(parent_tree){\n");
+               FPRINTF(eth_code, "        item=proto_tree_add_item(parent_tree, hf_index, tvb, offset, %d, TRUE);\n", alignment);
+               FPRINTF(eth_code, "        tree=proto_item_add_subtree(item, ett_%s_%s);\n", ifname, bitmap_name);
+               FPRINTF(eth_code, "    }\n");
+               FPRINTF(eth_code, "\n");
+               switch(alignment){
+               case 4:
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &flags);\n");
+                       FPRINTF(eth_code, "\n");
+                       break;
+               default:
+                       fprintf(stderr, "ERROR: typedefbitmap can not handle alignment:%d\n",alignment);
+                       Exit(10);
+               }
+               FPRINTF(eth_code, "\n");
+       }
+
+       /* scan the struct and create call for all bits */
+       while(ti){
+               if(!strcmp(ti->str, "}")){
+                       break;
+               }
+               if(!strcmp(ti->str, "[")){
+                       fprintf(stderr, "ERROR: typedefbitmap can not handle '[' yet\n");
+                       Exit(10);
+               }
+
+               name=ti->str;
+               ti=ti->next;
+               sprintf(hf_bitname, "hf_%s_%s_%s", ifname, bitmap_name, name);
+
+               if(strcmp(ti->str, "=")){
+                       fprintf(stderr, "ERROR: typedefbitmap i expected a '=' here\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+
+               value=ti->str;
+               ti=ti->next;
+               if(!strncmp(value, "0x", 2)){
+                       sscanf(value, "0x%x", &val);
+               } else {
+                       fprintf(stderr, "ERROR: typedefbitmap can only handle hexadecimal constants\n");
+                       Exit(10);
+               }
+
+               if( val&(val-1) ){
+                       fprintf(stderr, "ERROR: typedefbitmap can only handle single bit fields\n");
+                       Exit(10);
+               }
+
+               if(pass==0){
+                       char filter_name[256], base_name[256], tfs_name[256];
+                       char *hf;
+                       sprintf(filter_name, "%s.%s.%s", ifname, bitmap_name, name);
+                       sprintf(base_name, "%d", alignment*8);
+                       sprintf(tfs_name, "TFS(&%s_tfs)", name);
+                       hf=register_hf_field(hf_bitname, name, filter_name, "FT_BOOLEAN", base_name, tfs_name, value, "");
+
+                       FPRINTF(eth_code, "static const true_false_string %s_tfs = {\n",name);
+                       FPRINTF(eth_code, "    \"%s is SET\",\n", name);
+                       FPRINTF(eth_code, "    \"%s is NOT set\"\n", name);
+                       FPRINTF(eth_code, "};\n");
+                       FPRINTF(eth_code, "\n");
+               }
+
+               if(pass==1){
+                       FPRINTF(eth_code, "    proto_tree_add_boolean(tree, %s, tvb, offset-%d, %d, flags);\n", hf_bitname, alignment, alignment);
+                       FPRINTF(eth_code, "    if(flags&%s){\n", value);
+                       FPRINTF(eth_code, "        proto_item_append_text(item, \" %s\");\n", name);
+                       FPRINTF(eth_code, "    }\n");
+                       FPRINTF(eth_code, "    flags&=(~%s);\n", value);
+                       FPRINTF(eth_code, "\n");
+               }
+
+               if(!strcmp(ti->str, ",")){
+                       ti=ti->next;
+                       continue;
+               }
+       }
+
+       if(pass==1){
+               FPRINTF(eth_code, "    if(flags){\n");
+               FPRINTF(eth_code, "        proto_item_append_text(item, \"UNKNOWN-FLAGS\");\n");
+               FPRINTF(eth_code, "    }\n");
+               FPRINTF(eth_code, "\n");
+               FPRINTF(eth_code, "    return offset;\n");
+               FPRINTF(eth_code, "}\n");
+               switch(alignment){
+               case 4:
+                       register_new_type(bitmap_name, dissectorname, "FT_UINT32", "BASE_HEX", "0", "NULL", alignment);
+                       break;
+               default:
+                       fprintf(stderr, "ERROR: typedefbitmap can not handle alignment:%d\n",alignment);
+                       Exit(10);
+               }
+       }
+
+       FPRINTF(NULL,"\nEND BITMAP:%s pass:%d\n-------\n",bitmap_name,pass);
+       
+       /* only advance token_list for pass==1
+          ti now points to the '}' token
+       */
+       if(pass==1){
+               if(strcmp(ti->str,"}")){
+                       fprintf(stderr, "ERROR: bitmap does not end with '}'\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+
+               /* just skip the name */
+               ti=ti->next;
+
+               if(strcmp(ti->str,";")){
+                       fprintf(stderr, "ERROR: bitmap does not end with ';'\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+               
+               token_list=ti;
+       }
+}
+
+/* this function will parse a
+       typedef union {
+   construct and generate the appropriate code.
+   the typedef will be removed from the token_list once it has been processed
+   the function assumes that the typedef is the first object in the token_list
+   the function will be called twice, once with pass=0 and once with pass=1
+   which controls whether subdissectors are to be generated or whether the 
+   union dissector itself is to be generated 
+*/
+void parsetypedefunion(int pass)
+{
+       char *union_name;
+       token_item_t *ti, *tmpti;
+       char dissectorname[256];
+       bracket_item_t *bi=NULL;
+       char tmpstr[256], *ptmpstr;
+       int level, num_pointers;
+       static int alignment;
+       type_item_t *type_item;
+       char hf_index[256];
+       int tag_alignment, item_alignment;
+
+       ti=token_list;
+       if(strcmp(ti->str, "typedef")){
+               fprintf(stderr, "ERROR: typedefunion  first token is not 'typedef'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       if(strcmp(ti->str, "union")){
+               fprintf(stderr, "ERROR: typedefunion  second token is not 'union'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       if(strcmp(ti->str, "{")){
+               fprintf(stderr, "ERROR: typedefunion  third token is not '{'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       /* search forward until the '}' so we can find the name of the union */
+       for(tmpti=ti,level=0;tmpti;tmpti=tmpti->next){
+               if(!strcmp(tmpti->str, "{")){
+                       level++;
+                       continue;
+               }
+               if(!strcmp(tmpti->str, "}")){
+                       if(!level){
+                               break;
+                       }
+                       level--;
+                       continue;
+               }
+       }
+       union_name=tmpti->next->str;
+       sprintf(dissectorname, "%s_dissect_union_%s", ifname, union_name);
+
+       FPRINTF(NULL,"\nUNION:%s pass:%d\n-------\n",union_name,pass);
+
+       tag_alignment=get_union_tag_size(union_name);
+
+
+       /* this is pass 0  so reset alignment to the minimum possible value
+          and update as items are processed. 
+          we need alignment when pass 1 is run 
+       */
+       if(pass==0){
+               alignment=tag_alignment;
+       }
+
+       /* pass 1  generate header for the struct dissector */
+       if(pass==1){
+               FPRINTF(eth_ett, "static gint ett_%s_%s = -1;\n", ifname, union_name);
+               FPRINTF(eth_ettarr, "        &ett_%s_%s,\n", ifname, union_name);
+               FPRINTF(eth_code, "\n");
+               FPRINTF(eth_code, "static int\n");
+               FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+               FPRINTF(eth_code, "{\n");
+               FPRINTF(eth_code, "    proto_item *item=NULL;\n");
+               FPRINTF(eth_code, "    proto_tree *tree=NULL;\n");
+               FPRINTF(eth_code, "    int old_offset;\n");
+               /* we do alignment on the tag itself here so that
+                  we skip any alignment padding prior to where the tag
+                  itself starts, this makes the byterange in the hexpane
+                  for the union expansion start with the first byte of the tag
+               */
+               switch(tag_alignment){
+               case 1:
+                       break;
+               case 2:
+                       FPRINTF(eth_code, "    guint16 level;\n");
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "    ALIGN_TO_2_BYTES;\n");
+                       FPRINTF(eth_code, "\n");
+                       break;
+               case 4:
+                       FPRINTF(eth_code, "    guint32 level;\n");
+                       FPRINTF(eth_code, "\n");
+                       FPRINTF(eth_code, "    ALIGN_TO_4_BYTES;\n");
+                       FPRINTF(eth_code, "\n");
+                       break;
+               default:
+                       fprintf(stderr, "ERROR: typedefunion 1 can not handle alignment:%d\n",alignment);
+                       Exit(10);
+               }
+               FPRINTF(eth_code, "    old_offset=offset;\n");
+               FPRINTF(eth_code, "    if(parent_tree){\n");
+               FPRINTF(eth_code, "        item=proto_tree_add_text(parent_tree, tvb, offset, -1, \"%s\");\n", union_name);
+               FPRINTF(eth_code, "        tree=proto_item_add_subtree(item, ett_%s_%s);\n", ifname, union_name);
+               FPRINTF(eth_code, "    }\n");
+               FPRINTF(eth_code, "\n");
+               switch(tag_alignment){
+               case 1:
+                       break;
+               case 2:
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uint16(tvb, offset, pinfo, tree,\n");
+                       FPRINTF(eth_code, "                              drep, hf_index, &level);\n");
+               break;
+               case 4:
+                       FPRINTF(eth_code, "    offset=dissect_ndr_uint32(tvb, offset, pinfo, tree,\n");
+                       FPRINTF(eth_code, "                              drep, hf_index, &level);\n");
+                       break;
+               default:
+                       fprintf(stderr, "ERROR: typedefunion 2 can not handle alignment:%d\n",alignment);
+                       Exit(10);
+               }
+               FPRINTF(eth_code, "\n");
+               FPRINTF(eth_code, "    switch(level){\n");
+       }
+
+       /* scan the struct and create all subdissectors */
+       level=0;
+       while(ti){
+               if(!strcmp(ti->str, "{")){
+                       ti=ti->next;
+                       level++;
+                       continue;
+               }
+               if(!strcmp(ti->str, "}")){
+                       if(!level){
+                               break;
+                       }
+                       ti=ti->next;
+                       level--;
+                       continue;
+               }
+               if(!strcmp(ti->str, "[")){
+                       ti=parsebrackets(ti, &bi);
+                       continue;
+               }
+
+               if(!bi){
+                       fprintf(stderr, "ERROR : typedefunion no brackets found for case\n");
+                       Exit(10);
+               }
+               /* make sure we catch when we havent implemented everything
+                  yet.
+                  we currently only know about CASE and CASE_DEFAULT flags
+               */
+               if(bi->flags&(~(BI_CASE|BI_CASE_DEFAULT|BI_POINTER))){
+                       fprintf(stderr, "ERROR: typedefunion unknown bracket flags encountered : 0x%08x\n",bi->flags);
+                       Exit(10);
+               }
+               if(!(bi->flags&BI_CASE)){
+                       fprintf(stderr, "ERROR : typedefunion no case found in brackets\n");
+                       Exit(10);
+               }
+               /* only empty default cases for now */
+               if(bi->flags&BI_CASE_DEFAULT){
+                       if(strcmp(ti->str,";")){
+                               fprintf(stderr, "ERROR: default tag is not empty\n");
+                               Exit(10);
+                       }
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* just skip all and any 'empty' arms */
+               if(!strcmp(ti->str, ";")){
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* handle the type, verify that we KNOW this type */
+               type_item=find_type(ti->str);
+               if(!type_item){
+                       fprintf(stderr, "ERROR : typedefunion unknown type %s\n",ti->str);
+                       Exit(10);
+               }
+               ti=ti->next;
+               /* count the levels of pointers */
+               for(num_pointers=0;!strcmp(ti->str, "*");ti=ti->next){
+                       num_pointers++;
+               }
+
+               /* keep track of alignment */
+               if(num_pointers){
+                       item_alignment=4;
+               } else {
+                       item_alignment=type_item->alignment;
+               }
+               if(alignment<item_alignment){
+                       alignment=item_alignment;
+               }
+
+               sprintf(hf_index, "hf_%s_%s_%s_%s", ifname, union_name, bi->case_name, ti->str);
+               /* pass 0  generate subdissectors */
+               if(pass==0){
+                       char filter_name[256];
+                       char *hf;
+                       sprintf(tmpstr, "%s_dissect_union_%s_%s_%s", ifname, union_name, bi->case_name, ti->str);
+                       ptmpstr=strdup(tmpstr);
+
+                       sprintf(filter_name, "%s.%s.%s", ifname, union_name, ti->str);
+                       hf=register_hf_field(hf_index, ti->str, filter_name, type_item->ft_type, type_item->base_type, type_item->vals, type_item->mask, "");
+               
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", ptmpstr);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    guint32 param=%s;\n",find_dissector_param_value(ptmpstr));
+                       FPRINTF(eth_code, "    offset=%s(tvb, offset, pinfo, tree, drep, %s, param);\n", type_item->dissector, hf);
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+
+                       /* handle pointers */
+                       while(num_pointers--){
+                               sprintf(tmpstr, "%s_%s", ptmpstr, "unique");
+                               FPRINTF(eth_code, "static int\n");
+                               FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr);
+                               FPRINTF(eth_code, "{\n");
+                               FPRINTF(eth_code, "    offset=dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, %s, NDR_POINTER_UNIQUE, \"%s\", -1);\n", ptmpstr, ti->str);
+                               FPRINTF(eth_code, "    return offset;\n");
+                               FPRINTF(eth_code, "}\n");
+                               FPRINTF(eth_code, "\n");
+                               
+                               ptmpstr=strdup(tmpstr);
+                               
+                       }
+               }
+
+               if(pass==1){
+                       /* handle pointers */
+                       sprintf(tmpstr, "%s_dissect_union_%s_%s_%s", ifname, union_name, bi->case_name, ti->str);
+                       ptmpstr=strdup(tmpstr);
+                       while(num_pointers--){
+                               sprintf(tmpstr, "%s_%s", ptmpstr, "unique");
+                               ptmpstr=strdup(tmpstr);
+                       }
+                               
+                       FPRINTF(eth_code, "    case %s:\n",bi->case_name);
+                       /* each arm itself is aligned independently */
+                       switch(item_alignment){
+                       case 1:
+                               break;
+                       case 2:
+                               FPRINTF(eth_code, "        ALIGN_TO_2_BYTES;\n");
+                               break;
+                       case 4:
+                               FPRINTF(eth_code, "        ALIGN_TO_4_BYTES;\n");
+                               break;
+                       case 8:
+                               FPRINTF(eth_code, "        ALIGN_TO_8_BYTES;\n");
+                               break;
+                       default:
+                               fprintf(stderr, "ERROR: typedefunion 3 can not handle alignment:%d\n",item_alignment);
+                               Exit(10);
+                       }
+                       FPRINTF(eth_code, "        offset=%s(tvb, offset, pinfo, tree, drep);\n", ptmpstr);
+                       FPRINTF(eth_code, "        break;\n");
+                       FPRINTF(eth_code, "\n");
+               }
+               ti=ti->next;
+
+               if(strcmp(ti->str,";")){
+                       fprintf(stderr, "ERROR: field does not end with ';'\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+       }
+
+       if(pass==1){
+               FPRINTF(eth_code, "    }\n");
+               FPRINTF(eth_code, "\n");
+               FPRINTF(eth_code, "    proto_item_set_len(item, offset-old_offset);\n");
+               FPRINTF(eth_code, "\n");
+               FPRINTF(eth_code, "   return offset;\n");
+               FPRINTF(eth_code, "}\n");
+               switch(tag_alignment){
+               case 2:
+                       register_new_type(union_name, dissectorname, "FT_UINT16", "BASE_DEC", "0", "NULL", alignment);
+                       break;
+               case 4:
+                       register_new_type(union_name, dissectorname, "FT_UINT32", "BASE_DEC", "0", "NULL", alignment);
+                       break;
+               default:
+                       fprintf(stderr, "ERROR: typedefunion 4 can not handle alignment:%d\n",alignment);
+                       Exit(10);
+               }
+       }
+
+       FPRINTF(NULL,"\nEND UNION:%s pass:%d\n-------\n",union_name,pass);
+       
+       /* only advance token_list for pass==1
+          ti now points to the '}' token
+       */
+       if(pass==1){
+               if(strcmp(ti->str,"}")){
+                       fprintf(stderr, "ERROR: union does not end with '}'\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+
+               /* just skip the name */
+               ti=ti->next;
+
+               if(strcmp(ti->str,";")){
+                       fprintf(stderr, "ERROR: union does not end with ';'\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+               
+               token_list=ti;
+       }
+}
+
+
+/* this function will parse a
+       WERROR function (
+   construct and generate the appropriate code.
+   the function will be removed from the token_list once it has been processed
+   the function assumes that the function is the first object in the token_list
+   the function will be called three times with
+     pass=0   generate subdissectors and entries for the function table
+     pass=1   generate code for the REQUEST
+     pass=2   generate code for the REPLY
+*/
+void parsefunction(int pass)
+{
+       char *function_name;
+       static int funcno=0;
+       token_item_t *ti;
+       bracket_item_t *bi=NULL;
+       pointer_item_t *pi;
+       char *pointer_type;
+
+       char tmpstr[256], *ptmpstr;
+       int level, num_pointers;
+       type_item_t *type_item;
+       char hf_index[256];
+
+       ti=token_list;
+       if(strcmp(ti->str, "WERROR")){
+               fprintf(stderr, "ERROR: function  first token is not 'WERROR'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       function_name=ti->str;
+       ti=ti->next;
+
+       if(strcmp(ti->str, "(")){
+               fprintf(stderr, "ERROR: function  third token is not '('\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       FPRINTF(NULL,"\nFUNCTION:%s pass:%d\n-------\n",function_name,pass);
+
+       if(pass==0){
+               FPRINTF(eth_ft, "    { %d, \"%s\",\n",funcno,function_name);
+               FPRINTF(eth_ft, "        %s_dissect_%s_request,\n", ifname, function_name);
+               FPRINTF(eth_ft, "        %s_dissect_%s_response },\n", ifname, function_name);
+               funcno++;
+       }
+
+       /* pass 1,2  generate header for the function dissector */
+       if((pass==1)||(pass==2)){
+               FPRINTF(eth_code, "\n");
+               FPRINTF(eth_code, "static int\n");
+               FPRINTF(eth_code, "%s_dissect_%s_%s(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_)\n", ifname, function_name, (pass==1)?"request":"response");
+               FPRINTF(eth_code, "{\n");
+       }
+
+       /* scan the struct and create all subdissectors */
+       level=0;
+       while(ti){
+               if(!strcmp(ti->str, "(")){
+                       ti=ti->next;
+                       level++;
+                       continue;
+               }
+               if(!strcmp(ti->str, ")")){
+                       if(!level){
+                               break;
+                       }
+                       ti=ti->next;
+                       level--;
+                       continue;
+               }
+               if(!strcmp(ti->str, "[")){
+                       ti=parsebrackets(ti, &bi);
+                       continue;
+               }
+
+               if(!bi){
+                       fprintf(stderr, "ERROR : function no brackets found for case\n");
+                       Exit(10);
+               }
+
+               /* make sure we catch when we havent implemented everything
+                  yet.
+                  we currently only know about IN and OUT flags
+               */
+               if(bi->flags&(~(BI_IN|BI_OUT|BI_POINTER|BI_SIZE_IS|BI_LENGTH_IS))){
+                       fprintf(stderr, "ERROR: function unknown bracket flags encountered : 0x%08x\n",bi->flags);
+                       Exit(10);
+               }
+               if(!(bi->flags&(BI_IN|BI_OUT))){
+                       fprintf(stderr, "ERROR : function  parameter is neither in nor out\n");
+                       Exit(10);
+               }
+
+               /* handle the type, verify that we KNOW this type */
+               type_item=find_type(ti->str);
+               if(!type_item){
+                       fprintf(stderr, "ERROR : function unknown type %s\n",ti->str);
+                       Exit(10);
+               }
+               ti=ti->next;
+               /* count the levels of pointers */
+               for(num_pointers=0;!strcmp(ti->str, "*");ti=ti->next){
+                       num_pointers++;
+               }
+
+               /* now that we know how many real poitner there were we must
+                  prepend default pointers to the list so it has the right
+                  length.
+               */
+               pi=prepend_pointer_list(bi->pointer_list, num_pointers);
+
+               sprintf(hf_index, "hf_%s_%s_%s", ifname, function_name, ti->str);
+               /* pass 0  generate subdissectors */
+               if(pass==0){
+                       char filter_name[256];
+                       char *hf;
+
+                       sprintf(tmpstr, "%s_dissect_%s_%s", ifname, function_name, ti->str);
+                       ptmpstr=strdup(tmpstr);
+
+
+                       sprintf(filter_name, "%s.%s.%s", ifname, function_name, ti->str);
+                       hf=register_hf_field(hf_index, ti->str, filter_name, type_item->ft_type, type_item->base_type, type_item->vals, type_item->mask, "");
+
+                       FPRINTF(eth_code, "static int\n");
+                       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", ptmpstr);
+                       FPRINTF(eth_code, "{\n");
+                       FPRINTF(eth_code, "    guint32 param=%s;\n",find_dissector_param_value(ptmpstr));
+                       FPRINTF(eth_code, "    offset=%s(tvb, offset, pinfo, tree, drep, %s, param);\n", type_item->dissector, hf);
+                       FPRINTF(eth_code, "    return offset;\n");
+                       FPRINTF(eth_code, "}\n");
+                       FPRINTF(eth_code, "\n");
+
+
+                       /* handle switch_is */
+                       if(bi){
+                         switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){
+                         case 0:
+                           break;
+                         case BI_SIZE_IS|BI_LENGTH_IS:
+                           sprintf(tmpstr, "ucvarray_%s", ptmpstr);
+                           FPRINTF(eth_code, "static int\n");
+                           FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr);
+                           FPRINTF(eth_code, "{\n");
+                           FPRINTF(eth_code, "    offset=dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep, %s);\n", ptmpstr);
+                           FPRINTF(eth_code, "    return offset;\n");
+                           FPRINTF(eth_code, "}\n");
+                           FPRINTF(eth_code, "\n");
+                           ptmpstr=strdup(tmpstr);
+                           break;
+                         case BI_SIZE_IS:
+                           sprintf(tmpstr, "ucarray_%s", ptmpstr);
+                           FPRINTF(eth_code, "static int\n");
+                           FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr);
+                           FPRINTF(eth_code, "{\n");
+                           FPRINTF(eth_code, "    offset=dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep, %s);\n", ptmpstr);
+                           FPRINTF(eth_code, "    return offset;\n");
+                           FPRINTF(eth_code, "}\n");
+                           FPRINTF(eth_code, "\n");
+                           ptmpstr=strdup(tmpstr);
+                           break;
+                         default:
+                           fprintf(stderr, "ERROR: typedeffunction can not handle this combination of sizeis/lengthis\n");
+                           Exit(10);
+                         }
+                       }
+
+                       /* handle pointers */
+                       while(num_pointers--){
+                               pointer_type=pi->type;
+                               pi=pi->next;
+                               sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr);
+                               FPRINTF(eth_code, "static int\n");
+                               FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr);
+                               FPRINTF(eth_code, "{\n");
+                               FPRINTF(eth_code, "    offset=dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, %s, %s, \"%s\", -1);\n", ptmpstr, ptr_to_define(pointer_type), ti->str);
+                               FPRINTF(eth_code, "    return offset;\n");
+                               FPRINTF(eth_code, "}\n");
+                               FPRINTF(eth_code, "\n");
+                               
+                               ptmpstr=strdup(tmpstr);
+                               
+                       }
+               }
+
+               if((pass==1)||(pass==2)){
+                       sprintf(tmpstr, "%s_dissect_%s_%s", ifname, function_name, ti->str);
+                       ptmpstr=strdup(tmpstr);
+
+                       if(bi){
+                         switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){
+                         case 0:
+                           break;
+                         case BI_SIZE_IS|BI_LENGTH_IS:
+                           sprintf(tmpstr, "ucvarray_%s", ptmpstr);
+                           ptmpstr=strdup(tmpstr);
+                           break;
+                         case BI_SIZE_IS:
+                           sprintf(tmpstr, "ucarray_%s", ptmpstr);
+                           ptmpstr=strdup(tmpstr);
+                           break;
+                         default:
+                           fprintf(stderr, "ERROR: typedeffunction can not handle this combination of sizeis/lengthis\n");
+                           Exit(10);
+                         }
+                       }
+
+                       /* handle pointers */
+                       while(num_pointers--){
+                               pointer_type=pi->type;
+                               pi=pi->next;
+                               sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr);
+                               ptmpstr=strdup(tmpstr);
+                       }
+                       
+                       if((pass==1)&&(bi->flags&BI_IN)){       
+                               FPRINTF(eth_code, "        offset=%s(tvb, offset, pinfo, tree, drep);\n", ptmpstr);
+                               FPRINTF(eth_code, "\n");
+                       }
+                       if((pass==2)&&(bi->flags&BI_OUT)){      
+                               FPRINTF(eth_code, "        offset=%s(tvb, offset, pinfo, tree, drep);\n", ptmpstr);
+                               FPRINTF(eth_code, "\n");
+                       }
+               }
+               ti=ti->next;
+
+
+               if(!strcmp(ti->str,",")){
+                       ti=ti->next;
+                       continue;
+               }
+       }
+
+       if((pass==1)||(pass==2)){
+               if(pass==2){
+                       FPRINTF(eth_code, "   offset=dissect_ntstatus(tvb, offset, pinfo, tree, drep, %s, NULL);\n", hf_status);
+                       FPRINTF(eth_code, "\n");
+               }
+               FPRINTF(eth_code, "\n");
+               FPRINTF(eth_code, "   return offset;\n");
+               FPRINTF(eth_code, "}\n");
+       }
+
+       FPRINTF(NULL,"\nEND FUNCTION:%s pass:%d\n-------\n",function_name,pass);
+       
+       /* only advance token_list for pass==2
+          ti now points to the ')' token
+       */
+       if(pass==2){
+               if(strcmp(ti->str,")")){
+                       fprintf(stderr, "ERROR: function does not end with ')'\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+
+               if(strcmp(ti->str,";")){
+                       fprintf(stderr, "ERROR: function does not end with ';'\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+               
+               token_list=ti;
+       }
+}
+
+
+/* this function will parse a
+       typedef enum {
+   or a
+       typedef [ v1_enum ] enum {
+   construct and generate the appropriate code.
+   the typedef will be removed from the token_list once it has been processed
+   the function assumes that the typedef is the first object in the token_list
+*/
+void parsetypedefenum(void)
+{
+       token_item_t *ti;
+       enum_list_t *enum_list, *el, *lastel;
+       int eval, enumsize;
+       char dissectorname[256], valsstring[256], hfvalsstring[256];
+
+       enumsize=16;
+
+       ti=token_list;
+       if(strcmp(ti->str, "typedef")){
+               fprintf(stderr, "ERROR: typedefenum  first token is not 'typedef'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       /* this could be a [ v1_enum ] */
+       if(!strcmp(ti->str, "[")){
+               ti=ti->next;
+
+               if(strcmp(ti->str, "v1_enum")){
+                       fprintf(stderr, "ERROR: typedefenum  not 'v1_enum' inside brackets\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+
+               if(strcmp(ti->str, "]")){
+                       fprintf(stderr, "ERROR: typedefenum  'v1_enum' is not followed by ']'\n");
+                       Exit(10);
+               }
+               ti=ti->next;
+
+               enumsize=32;
+       }
+
+
+       if(strcmp(ti->str, "enum")){
+               fprintf(stderr, "ERROR: typedefenum  second token is not 'enum'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       if(strcmp(ti->str, "{")){
+               fprintf(stderr, "ERROR: typedefenum  third token is not '{'\n");
+               Exit(10);
+       }
+       ti=ti->next;
+
+       /* now parse all values until we find the "}" */
+       eval=0;
+       enum_list=NULL;
+       lastel=NULL;
+       while(1){
+               /* check for '}' */
+               if(!strcmp(ti->str,"}")){
+                       ti=ti->next;
+                       break;
+               }
+
+               /* handle 4 types of entries:
+                * 1, CONST = value,
+                * 2, CONST,
+                * 3, CONST = value}
+                * 4, CONST}
+                */
+               el=malloc(sizeof(enum_list_t));
+               el->next=NULL;
+               if(!enum_list){
+                       enum_list=el;
+               } else {
+                       lastel->next=el;
+               }
+               lastel=el;
+
+               /* grab CONST */
+               el->name=ti->str;
+               ti=ti->next;
+
+               /* grab separator */
+               if(!strcmp(ti->str,"=")){
+                       ti=ti->next;
+                       /* grab value */
+                       el->val=atoi(ti->str);
+                       ti=ti->next;
+               } else {
+                       el->val=eval;
+               }
+               eval=el->val+1;
+
+               /* check for ',' */
+               if(!strcmp(ti->str,",")){
+                       ti=ti->next;
+                       continue;
+               }
+
+               /* check for '}' */
+               if(!strcmp(ti->str,"}")){
+                       ti=ti->next;
+                       break;
+               }
+
+               fprintf(stderr,"ERROR: typedefenum should not be reached\n");
+               Exit(10);
+       }
+
+       /* verify that it ends with a ';' */
+       if(strcmp(ti->next->str,";")){
+               fprintf(stderr,"ERROR enum terminator is not ';'\n");
+               Exit(10);
+       }
+
+       sprintf(valsstring, "%s_%s_vals", ifname, ti->str);
+       sprintf(dissectorname, "%s_dissect_%s", ifname, ti->str);
+
+       FPRINTF(NULL,"\nENUM:%s\n-------\n",ti->str);
+
+       FPRINTF(eth_hdr, "\n");
+       for(el=enum_list;el;el=el->next){
+               FPRINTF(eth_hdr, "#define %s            %d\n", el->name, el->val);
+       }
+
+       FPRINTF(eth_hdr, "\n");
+       FPRINTF(eth_hdr, "extern const value_string %s[];\n", valsstring);
+       FPRINTF(eth_hdr, "int %s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param);\n", dissectorname);
+
+       FPRINTF(eth_code, "\n");
+       FPRINTF(eth_code, "const value_string %s[] = {\n", valsstring);
+
+       for(el=enum_list;el;el=el->next){
+               FPRINTF(eth_code, "    { %d     , \"%s\" },\n", el->val, el->name);
+       }
+       FPRINTF(eth_code, "    { 0      , NULL }\n");
+       FPRINTF(eth_code, "};\n");
+
+       FPRINTF(eth_code, "\n");
+       FPRINTF(eth_code, "int\n");
+       FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+       FPRINTF(eth_code, "{\n");
+       switch(enumsize){
+       case 16:
+               FPRINTF(eth_code, "    offset=dissect_ndr_uint16(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+               break;
+       case 32:
+               FPRINTF(eth_code, "    offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n");
+               break;
+       default:
+               fprintf(stderr,"ERROR enum unknown size\n");
+               Exit(10);
+       }
+
+       FPRINTF(eth_code, "    return offset;\n");
+       FPRINTF(eth_code, "}\n");
+       FPRINTF(eth_code, "\n");
+
+
+       sprintf(hfvalsstring, "VALS(%s)", valsstring);
+       switch(enumsize){
+       case 16:
+               register_new_type(ti->str, dissectorname, "FT_INT16", "BASE_DEC", "0", hfvalsstring, 2);
+               break;
+       case 32:
+               register_new_type(ti->str, dissectorname, "FT_INT32", "BASE_DEC", "0", hfvalsstring, 4);
+               break;
+       default:
+               fprintf(stderr,"ERROR enum unknown size\n");
+               Exit(10);
+       }
+
+       FPRINTF(NULL,"\n----------\nEND ENUM:%s\n",ti->str);
+
+       /* skip past the name and the ';' */
+       token_list=ti->next->next;
+}
+
+typedef struct _trimmed_prefixes_t {
+       struct _trimmed_prefixes_t *next;
+       char *name;
+} trimmed_prefixes_t;
+trimmed_prefixes_t *prefixes_to_trim=NULL;
+
+void preparetrimprefix(char *prefix_name)
+{
+       trimmed_prefixes_t *new_prefix;
+       new_prefix=malloc(sizeof(trimmed_prefixes_t));
+       new_prefix->next=prefixes_to_trim;
+       prefixes_to_trim=new_prefix;
+       new_prefix->name=strdup(prefix_name);
+}
+void
+trimprefix(void)
+{
+       token_item_t *ti;
+       trimmed_prefixes_t *pfx;
+       int len;
+
+       for(pfx=prefixes_to_trim;pfx;pfx=pfx->next){
+               len=strlen(pfx->name);
+               for(ti=token_list;ti;ti=ti->next){
+                       if(!strncmp(ti->str, pfx->name, len)){
+                               ti->str+=len;
+                       }
+               }
+       }
+}
+
+int Exit(int code)
+{
+       fprintf(stderr, "The tokens remaining when aborting:\n");
+       printtokenlist(10);
+
+       exit(code);
+}
+
+void usage(void)
+{
+       fprintf(stderr, "Usage: idl2eth <interface>\n");
+}
+
+void
+mergefile(char *name, FILE *outfile)
+{
+       FILE *infile;
+
+       fprintf(outfile, "\n\n/* INCLUDED FILE : %s */\n", name);
+       infile=fopen(name, "r");
+       while(!feof(infile)){
+               int ch;
+               ch=fgetc(infile);
+               if(ch!=-1){
+                       fputc(ch, outfile);
+               }
+       }
+       fclose(infile);
+       fprintf(outfile, "/* END OF INCLUDED FILE : %s */\n\n\n", name);
+}
+
+
+
+char *
+str_read_string(char *str, char **name)
+{
+       char tmpstr[256], *strptr;
+       int skip_blanks;
+       int quoted_string;
+
+       strptr=tmpstr;
+       skip_blanks=1;
+       quoted_string=0;
+       while(1){
+               if(!*str){
+                       *strptr=0;
+                       *name=strdup(tmpstr);
+                       return str;
+               }
+               if(skip_blanks){
+                       if( (*str==' ') || (*str=='\t') ){
+                               str++;
+                               continue;
+                       }
+                       if( *str=='"' ){
+                               str++;
+                               quoted_string=1;
+                       }
+                       skip_blanks=0;
+                       continue;
+               }
+               if( (*str==' ') || (*str=='\t') ){
+                       if(quoted_string){
+                               *strptr++ = *str++;
+                               continue;
+                       }
+                       *strptr=0;
+                       *name=strdup(tmpstr);
+                       return str;
+               }
+               if( (*str=='"') || (*str=='\n') ){
+                       *strptr=0;
+                       *name=strdup(tmpstr);
+                       return ++str;
+               }
+               *strptr++ = *str++;
+       }                       
+       return NULL;
+}
+
+void
+readcnffile(FILE *fh)
+{
+       char cnfline[1024];
+
+       FPRINTF(NULL, "Reading conformance file\n=======================\n");
+       while(!feof(fh)){
+               cnfline[0]=0;
+               fgets(cnfline, 1023, fh);
+               if(!cnfline[0]){
+                       continue;
+               }
+               if(cnfline[0]=='#'){
+                       /* ignore all comments */                       
+               } else if(!strncmp(cnfline, "NOEMIT", 6)){
+                       no_emit_item_t *nei;
+                       char *str, *name;
+
+                       str=cnfline+6;
+                       str=str_read_string(str, &name);
+                       nei=malloc(sizeof(no_emit_item_t));
+                       nei->next=no_emit_list;
+                       no_emit_list=nei;
+                       nei->name=name;
+                       FPRINTF(NULL, "NOEMIT : %s\n", nei->name);
+               } else if(!strncmp(cnfline, "TYPE", 4)){
+                       char *name, *dissectorname, *ft_type, *base_type;
+                       char *mask, *valsstring, *al;
+                       char *str;
+                       int alignment;
+
+                       str=cnfline+4;
+                       str=str_read_string(str, &name);
+                       str=str_read_string(str, &dissectorname);
+                       str=str_read_string(str, &ft_type);
+                       str=str_read_string(str, &base_type);
+                       str=str_read_string(str, &mask);
+                       str=str_read_string(str, &valsstring);
+                       str=str_read_string(str, &al);
+                       alignment=atoi(al);
+
+                       FPRINTF(NULL, "TYPE : X%s,%sX\n", name, dissectorname);
+                       register_new_type(name, dissectorname, ft_type, base_type, mask, valsstring, alignment);
+               } else if(!strncmp(cnfline, "PARAM_VALUE", 11)){
+                       char *dissectorname, *value;
+                       char *str;
+
+                       str=cnfline+11;
+                       str=str_read_string(str, &dissectorname);
+                       str=str_read_string(str, &value);
+
+                       FPRINTF(NULL, "PARAM_VALUE : %s=%s\n", dissectorname,value);
+                       register_dissector_param_value(dissectorname, value);
+               } else if(!strncmp(cnfline, "HF_FIELD", 8)){
+                       char *hf_index, *title, *filter_name, *ft_type;
+                       char *base_type, *valsstring, *mask, *blurb;
+                       char *str;
+
+                       str=cnfline+8;
+                       str=str_read_string(str, &hf_index);
+                       str=str_read_string(str, &title);
+                       str=str_read_string(str, &filter_name);
+                       str=str_read_string(str, &ft_type);
+                       str=str_read_string(str, &base_type);
+                       str=str_read_string(str, &valsstring);
+                       str=str_read_string(str, &mask);
+                       str=str_read_string(str, &blurb);
+                       FPRINTF(NULL, "HF_FIELD: %s \"%s\"\n", hf_index, title);
+                       register_hf_field(hf_index, title, filter_name, ft_type, base_type, valsstring, mask, blurb);
+               } else if(!strncmp(cnfline, "HF_RENAME", 9)){
+                       char *old_name, *new_name;
+                       char *str;
+
+                       str=cnfline+9;
+                       str=str_read_string(str, &old_name);
+                       str=str_read_string(str, &new_name);
+                       FPRINTF(NULL, "HF_RENAME: %s -> %s\n", old_name, new_name);
+                       register_hf_rename(old_name, new_name);
+               } else if(!strncmp(cnfline, "UNION_TAG_SIZE", 14)){
+                       char *union_name, *union_tag;
+                       int union_tag_size;
+                       union_tag_size_item_t *utsi;
+                       char *str;
+
+                       str=cnfline+14;
+                       str=str_read_string(str, &union_name);
+                       str=str_read_string(str, &union_tag);
+                       union_tag_size=atoi(union_tag);
+                       FPRINTF(NULL, "UNION_TAG_SIZE: %s == %d\n", union_name, union_tag_size);
+                       utsi=malloc(sizeof(union_tag_size_item_t));
+                       utsi->next=union_tag_size_list;
+                       union_tag_size_list=utsi;
+                       utsi->name=strdup(union_name);
+                       utsi->size=union_tag_size;
+               } else if(!strncmp(cnfline, "STRIP_PREFIX", 12)){
+                       char *prefix_name;
+                       char *str;
+
+                       str=cnfline+12;
+                       str=str_read_string(str, &prefix_name);
+                       FPRINTF(NULL, "STRIP_PREFIX: %s\n", prefix_name);
+                       preparetrimprefix(prefix_name);
+               } else {
+                       fprintf(stderr, "ERROR: could not parse cnf directive:%s\n",cnfline);
+                       exit(10);
+               }
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       char idlfile[256];
+       char cnffile[256];
+       char prefix_str[256];
+       bracket_item_t *bi;
+
+       if(argc!=2){
+               usage();
+               exit(0);
+       }
+
+       eth_code=fopen("ETH_CODE", "w");
+       eth_hdr=fopen("ETH_HDR", "w");
+       eth_hfarr=fopen("ETH_HFARR", "w");
+       eth_hf=fopen("ETH_HF", "w");
+       eth_ettarr=fopen("ETH_ETTARR", "w");
+       eth_ett=fopen("ETH_ETT", "w");
+       eth_ft=fopen("ETH_FT", "w");
+       eth_handoff=fopen("ETH_HANDOFF", "w");
+
+       sprintf(idlfile, "%s.cnf", argv[1]);
+       fh=fopen(idlfile,"r");
+       if(fh){
+               readcnffile(fh);
+               fclose(fh);
+       }
+
+       sprintf(idlfile, "%s.idl", argv[1]);
+       fh=fopen(idlfile,"r");
+       if(!fh){
+               fprintf(stderr, "ERROR: could not open idl-file:%s\n",idlfile);
+               Exit(0);
+       }
+
+       lineno=0;
+       linepos=0;
+       tokenize();
+       prune_keyword_parameters("size_is");
+       prune_keyword_parameters("length_is");
+       rename_tokens("NTSTATUS", "WERROR");
+       rename_tokens("unistr_noterm", "unistr");
+       rename_tokens("ascstr_noterm", "ascstr");
+       rename_tokens("hyper", "uint64");
+       FPRINTF(NULL,"\n\nParsing header:\n================\n");
+       parseheader();
+
+       /* some idl files prepend a lot of symbols with <ifname>_
+          search through the tokenlist and remove all such
+          prefixes
+       */
+       sprintf(prefix_str, "%s_", ifname);
+       preparetrimprefix(prefix_str);
+       trimprefix();
+
+       /* this is the main loop, each iteration it tries to identify what
+          kind of construct is the first entry in the token_list and call
+          the appropriate handler
+       */
+       while(1) {
+               /* just skip any [ ] that starts a new construct */
+               if( !strcmp(token_list->str, "[") ){
+                       token_list=parsebrackets(token_list, &bi);
+                       continue;
+               }
+
+               /* typedef enum { */
+               if( !strcmp(token_list->str,"typedef")
+                 &&!strcmp(token_list->next->str,"enum") ){
+                       parsetypedefenum();
+                       continue;
+               }
+
+               /* typedef [ v1_enum ] enum { */
+               if( !strcmp(token_list->str,"typedef")
+                 &&!strcmp(token_list->next->str,"[")
+                 &&!strcmp(token_list->next->next->str,"v1_enum")
+                 &&!strcmp(token_list->next->next->next->str,"]")
+                 &&!strcmp(token_list->next->next->next->next->str,"enum") ){
+                       parsetypedefenum();
+                       continue;
+               }
+
+               /* const */
+               if( !strcmp(token_list->str,"const") ){
+                       parseconst();
+                       continue;
+               }
+
+               /* typedef struct { */
+               if( !strcmp(token_list->str,"typedef") ){
+                       token_item_t *tmpti;
+                       
+                       tmpti=token_list->next;
+                       if( !strcmp(tmpti->str, "[") ){
+                               tmpti=parsebrackets(tmpti, &bi);
+                               /* do some sanity checks here of bi->flags */
+                       }
+                       if( !strcmp(tmpti->str, "struct") ){
+                               parsetypedefstruct(0);
+                               parsetypedefstruct(1);
+                               continue;
+                       }
+               }
+
+               /* typedef union { */
+               if( !strcmp(token_list->str,"typedef")
+                 &&!strcmp(token_list->next->str,"union") ){
+                       parsetypedefunion(0);
+                       parsetypedefunion(1);
+                       continue;
+               }
+
+               /* typedef bitmap { */
+               if( !strcmp(token_list->str,"typedef") ){
+                       token_item_t *tmpti;
+                       
+                       tmpti=token_list->next;
+                       if( !strcmp(tmpti->str, "[") ){
+                               tmpti=parsebrackets(tmpti, &bi);
+                               /* do some sanity checks here of bi->flags */
+                       }
+                       if( !strcmp(tmpti->str, "bitmap") ){
+                               parsetypedefbitmap(0);
+                               parsetypedefbitmap(1);
+                               continue;
+                       }
+               }
+
+               /* functions:  WERROR function '(' */
+               if( !strcmp(token_list->str,"WERROR")
+                 &&!strcmp(token_list->next->next->str,"(") ){
+                       parsefunction(0);
+                       parsefunction(1);
+                       parsefunction(2);
+                       continue;
+               }
+
+               /* declare ... ; */
+               if( !strcmp(token_list->str,"declare") ){
+                       skipdeclare();
+                       continue;
+               }
+
+               
+               break;
+       };
+
+
+       fclose(eth_code);
+       fclose(eth_hdr);
+       fclose(eth_hf);
+       fclose(eth_hfarr);
+       fclose(eth_ett);
+       fclose(eth_ettarr);
+       fclose(eth_ft);
+       fclose(eth_handoff);
+
+       /* unless the token_list now only contains a single token : '}'
+          we have failed to compile the idl file properly
+        */
+       if( strcmp(token_list->str, "}") || token_list->next){
+               fprintf(stderr, "ERROR: we did not process all tokens. Compiler is incomplete.\n===========================================\n");
+               printtokenlist(10);
+               exit(10);
+       }
+
+       /* merge code and template into dissector */
+       sprintf(line, "packet-dcerpc-%s.c", ifname);
+       fh=fopen(line, "w");
+       tfh=fopen("template.c", "r");
+       if(!tfh){
+               fprintf(stderr, "ERROR: could not find template.c\n");
+               exit(10);
+       }
+       while(!feof(tfh)){
+               line[0]=0;
+               fgets(line, 1024, tfh);
+               if(!strncmp(line, "ETH_CODE", 8)){
+                       mergefile("ETH_CODE",fh);
+               } else if(!strncmp(line, "ETH_HDR", 7)){
+                       mergefile("ETH_HDR",fh);
+               } else if(!strncmp(line, "ETH_HFARR", 9)){
+                       mergefile("ETH_HFARR",fh);
+               } else if(!strncmp(line, "ETH_HF", 6)){
+                       mergefile("ETH_HF",fh);
+               } else if(!strncmp(line, "ETH_ETTARR", 10)){
+                       mergefile("ETH_ETTARR",fh);
+               } else if(!strncmp(line, "ETH_ETT", 7)){
+                       mergefile("ETH_ETT",fh);
+               } else if(!strncmp(line, "ETH_FT", 6)){
+                       mergefile("ETH_FT",fh);
+               } else if(!strncmp(line, "ETH_HANDOFF", 11)){
+                       mergefile("ETH_HANDOFF",fh);
+               } else {
+                       fputs(line, fh);
+               }
+       }
+       fclose(fh);
+       fclose(tfh);
+
+
+       sprintf(line, "packet-dcerpc-%s.h", ifname);
+       fh=fopen(line, "w");
+       tfh=fopen("template.h", "r");
+       if(!tfh){
+               fprintf(stderr, "ERROR: could not find template.h\n");
+               exit(10);
+       }
+       while(!feof(tfh)){
+               line[0]=0;
+               fgets(line, 1024, tfh);
+               if(!strncmp(line, "ETH_CODE", 8)){
+                       mergefile("ETH_CODE",fh);
+               } else if(!strncmp(line, "ETH_HDR", 7)){
+                       mergefile("ETH_HDR",fh);
+               } else if(!strncmp(line, "ETH_HFARR", 9)){
+                       mergefile("ETH_HFARR",fh);
+               } else if(!strncmp(line, "ETH_HF", 6)){
+                       mergefile("ETH_HF",fh);
+               } else if(!strncmp(line, "ETH_ETTARR", 10)){
+                       mergefile("ETH_ETTARR",fh);
+               } else if(!strncmp(line, "ETH_ETT", 7)){
+                       mergefile("ETH_ETT",fh);
+               } else if(!strncmp(line, "ETH_FT", 6)){
+                       mergefile("ETH_FT",fh);
+               } else if(!strncmp(line, "ETH_HANDOFF", 11)){
+                       mergefile("ETH_HANDOFF",fh);
+               } else {
+                       fputs(line, fh);
+               }
+       }
+
+       printf("%s was successfully compiled\n", ifname);
+
+       fclose(fh);
+       fclose(tfh);
+
+       return 0;
+}
+