merge
authorMario de Sousa <msousa@fe.up.pt>
Thu, 22 Nov 2012 19:19:48 +0000
changeset 744 6ecb38715724
parent 742 a9741eb5aaab (diff)
parent 743 fbf77edf54ca (current diff)
child 751 0a5c050d64bb
merge
--- a/absyntax/absyntax.def	Mon Nov 12 22:36:55 2012 +0100
+++ b/absyntax/absyntax.def	Thu Nov 22 19:19:48 2012 +0000
@@ -114,7 +114,8 @@
 /***************************/
 /* B 0 - Programming Model */
 /***************************/
-SYM_LIST(library_c)
+/* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
+SYM_LIST(library_c, enumvalue_symtable_t enumvalue_symtable;)
 
 
 /*************************/
@@ -701,7 +702,8 @@
 /***********************/
 /* B 1.5.1 - Functions */
 /***********************/
-SYM_REF4(function_declaration_c, derived_function_name, type_name, var_declarations_list, function_body)
+/* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
+SYM_REF4(function_declaration_c, derived_function_name, type_name, var_declarations_list, function_body, enumvalue_symtable_t enumvalue_symtable;)
 
 /* intermediate helper symbol for
  * - function_declaration
@@ -721,7 +723,8 @@
 /* B 1.5.2 - Function Blocks */
 /*****************************/
 /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
-SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body)
+/* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
+SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body, enumvalue_symtable_t enumvalue_symtable;)
 
 /* intermediate helper symbol for function_declaration */
 /*  { io_var_declarations | other_var_declarations }   */
@@ -743,7 +746,8 @@
 /* B 1.5.3 - Programs */
 /**********************/
 /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
-SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body)
+/* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
+SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body, enumvalue_symtable_t enumvalue_symtable;)
 
 /* intermediate helper symbol for program_declaration_c */
 /*  { io_var_declarations | other_var_declarations }   */
@@ -826,7 +830,8 @@
    optional_instance_specific_initializations
 END_CONFIGURATION
 */
-SYM_REF5(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations)
+/* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
+SYM_REF5(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, enumvalue_symtable_t enumvalue_symtable;)
 
 /* helper symbol for configuration_declaration */
 SYM_LIST(resource_declaration_list_c)
@@ -837,7 +842,8 @@
    single_resource_declaration
 END_RESOURCE
 */
-SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration)
+/* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
+SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration, enumvalue_symtable_t enumvalue_symtable;)
 
 /* task_configuration_list program_configuration_list */
 SYM_REF2(single_resource_declaration_c, task_configuration_list, program_configuration_list)
--- a/absyntax/absyntax.hh	Mon Nov 12 22:36:55 2012 +0100
+++ b/absyntax/absyntax.hh	Thu Nov 22 19:19:48 2012 +0000
@@ -48,6 +48,7 @@
 
 #include <stdio.h> // required for NULL
 #include <vector>
+#include <map>
 #include <string>
 #include <stdint.h>  // required for uint64_t, etc...
 #include "../main.hh" // required for uint8_t, real_64_t, ..., and the macros INT8_MAX, REAL32_MAX, ... */
@@ -72,6 +73,28 @@
 
 
 
+/* Case insensitive string compare */
+  /* Case insensitive string compare copied from
+   * "The C++ Programming Language" - 3rd Edition
+   * by Bjarne Stroustrup, ISBN 0201889544.
+   */
+class nocasecmp_c {
+    public:
+      bool operator() (const std::string& x, const std::string& y) const {
+        std::string::const_iterator ix = x.begin();
+        std::string::const_iterator iy = y.begin();
+
+        for(; (ix != x.end()) && (iy != y.end()) && (toupper(*ix) == toupper(*iy)); ++ix, ++iy);
+        if (ix == x.end()) return (iy != y.end());
+        if (iy == y.end()) return false;
+        return (toupper(*ix) < toupper(*iy));
+      };
+  };
+
+
+
+
+
 
 
 
@@ -99,7 +122,7 @@
 
     /*
      * Annotations produced during stage 3
-     */
+     */    
     /*** Data type analysis ***/
     std::vector <symbol_c *> candidate_datatypes; /* All possible data types the expression/literal/etc. may take. Filled in stage3 by fill_candidate_datatypes_c class */
     /* Data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c 
@@ -138,6 +161,12 @@
     } const_value_t;
     const_value_t const_value;
     
+    /*** Enumeration datatype checking ***/    
+    /* Not all symbols will contain the following anotations, which is why they are not declared here in symbol_c
+     * They will be declared only inside the symbols that require them (have a look at absyntax.def)
+     */
+    typedef std::multimap<std::string, symbol_c *, nocasecmp_c> enumvalue_symtable_t;
+    
 
   public:
     /* default constructor */
@@ -153,6 +182,8 @@
 };
 
 
+
+
 class token_c: public symbol_c {
   public:
     /* WARNING: only use this method for debugging purposes!! */
@@ -169,6 +200,8 @@
 };
 
 
+
+
  /* a list of symbols... */
 class list_c: public symbol_c {
   public:
@@ -200,6 +233,11 @@
 
 
 
+
+
+
+
+
 #define SYM_LIST(class_name_c, ...)											\
 class class_name_c:	public list_c {											\
   public:														\
--- a/absyntax/visitor.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/absyntax/visitor.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -70,7 +70,7 @@
 
 null_visitor_c::~null_visitor_c(void) {return;}
 
-#define SYM_LIST(class_name_c)	\
+#define SYM_LIST(class_name_c, ...)	\
   void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
 
 #define SYM_TOKEN(class_name_c, ...)	\
@@ -174,7 +174,7 @@
 }
 
 
-#define SYM_LIST(class_name_c)	\
+#define SYM_LIST(class_name_c, ...)	\
   void *iterator_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);}
 
 #define SYM_TOKEN(class_name_c, ...)	\
@@ -318,7 +318,7 @@
 }
 
 
-#define SYM_LIST(class_name_c)	\
+#define SYM_LIST(class_name_c, ...)	\
   void *search_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);}
 
 #define SYM_TOKEN(class_name_c, ...)	\
--- a/absyntax_utils/absyntax_utils.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/absyntax_utils/absyntax_utils.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -193,7 +193,7 @@
   /*  enumerated_type_name ':' enumerated_spec_init */
   void *visit(enumerated_type_declaration_c *symbol) {
     TRACE("enumerated_type_declaration_c");
-    type_symtable.insert(symbol->enumerated_type_name, symbol->enumerated_spec_init);
+    type_symtable.insert(symbol->enumerated_type_name, symbol);
     current_enumerated_type = symbol->enumerated_type_name;
     symbol->enumerated_spec_init->accept(*this);
     current_enumerated_type = NULL;
--- a/absyntax_utils/debug_ast.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/absyntax_utils/debug_ast.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -44,14 +44,32 @@
 #include <unistd.h>
 #include <stdio.h>  /* required for NULL */
 #include "absyntax_utils.hh"
-
-
-
-
-
-
-
-
+#include "../absyntax/visitor.hh"
+
+
+
+
+
+
+/*********************************/
+/* Class to print a symbol       */
+/*********************************/
+
+
+class print_symbol_c: public fcall_visitor_c { 
+  public:
+    static void print(symbol_c *symbol);
+    
+  protected:
+    void fcall(symbol_c *symbol);  
+    /* AST symbols with extra data have their own specialised methods for printing that data */
+    void *visit(il_instruction_c *symbol);
+
+  private:
+    static print_symbol_c *singleton;
+    
+    void dump_symbol(symbol_c* symbol);
+};
 
 
 
@@ -70,9 +88,6 @@
 
 
 
-
-
-
 void print_symbol_c::fcall(symbol_c* symbol) {
   dump_symbol(symbol);
   fprintf(stderr, "\n");
@@ -85,8 +100,9 @@
   fprintf(stderr, "  datatype=");
   if (NULL == symbol->datatype)
     fprintf(stderr, "NULL\t\t");
-  else 
-    fprintf(stderr, symbol->datatype->absyntax_cname());
+  else {
+	  fprintf(stderr, "%s", symbol->datatype->absyntax_cname());
+  }
   fprintf(stderr, "\t<-{");
   if (symbol->candidate_datatypes.size() == 0) {
     fprintf(stderr, "\t\t\t\t\t");
@@ -97,9 +113,13 @@
       else
         fprintf(stderr, "\t\t\t");
   } else {
-    fprintf(stderr, "(%d)\t\t\t\t\t", symbol->candidate_datatypes.size());
+    fprintf(stderr, "(%lu)\t\t\t\t\t", (unsigned long int)symbol->candidate_datatypes.size());
   }
-  fprintf(stderr, "}\t");          
+  fprintf(stderr, "}\t");         
+  
+  /* print the const values... */
+  fprintf(stderr, " constv{f=%f, i=%"PRId64", u=%"PRIu64", b=%d}\t", symbol->const_value._real64.value, symbol->const_value._int64.value, symbol->const_value._uint64.value, symbol->const_value._bool.value?1:0);
+  
 }
 
 
@@ -107,8 +127,9 @@
 void *print_symbol_c::visit(il_instruction_c *symbol) {
    dump_symbol(symbol);
 
-  fprintf(stderr, "  next_il_=%d ", symbol->next_il_instruction.size());
-  fprintf(stderr, "  prev_il_=%d ", symbol->prev_il_instruction.size());
+   /* NOTE: std::map.size() returns a size_type, whose type is dependent on compiler/platform. To be portable, we need to do an explicit type cast. */
+  fprintf(stderr, "  next_il_=%lu ", (unsigned long int)symbol->next_il_instruction.size());
+  fprintf(stderr, "  prev_il_=%lu ", (unsigned long int)symbol->prev_il_instruction.size());
   
   if (symbol->prev_il_instruction.size() == 0)
     fprintf(stderr, "(----,");
@@ -137,10 +158,22 @@
 
 
 
-
-
-
-
+/*********************************/
+/* Class to print an AST         */
+/*********************************/
+
+class print_ast_c: public fcall_iterator_visitor_c { 
+  public:
+    static void print(symbol_c *symbol);
+    static void print(const char *str);
+    
+  protected:
+    void prefix_fcall(symbol_c *symbol);
+    void suffix_fcall(symbol_c *symbol);  
+  
+  private:
+    static print_ast_c *singleton;    
+};
 
 
 
@@ -155,6 +188,11 @@
   symbol->accept(*singleton);
 }
 
+
+void print_ast_c::print(const char *str) {
+  fprintf(stderr, str);
+}
+
   
 void print_ast_c::prefix_fcall(symbol_c* symbol) {print_symbol_c::print(symbol);}
 void print_ast_c::suffix_fcall(symbol_c* symbol) {}
@@ -163,14 +201,26 @@
 
 
 
-
-
-
-
-
-
-
-
-
-
-
+/*********************************/
+/* The DEBUG class               */
+/*********************************/
+
+
+
+
+void debug_c::print(const char *str) {
+  fprintf(stderr, str);
+}
+
+void debug_c::print(symbol_c *symbol) {
+  print_symbol_c::print(symbol);
+}
+
+void debug_c::print_ast(symbol_c *symbol) {
+  print_ast_c::print(symbol);
+}
+
+
+
+
+
--- a/absyntax_utils/debug_ast.hh	Mon Nov 12 22:36:55 2012 +0100
+++ b/absyntax_utils/debug_ast.hh	Thu Nov 22 19:19:48 2012 +0000
@@ -41,40 +41,16 @@
 
 
 
-#include "../absyntax/visitor.hh"
+#include "../absyntax/absyntax.hh"
 
 
-
-class print_symbol_c: public fcall_visitor_c { 
+class debug_c { 
   public:
     static void print(symbol_c *symbol);
-    
-  protected:
-    void fcall(symbol_c *symbol);  
-    /* AST symbols with extra data have their own specialised methods for printing that data */
-    void *visit(il_instruction_c *symbol);
+    static void print(const char *str);
 
-  private:
-    static print_symbol_c *singleton;
-    
-    void dump_symbol(symbol_c* symbol);
-};
-
-
-
-
-
-
-class print_ast_c: public fcall_iterator_visitor_c { 
-  public:
-    static void print(symbol_c *symbol);
-    
-  protected:
-  void prefix_fcall(symbol_c *symbol);
-  void suffix_fcall(symbol_c *symbol);  
-  
-  private:
-    static print_ast_c *singleton;    
+    /* print the AST from this point downwards */
+    static void print_ast(symbol_c *root_symbol);
 };
 
 
@@ -92,3 +68,5 @@
 
 
 
+
+
--- a/absyntax_utils/get_datatype_info.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/absyntax_utils/get_datatype_info.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -50,13 +50,78 @@
 #include <typeinfo>  // required for typeid
 
 
-
-
-
-
-
-
-
+/**********************************************************/
+/**********************************************************/
+/**********************************************************/
+/*****                                                *****/
+/*****                                                *****/
+/*****           Some helper classes                  *****/
+/*****                                                *****/
+/*****                                                *****/
+/**********************************************************/
+/**********************************************************/
+/**********************************************************/
+
+/* Return the identifier (name) of a datatype, typically declared in a TYPE .. END_TYPE declaration */
+class get_datatype_id_c: null_visitor_c {
+  private:
+    static get_datatype_id_c *singleton;
+    
+  public:
+    static symbol_c *get_id(symbol_c *symbol) {
+      if (NULL == singleton) singleton = new  get_datatype_id_c();
+      if (NULL == singleton) ERROR;
+      return (symbol_c *)symbol->accept(*singleton);
+    }
+    
+  protected:
+    /********************************/
+    /* B 1.3.3 - Derived data types */
+    /********************************/
+    /*  simple_type_name ':' simple_spec_init */
+    void *visit(simple_type_declaration_c *symbol)      {return symbol->simple_type_name;}
+    /*  subrange_type_name ':' subrange_spec_init */
+    void *visit(subrange_type_declaration_c *symbol)    {return symbol->subrange_type_name;}
+    /*  enumerated_type_name ':' enumerated_spec_init */
+    void *visit(enumerated_type_declaration_c *symbol)  {return symbol->enumerated_type_name;}
+    /*  identifier ':' array_spec_init */
+    void *visit(array_type_declaration_c *symbol)       {return symbol->identifier;}
+    /*  structure_type_name ':' structure_specification */
+    void *visit(structure_type_declaration_c *symbol)   {return symbol->structure_type_name;}
+    /*  string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */
+    void *visit(string_type_declaration_c *symbol)      {return symbol->string_type_name;}
+    
+    /*****************************/
+    /* B 1.5.2 - Function Blocks */
+    /*****************************/
+    /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
+    void *visit(function_block_declaration_c *symbol)      {return symbol->fblock_name;}
+}; // get_datatype_id_c 
+
+get_datatype_id_c *get_datatype_id_c::singleton = NULL;
+
+
+
+
+
+
+/**********************************************************/
+/**********************************************************/
+/**********************************************************/
+/*****                                                *****/
+/*****                                                *****/
+/*****        GET_DATATYPE_INFO_C                     *****/
+/*****                                                *****/
+/*****                                                *****/
+/**********************************************************/
+/**********************************************************/
+/**********************************************************/
+
+
+
+symbol_c *get_datatype_info_c::get_datatype_id(symbol_c *datatype) {
+  return get_datatype_id_c::get_id(datatype);
+}
 
 
 bool get_datatype_info_c::is_type_equal(symbol_c *first_type, symbol_c *second_type) {
--- a/absyntax_utils/get_datatype_info.hh	Mon Nov 12 22:36:55 2012 +0100
+++ b/absyntax_utils/get_datatype_info.hh	Thu Nov 22 19:19:48 2012 +0000
@@ -57,6 +57,8 @@
 
   
   public:
+    static symbol_c *get_datatype_id(symbol_c *datatype); /* get the identifier (name) of the datatype); returns NULL if anonymous datatype! */
+      
     static bool is_type_equal(symbol_c *first_type, symbol_c *second_type);
     static bool is_type_valid(symbol_c *type);
       
--- a/absyntax_utils/search_base_type.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/absyntax_utils/search_base_type.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -54,7 +54,7 @@
 
 
 
-search_base_type_c::search_base_type_c(void) {current_type_name = NULL;}
+search_base_type_c::search_base_type_c(void) {current_type_name = NULL; current_basetype = NULL;}
 
 /* static method! */
 void search_base_type_c::create_singleton(void) {
@@ -66,15 +66,17 @@
 symbol_c *search_base_type_c::get_basetype_decl(symbol_c *symbol) {
   create_singleton();
   if (NULL == symbol)    return NULL; 
+  search_base_type_singleton->current_type_name = NULL;
+  search_base_type_singleton->current_basetype  = NULL; 
   return (symbol_c *)symbol->accept(*search_base_type_singleton);
 }
 
 /* static method! */
 symbol_c *search_base_type_c::get_basetype_id  (symbol_c *symbol) {
   create_singleton();
-  if (NULL == symbol)    return NULL;
-  
+  if (NULL == symbol)    return NULL; 
   search_base_type_singleton->current_type_name = NULL;
+  search_base_type_singleton->current_basetype  = NULL; 
   symbol->accept(*search_base_type_singleton);
   return (symbol_c *)search_base_type_singleton->current_type_name;
 }
@@ -112,6 +114,10 @@
   symbol_c *type_decl;
 
   this->current_type_name = type_name;
+  /* if we have reached this point, it is because the current_basetype is not yet pointing to the base datatype we are looking for,
+   * so we will be searching for the delcaration of the type named in type_name, which might be the base datatype (we search recursively!)
+   */
+  this->current_basetype  = NULL; 
   
   /* look up the type declaration... */
   type_decl = type_symtable.find_value(type_name);
@@ -244,20 +250,37 @@
 /*  enumerated_type_name ':' enumerated_spec_init */
 void *search_base_type_c::visit(enumerated_type_declaration_c *symbol) {
   this->current_type_name = symbol->enumerated_type_name;
+  /* NOTE: We want search_base_type_c to return a enumerated_type_declaration_c as the base datatpe if possible
+   *       (i.e. if it is a named datatype declared inside a TYPE ... END_TYPE declarations, as opposed to an
+   *        anonymous datatype declared in a VAR ... AND_VAR declaration).
+   *       However, we cannot return this symbol just yet, as it may not be the final base datatype.
+   *       So we store it in a temporary current_basetype variable!
+   */
+  this->current_basetype  = symbol; 
   return symbol->enumerated_spec_init->accept(*this);
 }
 
 /* enumerated_specification ASSIGN enumerated_value */
 void *search_base_type_c::visit(enumerated_spec_init_c *symbol) {
   this->is_enumerated = true;
-  return symbol->enumerated_specification->accept(*this);
+  // current_basetype may have been set in the previous enumerated_type_declaration_c visitor, in which case we do not want to overwrite the value!
+  if (NULL == this->current_basetype)
+    this->current_basetype  = symbol; 
+  /* NOTE: the following line may call either the visitor to 
+   *         - identifier_c, in which case this is not yet the base datatype we are looking for (it will set current_basetype to NULL!)
+   *         - enumerated_value_list_c, in which case we have found the base datatype.
+   */
+  return symbol->enumerated_specification->accept(*this); 
 }
 
 /* helper symbol for enumerated_specification->enumerated_spec_init */
 /* enumerated_value_list ',' enumerated_value */
 void *search_base_type_c::visit(enumerated_value_list_c *symbol) {
   this->is_enumerated = true;
-  return (void *)symbol;
+  // current_basetype may have been set in the previous enumerated_type_declaration_c or enumerated_spec_init_c visitors, in which case we do not want to overwrite the value!
+  if (NULL == this->current_basetype) 
+    this->current_basetype  = symbol; 
+  return (void *)current_basetype;
 }
 
 /* enumerated_type_name '#' identifier */
--- a/absyntax_utils/search_base_type.hh	Mon Nov 12 22:36:55 2012 +0100
+++ b/absyntax_utils/search_base_type.hh	Thu Nov 22 19:19:48 2012 +0000
@@ -52,6 +52,7 @@
 
   private:
     symbol_c *current_type_name;
+    symbol_c *current_basetype;
     bool is_array;
     bool is_subrange;
     bool is_enumerated;
--- a/lib/iec_types.h	Mon Nov 12 22:36:55 2012 +0100
+++ b/lib/iec_types.h	Thu Nov 22 19:19:48 2012 +0000
@@ -32,7 +32,7 @@
 typedef struct {
     long int tv_sec;            /* Seconds.  */
     long int tv_nsec;           /* Nanoseconds.  */
-} IEC_TIMESPEC;
+} /* __attribute__((packed)) */ IEC_TIMESPEC;  /* packed is gcc specific! */
 
 typedef IEC_TIMESPEC IEC_TIME;
 typedef IEC_TIMESPEC IEC_DATE;
@@ -51,6 +51,6 @@
 typedef struct {
     __strlen_t len;
     uint8_t body[STR_MAX_LEN];
-} IEC_STRING;
+} /* __attribute__((packed)) */ IEC_STRING;  /* packed is gcc specific! */
 
 #endif /*IEC_TYPES_H*/
--- a/stage1_2/iec_bison.yy	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage1_2/iec_bison.yy	Thu Nov 22 19:19:48 2012 +0000
@@ -2549,10 +2549,13 @@
 
 simple_type_declaration:
 /*  simple_type_name ':' simple_spec_init */
-  identifier ':' simple_spec_init
-	{$$ = new simple_type_declaration_c($1, $3, locloc(@$));
-	 library_element_symtable.insert($1, prev_declared_simple_type_name_token);
-	}
+/* To understand why simple_spec_init was brocken up into its consituent components in the following rules, please see note in the definition of 'enumerated_type_declaration'. */
+  identifier ':' simple_specification           {library_element_symtable.insert($1, prev_declared_simple_type_name_token);}
+	{$$ = new simple_type_declaration_c($1, $3, locloc(@$));}
+| identifier ':' elementary_type_name           {library_element_symtable.insert($1, prev_declared_simple_type_name_token);} ASSIGN constant
+	{$$ = new simple_type_declaration_c($1, new simple_spec_init_c($3, $6, locf(@3), locl(@6)), locloc(@$));}
+| identifier ':' prev_declared_simple_type_name {library_element_symtable.insert($1, prev_declared_simple_type_name_token);} ASSIGN constant
+	{$$ = new simple_type_declaration_c($1, new simple_spec_init_c($3, $6, locf(@3), locl(@6)), locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | error ':' simple_spec_init
 	{$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid name defined for data type declaration.");yyerrok;}
@@ -2687,10 +2690,23 @@
 
 enumerated_type_declaration:
 /*  enumerated_type_name ':' enumerated_spec_init */
-  identifier ':' enumerated_spec_init
-	{$$ = new enumerated_type_declaration_c($1, $3, locloc(@$));
-	 library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);
-	}
+/* NOTE: The 'identifier' used for the name of the new enumerated type is inserted early into the library_element_symtable so it may be used
+ *       in defining the default initial value of this type, using the fully qualified enumerated constant syntax: type_name#enum_value
+ *       In other words, this allows us to correclty parse the following IEC 61131-3 code:
+ *           TYPE enum_t : (x1, x2, x3) := enum_t#x3; END_TYPE
+ *                                         ^^^^^^^
+ *
+ *       However, we can only introduce it after we are sure we are parsing an enumerated_spec. For this reason, instead of using the
+ *       symbol enumerated_spec_init in this rule, we decompose it here instead!
+ *       
+ *       If it were not for the above, we could use the rule
+ *           identifier ':' enumerated_spec_init
+ *       and include the library_element_symtable.insert(...) code in the rule actions!
+ */
+  identifier ':' enumerated_specification {library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);}
+	{$$ = new enumerated_type_declaration_c($1, new enumerated_spec_init_c($3, NULL, locloc(@3)), locloc(@$));}
+| identifier ':' enumerated_specification {library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);} ASSIGN enumerated_value
+	{$$ = new enumerated_type_declaration_c($1, new enumerated_spec_init_c($3, $6, locf(@3), locl(@6)), locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | error ':' enumerated_spec_init
 	{$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid name defined for enumerated type declaration."); yyerrok;}
--- a/stage1_2/iec_flex.ll	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage1_2/iec_flex.ll	Thu Nov 22 19:19:48 2012 +0000
@@ -416,7 +416,7 @@
 /* we are parsing a function, program or function block declaration */
 %s decl_state
 
-/* we will be parsing a function body. Whether il/st is remains unknown */
+/* we will be parsing a function body. Whether il/st/sfc remains to be determined */
 %x body_state
 
 /* we are parsing il code -> flex must return the EOL tokens!       */
@@ -924,8 +924,7 @@
 			       * calling yyterminate() is equivalent to doing that. 
 			       */ 	
 			    yyterminate();
-			  }      
- else {
+			  } else {
 			    --include_stack_ptr;
 			    yy_delete_buffer(YY_CURRENT_BUFFER);
 			    yy_switch_to_buffer((include_stack[include_stack_ptr]).buffer_state);
@@ -1735,12 +1734,10 @@
    *   return 0;
    */
 
-  /* to we stop processing...
-   *
+  /* to stop processing...
    *   return 1;
    */
 
-
   return 1;  /* Stop scanning at end of input file. */
 }
 
--- a/stage3/Makefile.am	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage3/Makefile.am	Thu Nov 22 19:19:48 2012 +0000
@@ -13,5 +13,6 @@
 	lvalue_check.cc \
 	array_range_check.cc \
         constant_folding.cc \
-        declaration_check.cc
+        declaration_check.cc \
+        enum_declaration_check.cc
 
--- a/stage3/Makefile.in	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage3/Makefile.in	Thu Nov 22 19:19:48 2012 +0000
@@ -83,7 +83,8 @@
 	forced_narrow_candidate_datatypes.$(OBJEXT) \
 	print_datatypes_error.$(OBJEXT) datatype_functions.$(OBJEXT) \
 	lvalue_check.$(OBJEXT) array_range_check.$(OBJEXT) \
-	constant_folding.$(OBJEXT) declaration_check.$(OBJEXT)
+	constant_folding.$(OBJEXT) declaration_check.$(OBJEXT) \
+	enum_declaration_check.$(OBJEXT)
 libstage3_a_OBJECTS = $(am_libstage3_a_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
 depcomp = $(SHELL) $(top_srcdir)/config/depcomp
@@ -209,7 +210,8 @@
 	lvalue_check.cc \
 	array_range_check.cc \
         constant_folding.cc \
-        declaration_check.cc
+        declaration_check.cc \
+        enum_declaration_check.cc
 
 all: all-am
 
@@ -291,6 +293,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constant_folding.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datatype_functions.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/declaration_check.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enum_declaration_check.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fill_candidate_datatypes.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flow_control_analysis.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/forced_narrow_candidate_datatypes.Po@am__quote@
--- a/stage3/constant_folding.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage3/constant_folding.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -253,7 +253,7 @@
   int64_t      ret;
   std::string  str = "";
   char        *endptr;
-  const char  *value;
+  const char  *value = NULL;
   int          base;
   integer_c         *integer;
   hex_integer_c     *hex_integer;
@@ -285,7 +285,7 @@
   uint64_t     ret;
   std::string  str = "";
   char        *endptr;
-  const char  *value;
+  const char  *value = NULL;
   int          base;
   integer_c         *integer;
   hex_integer_c     *hex_integer;
--- a/stage3/fill_candidate_datatypes.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage3/fill_candidate_datatypes.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -75,29 +75,6 @@
 
 
 
-#define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order)   ? (symbol1) : (symbol2))
-#define  LAST_(symbol1, symbol2) (((symbol1)->last_order  > (symbol2)->last_order)    ? (symbol1) : (symbol2))
-
-
-#define STAGE3_ERROR(error_level, symbol1, symbol2, ...) {                                                                  \
-    fprintf(stderr, "%s:%d-%d..%d-%d: error: ",                                                                             \
-            FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\
-                                                 LAST_(symbol1,symbol2) ->last_line,  LAST_(symbol1,symbol2) ->last_column);\
-    fprintf(stderr, __VA_ARGS__);                                                                                           \
-    fprintf(stderr, "\n");                                                                                                  \
-}  
-
-
-#define STAGE3_WARNING(symbol1, symbol2, ...) {                                                                             \
-    fprintf(stderr, "%s:%d-%d..%d-%d: warning: ",                                                                           \
-            FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\
-                                                 LAST_(symbol1,symbol2) ->last_line,  LAST_(symbol1,symbol2) ->last_column);\
-    fprintf(stderr, __VA_ARGS__);                                                                                           \
-    fprintf(stderr, "\n");                                                                                                  \
-}  
-
-
-
 /* set to 1 to see debug info during execution */
 static int debug = 0;
 
@@ -161,7 +138,6 @@
     for (; lower != upper; lower++)
       if (lower->second == current_enumerated_type) {
         /*  The same identifier is used more than once as an enumerated value/constant inside the same enumerated datat type! */
-        STAGE3_ERROR(0, symbol, symbol, "Duplicate identifier in enumerated data type.");
         return NULL; /* No need to insert it! It is already in the table! */
       }
 
@@ -229,13 +205,13 @@
 static enumerated_value_symtable_t local_enumerated_value_symtable;
 
 
-class populate_enumvalue_symtable_c: public iterator_visitor_c {
+class populate_localenumvalue_symtable_c: public iterator_visitor_c {
   private:
     symbol_c *current_enumerated_type;
 
   public:
-     populate_enumvalue_symtable_c(void) {current_enumerated_type = NULL;};
-    ~populate_enumvalue_symtable_c(void) {}
+     populate_localenumvalue_symtable_c(void) {current_enumerated_type = NULL;};
+    ~populate_localenumvalue_symtable_c(void) {}
 
   public:
   /*************************/
@@ -271,7 +247,6 @@
     for (; lower != upper; lower++)
       if (lower->second == current_enumerated_type) {
         /*  The same identifier is used more than once as an enumerated value/constant inside the same enumerated datat type! */
-        STAGE3_ERROR(0, symbol, symbol, "Duplicate identifier in enumerated data type.");
         return NULL; /* No need to insert it! It is already in the table! */
       }
     
@@ -281,7 +256,7 @@
   }
 }; // class populate_enumvalue_symtable_c
 
-static populate_enumvalue_symtable_c populate_enumvalue_symtable;
+static populate_localenumvalue_symtable_c populate_enumvalue_symtable;
 
 
 
@@ -879,13 +854,25 @@
 
 /*  enumerated_type_name ':' enumerated_spec_init */
 // SYM_REF2(enumerated_type_declaration_c, enumerated_type_name, enumerated_spec_init)
-/* NOTE: Not required. already handled by iterator_visitor_c base class */
+void *fill_candidate_datatypes_c::visit(enumerated_type_declaration_c *symbol) {
+  current_enumerated_spec_type = base_type(symbol);
+  add_datatype_to_candidate_list(symbol,                       current_enumerated_spec_type);
+  add_datatype_to_candidate_list(symbol->enumerated_type_name, current_enumerated_spec_type);
+  symbol->enumerated_spec_init->accept(*this);
+  current_enumerated_spec_type = NULL;  
+  return NULL;
+}
 
 
 /* enumerated_specification ASSIGN enumerated_value */
 // SYM_REF2(enumerated_spec_init_c, enumerated_specification, enumerated_value)
 void *fill_candidate_datatypes_c::visit(enumerated_spec_init_c *symbol) {
-  current_enumerated_spec_type = symbol;
+  /* If we are handling an anonymous datatype (i.e. a datatype implicitly declared inside a VAR ... END_VAR declaration)
+   * then the symbol->datatype has not yet been set by the previous visit(enumerated_spec_init_c) method!
+   */
+  if (NULL == current_enumerated_spec_type)
+    current_enumerated_spec_type = base_type(symbol);  
+  add_datatype_to_candidate_list(symbol, current_enumerated_spec_type);
   symbol->enumerated_specification->accept(*this); /* calls enumerated_value_list_c (or identifier_c, which we ignore!) visit method */
   current_enumerated_spec_type = NULL;  
   if (NULL != symbol->enumerated_value) symbol->enumerated_value->accept(*this);
@@ -896,20 +883,13 @@
 /* enumerated_value_list ',' enumerated_value */
 // SYM_LIST(enumerated_value_list_c)
 void *fill_candidate_datatypes_c::visit(enumerated_value_list_c *symbol) {
-  if (NULL == current_enumerated_spec_type) ERROR;
-  
-  /* Actually, all this passing of symbol_c * through the  current_enumerated_spec_type is actually useless, as the base type
-   * is actually this enumerated_value_list_c symbol!!! However, it is safer to do it this way, as we can then later change 
-   * search_base_type_c without having to change this fill_candidate_datatypes_c class too!!
-   */
-  current_enumerated_spec_type = base_type(current_enumerated_spec_type);
-  if (NULL == current_enumerated_spec_type) ERROR;
+  if (NULL == current_enumerated_spec_type) ERROR;  
+  add_datatype_to_candidate_list(symbol, current_enumerated_spec_type);
   
   /* We already know the datatype of the enumerated_value(s) in the list, so we set them directly instead of recursively calling the enumerated_value_c visit method! */
-  for(int i = 0; i < symbol->n; i++) {
+  for(int i = 0; i < symbol->n; i++)
     add_datatype_to_candidate_list(symbol->elements[i], current_enumerated_spec_type);
-    symbol->elements[i]->datatype = current_enumerated_spec_type; // To be consistent, this should really be done in the narrow_candidate_datatypes_c !!
-  }
+
   return NULL;  
 }
 
@@ -930,15 +910,10 @@
 void *fill_candidate_datatypes_c::visit(enumerated_value_c *symbol) {
 	symbol_c *global_enumerated_type;
 	symbol_c *local_enumerated_type;
-	symbol_c *enumerated_type;
+	symbol_c *enumerated_type = NULL;
 
 	if (NULL != symbol->type) {
-#if 1
-		enumerated_type = symbol->type; 
-#else
-		/* NOTE: The following code works but is not complete, that is why it is currently commented out!
-		 *  
-		 *        It is not complete because it does not yet consider the following situation:
+		/* NOTE: This code must take into account the following situation:
 		 *
 		 *        TYPE  
 		 *           base_enum_t: (x1, x2, x3);
@@ -952,10 +927,6 @@
 		 *             enum_t1#x1
 		 *             enum_t2#x1
 		 *            enum_t12#x1
-		 *
-		 *      However, the following code only considers 
- 		 *         base_enum_t#x1
-		 *      as correct, and all the others as incorrect!
 		 */
 		/* check whether the value really belongs to that datatype!! */
 		/* All local enum values are declared inside anonymous enumeration datatypes (i.e. inside a VAR ... END_VAR declaration, with
@@ -966,9 +937,8 @@
 		enumerated_value_symtable_t::iterator lower = global_enumerated_value_symtable.lower_bound(symbol->value);
 		enumerated_value_symtable_t::iterator upper = global_enumerated_value_symtable.upper_bound(symbol->value);
 		for (; lower != upper; lower++)
-			if (compare_identifiers(search_base_type_c::get_basetype_id(lower->second), symbol->type) == 0)  // returns 0 if identifiers are equal!!
+			if (get_datatype_info_c::is_type_equal(base_type(lower->second), base_type(symbol->type)))
 				enumerated_type = symbol->type; 
-#endif
 	}
 	else {
 		symbol_c *global_enumerated_type = global_enumerated_value_symtable.find_value  (symbol->value);
@@ -1132,11 +1102,12 @@
 /******************************************/
 
 void *fill_candidate_datatypes_c::visit(var1_list_c *symbol) {
-#if 0   /* We don't really need to set the datatype of each variable. We just check the declaration itself! */
   for(int i = 0; i < symbol->n; i++) {
-    add_datatype_to_candidate_list(symbol->elements[i], search_varfb_instance_type->get_basetype_decl(symbol->elements[i])); /* will only add if non NULL */
+    /* We don't really need to set the datatype of each variable. We just check the declaration itself! 
+    add_datatype_to_candidate_list(symbol->elements[i], search_varfb_instance_type->get_basetype_decl(symbol->elements[i])); // will only add if non NULL 
+    */
+    symbol->elements[i]->accept(*this); // handle the extensible_input_parameter_c, etc...
   }
-#endif
   return NULL;
 }  
 
--- a/stage3/fill_candidate_datatypes.hh	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage3/fill_candidate_datatypes.hh	Thu Nov 22 19:19:48 2012 +0000
@@ -175,7 +175,7 @@
 //  void *visit(subrange_spec_init_c *symbol);
 //  void *visit(subrange_specification_c *symbol);
     void *visit(subrange_c *symbol);
-//  void *visit(enumerated_type_declaration_c *symbol); /* Not required. already handled by iterator_visitor_c base class */
+    void *visit(enumerated_type_declaration_c *symbol);
     void *visit(enumerated_spec_init_c *symbol);
     void *visit(enumerated_value_list_c *symbol);
     void *visit(enumerated_value_c *symbol);
--- a/stage3/narrow_candidate_datatypes.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage3/narrow_candidate_datatypes.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -414,9 +414,8 @@
 	return search_base_type_c::get_basetype_decl(symbol);
 }
 
-/*********************/
-/* B 1.2 - Constants */
-/*********************/
+
+
 
 /**********************/
 /* B 1.3 - Data types */
@@ -424,6 +423,18 @@
 /********************************/
 /* B 1.3.3 - Derived data types */
 /********************************/
+/*  TYPE type_declaration_list END_TYPE */
+// SYM_REF1(data_type_declaration_c, type_declaration_list)
+/* NOTE: Not required. already handled by iterator_visitor_c base class */
+
+/* helper symbol for data_type_declaration */
+// SYM_LIST(type_declaration_list_c)
+/* NOTE: Not required. already handled by iterator_visitor_c base class */
+
+/*  simple_type_name ':' simple_spec_init */
+// SYM_REF2(simple_type_declaration_c, simple_type_name, simple_spec_init)
+/* NOTE: Not required. already handled by iterator_visitor_c base class */
+
 /* simple_specification ASSIGN constant */
 // SYM_REF2(simple_spec_init_c, simple_specification, constant)
 void *narrow_candidate_datatypes_c::visit(simple_spec_init_c *symbol) {
@@ -441,9 +452,18 @@
 }
 
 
+/*  subrange_type_name ':' subrange_spec_init */
+// SYM_REF2(subrange_type_declaration_c, subrange_type_name, subrange_spec_init)
+
+/* subrange_specification ASSIGN signed_integer */
+// SYM_REF2(subrange_spec_init_c, subrange_specification, signed_integer)
+
+/*  integer_type_name '(' subrange')' */
+// SYM_REF2(subrange_specification_c, integer_type_name, subrange)
 
 /*  signed_integer DOTDOT signed_integer */
-// SYM_REF2(subrange_c, lower_limit, upper_limit)
+/* dimension will be filled in during stage 3 (array_range_check_c) with the number of elements in this subrange */
+// SYM_REF2(subrange_c, lower_limit, upper_limit, unsigned long long int dimension;)
 void *narrow_candidate_datatypes_c::visit(subrange_c *symbol) {
 	symbol->lower_limit->datatype = symbol->datatype;
 	symbol->lower_limit->accept(*this);
@@ -453,6 +473,112 @@
 }
 
 
+/*  enumerated_type_name ':' enumerated_spec_init */
+// SYM_REF2(enumerated_type_declaration_c, enumerated_type_name, enumerated_spec_init)
+void *narrow_candidate_datatypes_c::visit(enumerated_type_declaration_c *symbol) {
+  if (symbol->candidate_datatypes.size() != 1) ERROR;
+  
+  symbol->datatype = symbol->candidate_datatypes[0];
+  set_datatype(symbol->datatype, symbol->enumerated_type_name);
+  set_datatype(symbol->datatype, symbol->enumerated_spec_init);
+  
+  symbol->enumerated_spec_init->accept(*this);
+  return NULL;
+}
+
+
+/* enumerated_specification ASSIGN enumerated_value */
+// SYM_REF2(enumerated_spec_init_c, enumerated_specification, enumerated_value)
+void *narrow_candidate_datatypes_c::visit(enumerated_spec_init_c *symbol) {
+  /* If we are handling an anonymous datatype (i.e. a datatype implicitly declared inside a VAR ... END_VAR declaration)
+   * then the symbol->datatype has not yet been set by the previous visit(enumerated_spec_init_c) method!
+   */
+  if (NULL == symbol->datatype) {
+    if (symbol->candidate_datatypes.size() != 1) ERROR;
+    symbol->datatype = symbol->candidate_datatypes[0];
+  }
+  set_datatype(symbol->datatype, symbol->enumerated_specification);
+  if (NULL != symbol->enumerated_value) 
+    set_datatype(symbol->datatype, symbol->enumerated_value);
+
+  symbol->enumerated_specification->accept(*this); /* calls enumerated_value_list_c (or identifier_c, which we ignore!) visit method */
+  return NULL;
+}
+
+/* helper symbol for enumerated_specification->enumerated_spec_init */
+/* enumerated_value_list ',' enumerated_value */
+// SYM_LIST(enumerated_value_list_c)
+void *narrow_candidate_datatypes_c::visit(enumerated_value_list_c *symbol) {
+  if (NULL == symbol->datatype) ERROR;
+  
+  for(int i = 0; i < symbol->n; i++) {
+    /* the enumerated_value_c objects to which this list points to has both the datatype and the candidate_datatype_list filled in, so we 
+     * call set_datatype() instead of setting the datatype directly!
+     */
+    set_datatype(symbol->datatype, symbol->elements[i]);
+    if (NULL == symbol->elements[i]->datatype) ERROR;
+  }
+  return NULL;  
+}
+
+
+/* enumerated_type_name '#' identifier */
+// SYM_REF2(enumerated_value_c, type, value)
+// void *narrow_candidate_datatypes_c::visit(enumerated_value_c *symbol) {/* do nothing! */ return NULL;}
+
+
+/*  identifier ':' array_spec_init */
+// SYM_REF2(array_type_declaration_c, identifier, array_spec_init)
+
+/* array_specification [ASSIGN array_initialization} */
+/* array_initialization may be NULL ! */
+// SYM_REF2(array_spec_init_c, array_specification, array_initialization)
+
+/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+// SYM_REF2(array_specification_c, array_subrange_list, non_generic_type_name)
+
+/* helper symbol for array_specification */
+/* array_subrange_list ',' subrange */
+// SYM_LIST(array_subrange_list_c)
+
+/* array_initialization:  '[' array_initial_elements_list ']' */
+/* helper symbol for array_initialization */
+/* array_initial_elements_list ',' array_initial_elements */
+// SYM_LIST(array_initial_elements_list_c)
+
+/* integer '(' [array_initial_element] ')' */
+/* array_initial_element may be NULL ! */
+// SYM_REF2(array_initial_elements_c, integer, array_initial_element)
+
+/*  structure_type_name ':' structure_specification */
+// SYM_REF2(structure_type_declaration_c, structure_type_name, structure_specification)
+
+/* structure_type_name ASSIGN structure_initialization */
+/* structure_initialization may be NULL ! */
+// SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
+
+/* helper symbol for structure_declaration */
+/* structure_declaration:  STRUCT structure_element_declaration_list END_STRUCT */
+/* structure_element_declaration_list structure_element_declaration ';' */
+// SYM_LIST(structure_element_declaration_list_c)
+
+/*  structure_element_name ':' *_spec_init */
+// SYM_REF2(structure_element_declaration_c, structure_element_name, spec_init)
+
+/* helper symbol for structure_initialization */
+/* structure_initialization: '(' structure_element_initialization_list ')' */
+/* structure_element_initialization_list ',' structure_element_initialization */
+// SYM_LIST(structure_element_initialization_list_c)
+
+/*  structure_element_name ASSIGN value */
+// SYM_REF2(structure_element_initialization_c, structure_element_name, value)
+
+/*  string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */
+// SYM_REF4(string_type_declaration_c, string_type_name, elementary_string_type_name, string_type_declaration_size, string_type_declaration_init/* may be == NULL! */) 
+
+
+
+
 /*********************/
 /* B 1.4 - Variables */
 /*********************/
--- a/stage3/narrow_candidate_datatypes.hh	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage3/narrow_candidate_datatypes.hh	Thu Nov 22 19:19:48 2012 +0000
@@ -96,8 +96,31 @@
     /********************************/
     /* B 1.3.3 - Derived data types */
     /********************************/
+//  void *visit(data_type_declaration_c *symbol);   /* Not required. already handled by iterator_visitor_c base class */
+//  void *visit(type_declaration_list_c *symbol);   /* Not required. already handled by iterator_visitor_c base class */
+//  void *visit(simple_type_declaration_c *symbol); /* Not required. already handled by iterator_visitor_c base class */
+    void *visit(simple_spec_init_c *symbol);
+//  void *visit(subrange_type_declaration_c *symbol);
+//  void *visit(subrange_spec_init_c *symbol);
+//  void *visit(subrange_specification_c *symbol);
     void *visit(subrange_c *symbol);
-    void *visit(simple_spec_init_c *symbol);
+    void *visit(enumerated_type_declaration_c *symbol);
+    void *visit(enumerated_spec_init_c *symbol);
+    void *visit(enumerated_value_list_c *symbol);
+//  void *visit(enumerated_value_c *symbol);        /* Not required */
+//  void *visit(array_type_declaration_c *symbol);
+//  void *visit(array_spec_init_c *symbol);
+//  void *visit(array_specification_c *symbol);
+//  void *visit(array_subrange_list_c *symbol);
+//  void *visit(array_initial_elements_list_c *symbol);
+//  void *visit(array_initial_elements_c *symbol);
+//  void *visit(structure_type_declaration_c *symbol);
+//  void *visit(initialized_structure_c *symbol);
+//  void *visit(structure_element_declaration_list_c *symbol);
+//  void *visit(structure_element_declaration_c *symbol);
+//  void *visit(structure_element_initialization_list_c *symbol);
+//  void *visit(structure_element_initialization_c *symbol);
+//  void *visit(string_type_declaration_c *symbol);
 
     /*********************/
     /* B 1.4 - Variables */
--- a/stage3/print_datatypes_error.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage3/print_datatypes_error.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -536,11 +536,6 @@
 	return NULL;
 }
 
-void *print_datatypes_error_c::visit(data_type_declaration_c *symbol) {
-	// TODO !!!
-	/* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
-	return NULL;
-}
 
 void *print_datatypes_error_c::visit(enumerated_value_c *symbol) {
 	if (symbol->candidate_datatypes.size() == 0)
@@ -648,8 +643,7 @@
 /*********************/
 void *print_datatypes_error_c::visit(function_declaration_c *symbol) {
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
-	/* We do not check for data type errors in variable declarations, Skip this for now... */
-// 	symbol->var_declarations_list->accept(*this);
+ 	symbol->var_declarations_list->accept(*this);
 	if (debug) printf("Print error data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
 	il_parenthesis_level = 0;
 	il_error = false;
@@ -664,8 +658,7 @@
 /***************************/
 void *print_datatypes_error_c::visit(function_block_declaration_c *symbol) {
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
-	/* We do not check for data type errors in variable declarations, Skip this for now... */
-// 	symbol->var_declarations->accept(*this);
+ 	symbol->var_declarations->accept(*this);
 	if (debug) printf("Print error data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
 	il_parenthesis_level = 0;
 	il_error = false;
@@ -680,7 +673,6 @@
 /**********************/
 void *print_datatypes_error_c::visit(program_declaration_c *symbol) {
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
-	/* We do not check for data type errors in variable declarations, Skip this for now... */
 	symbol->var_declarations->accept(*this);
 	if (debug) printf("Print error data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
 	il_parenthesis_level = 0;
--- a/stage3/print_datatypes_error.hh	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage3/print_datatypes_error.hh	Thu Nov 22 19:19:48 2012 +0000
@@ -159,7 +159,7 @@
     /* B 1.3.3 - Derived data types */
     /********************************/
     void *visit(simple_spec_init_c *symbol);
-    void *visit(data_type_declaration_c *symbol);
+//  void *visit(data_type_declaration_c *symbol); /* use base iterator_c method! */
     void *visit(enumerated_value_c *symbol);
 
     /*********************/
--- a/stage3/stage3.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage3/stage3.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -43,6 +43,15 @@
 #include "array_range_check.hh"
 #include "constant_folding.hh"
 #include "declaration_check.hh"
+#include "enum_declaration_check.hh"
+
+
+static int enum_declaration_check(symbol_c *tree_root){
+    enum_declaration_check_c enum_declaration_check(NULL);
+    tree_root->accept(enum_declaration_check);
+    return enum_declaration_check.get_error_count();
+}
+
 
 static int declaration_safety(symbol_c *tree_root){
     declaration_check_c declaration_check(tree_root);
@@ -107,6 +116,7 @@
 
 int stage3(symbol_c *tree_root){
 	int error_count = 0;
+	error_count += enum_declaration_check(tree_root);
 	error_count += declaration_safety(tree_root);
 	error_count += flow_control_analysis(tree_root);
 	error_count += constant_folding(tree_root);
--- a/stage4/generate_c/generate_c_typedecl.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage4/generate_c/generate_c_typedecl.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -317,8 +317,15 @@
   if (current_typedefinition == enumerated_td)
     current_type_name->accept(*basedecl);
   else {
-    if (NULL == symbol->datatype) ERROR;
-    symbol->datatype->accept(*basedecl);
+    if (NULL == symbol->datatype) {
+      debug_c::print(symbol);
+      ERROR;
+    }
+    symbol_c *type_name = get_datatype_info_c::get_datatype_id(symbol->datatype);
+    if (NULL == type_name) {
+//       ERROR_MSG("generate_c does not support anonymous enumerated data types.");
+    } else
+    type_name->accept(*basedecl);
   }
   s4o_incl.print("__");
   symbol->value->accept(*basedecl);
--- a/stage4/generate_c/generate_var_list.cc	Mon Nov 12 22:36:55 2012 +0100
+++ b/stage4/generate_c/generate_var_list.cc	Thu Nov 22 19:19:48 2012 +0000
@@ -382,6 +382,40 @@
       }
     }
 
+
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+    /*  enumerated_type_name ':' enumerated_spec_init */
+    void *visit(enumerated_type_declaration_c *symbol) {
+      this->current_var_type_name->accept(*this);
+      return NULL;
+    }
+
+    /* enumerated_specification ASSIGN enumerated_value */
+    void *visit(enumerated_spec_init_c *symbol) {
+      /* search_base_type_c now returns an enumerated_type_declaration_c as the base type of a non-anonymous enumerated type
+       * (non-anonymous means it is declared inside a TYPE ... END_TYPE declaration, with a given name/identifier
+       *  unlike implicitly defined anonymous datatypes declared inside VAR ... END_VAR declarations!).
+       * This means that this method should not get called.
+       */
+      ERROR;  
+      this->current_var_type_name->accept(*this);
+      return NULL;
+    }
+
+    /* enumerated_value_list ',' enumerated_value */
+    void *visit(enumerated_value_list_c *symbol) {
+      /* search_base_type_c now returns an enumerated_type_declaration_c as the base type of a non-anonymous enumerated type
+       * (non-anonymous means it is declared inside a TYPE ... END_TYPE declaration, with a given name/identifier
+       *  unlike implicitly defined anonymous datatypes declared inside VAR ... END_VAR declarations!).
+       * This means that this method should not get called.
+       */
+      ERROR;
+      this->current_var_type_name->accept(*this);
+      return NULL;
+    }
+
 /********************************************/
 /* B.1.4.3 - Declaration and initialization */
 /********************************************/
@@ -556,12 +590,7 @@
       return NULL;
     }
 
-    /* enumerated_value_list ',' enumerated_value */
-    void *visit(enumerated_value_list_c *symbol) {
-      this->current_var_type_name->accept(*this);
-      return NULL;
-    }
-    
+
     /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
     /* structure_initialization -> may be NULL ! */
     void *visit(fb_name_decl_c *symbol) {