merge
authormjsousa
Sun, 16 Nov 2014 15:37:12 +0000
changeset 947 aca1ab9fcb6d
parent 944 d6d9211e9aab (current diff)
parent 946 c012a64dc2fa (diff)
child 948 543f8319bdf8
child 960 27063736913f
merge
stage4/generate_c/generate_c_base.cc
--- a/absyntax/absyntax.def	Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax/absyntax.def	Sun Nov 16 15:37:12 2014 +0000
@@ -125,6 +125,9 @@
 /* B 1.1 - Letters, digits and identifiers */
 /*******************************************/
 SYM_TOKEN(identifier_c)
+/* A special identifier class, used for identifiers that have been previously declared as a derived datatype */
+/*  This is currently needed because generate_c stage 4 needs to handle the array datatype identifiers differently to all other identifiers. */
+SYM_TOKEN(derived_datatype_identifier_c) 
 
 
 /*********************/
--- a/absyntax_utils/get_datatype_info.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/get_datatype_info.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -43,7 +43,7 @@
  */
 #include "absyntax_utils.hh"
 
-#include "../main.hh" // required for ERROR() and ERROR_MSG() macros.
+#include "../main.hh" // required for ERROR() and ERROR_MSG() macros, as well as the runtime_options global variable
 
 
 
@@ -199,7 +199,8 @@
     /*******************************************/
     /* B 1.1 - Letters, digits and identifiers */
     /*******************************************/
-    void *visit(identifier_c *symbol) {return (void *)symbol->value;};
+    void *visit(                 identifier_c *symbol) {return (void *)symbol->value;};
+    void *visit(derived_datatype_identifier_c *symbol) {return (void *)symbol->value;};
 
     /***********************************/
     /* B 1.3.1 - Elementary Data Types */
@@ -249,6 +250,11 @@
     void *visit(safewstring_type_name_c *symbol) {return (void *)"SAFEWSTRING"; };
 
     /********************************/
+    /* B.1.3.2 - Generic data types */
+    /********************************/
+    void *visit(generic_type_any_c *symbol) {return (void *)"ANY"; };
+
+    /********************************/
     /* B 1.3.3 - Derived data types */
     /********************************/
     /*  simple_type_name ':' simple_spec_init */
@@ -417,17 +423,21 @@
   return get_struct_info_c::get_field_type_id(struct_datatype, struct_fieldname);
 }
 
+
+
 symbol_c *get_datatype_info_c::get_array_storedtype_id(symbol_c *type_symbol) {
   // returns the datatype of the variables stored in the array
-  symbol_c *basetype = search_base_type_c::get_basetype_decl(type_symbol);
-  array_specification_c *symbol = dynamic_cast<array_specification_c *>(basetype);
-
-  if (NULL != symbol) 
+  array_specification_c *symbol = NULL;
+  if (NULL == symbol)  symbol = dynamic_cast<array_specification_c *>(type_symbol);
+  if (NULL == symbol)  symbol = dynamic_cast<array_specification_c *>(search_base_type_c::get_basetype_decl(type_symbol));
+  if (NULL != symbol)  
     return symbol->non_generic_type_name;
   return NULL; // this is not an array!
 }
   
   
+  
+
 /* Returns true if both datatypes are equivalent (not necessarily equal!).
  * WARNING: May return true even though the datatypes are not the same/identicial!!!
  *          This occurs when at least one of the datatypes is of a generic
@@ -439,7 +449,13 @@
  *       this function will currently only return true if the dataypes are identicial.
  */
 
-/* NOTE: Currently the datatype model used by matiec considers any implicitly defined datatype
+/* NOTE: matiec supports a strict and a relaxed data type model. Which datatype model to use is chosen
+ *       as a command line option.
+ * 
+ * 
+ *       The Strict Datatype Model
+ *       =========================
+ *       The strict datatype model used by matiec considers any implicitly defined datatype
  *       (e.g. an array datatype defined in the variable declaration itself, instead of inside a TYPE ... END_TYPE
  *       construct) to be different (i.e. not the same datatype, and therefore not compatible) to any other
  *       datatype, including with datatypes declared identically to the implicit datatype.
@@ -459,6 +475,8 @@
  *              (this rule is specified in the standard, so we follow it!)
  *        (2) REF_TO datatypes that reference the same datatype
  *              (I dont think the standard says anything about this!)
+ *              (This rule should actually be part of the relaxed datatype model, but for now we
+ *               will leave it in the strict datatype model) 
  *
  *         TYPE 
  *          my_array_1_t: ARRAY [1..3] OF INT; 
@@ -511,6 +529,29 @@
  *       This rule was adopted as without it, the datatype of the value returned by the REF() 
  *       operator would be considered distinct to all other datatypes, and therefore the
  *       REF() operator would be essentially useless.
+ * 
+ * 
+ *       The Relaxed Datatype Model
+ *       ==========================
+ *       In the relaxed datatype model, the same rules as the strict datatype model are followed, with the
+ *       exception of implicitly defined array datatypes, which are now considered equal if they define
+ *       identical datatypes.
+ *       This means that in the following example
+ *         TYPE 
+ *          array_t: ARRAY [1..3] OF INT; 
+ *         END_TYPE;
+ *         VAR
+ *          array_var1: array_t; 
+ *          array_var2: ARRAY [1..3] OF INT; 
+ *          array_var3: ARRAY [1..3] OF INT; 
+ *         END_VAR
+ * 
+ *       all three variables (array_var1, array_var2, and array_var3) are considered as being of the
+ *       same datatype.
+ *      
+ *       Note that the strict datatype model currently actually uses a relaxed datatype model for 
+ *       REF_TO datatypes, so in both the relaxed and strict datatype models matiec currently uses a 
+ *       relaxed datatype equivalince for REF_TO datatypes.
  */
 bool get_datatype_info_c::is_type_equal(symbol_c *first_type, symbol_c *second_type) {
   if (!is_type_valid( first_type))                                   {return false;}
@@ -522,16 +563,116 @@
       (is_ANY_generic_type(second_type)))                            {return true;}
       
   /* ANY_ELEMENTARY */
-  if ((is_ANY_ELEMENTARY(first_type)) &&
+  if ((is_ANY_ELEMENTARY_compatible(first_type)) &&
       (typeid(*first_type) == typeid(*second_type)))                 {return true;}
-
-  /* ANY_DERIVED */
+  if (   is_ANY_ELEMENTARY_compatible(first_type) 
+      || is_ANY_ELEMENTARY_compatible(second_type))                  {return false;}  
+  
+  /* ANY_DERIVED  */
+  // from now on, we are sure both datatypes are derived...
   if (is_ref_to(first_type) && is_ref_to(second_type)) {
     return is_type_equal(search_base_type_c::get_basetype_decl(get_ref_to(first_type )),
                          search_base_type_c::get_basetype_decl(get_ref_to(second_type)));
   }
-  return (first_type == second_type);
-}
+
+    // check for same datatype
+  if (first_type == second_type)                                     {return true;}
+  
+    // remaining type equivalence rules are not applied in the strict datatype model
+  if (false == runtime_options.relaxed_datatype_model)               {return false;}
+  
+    // check for array equivalence usig the relaxed datatype model
+  if (is_arraytype_equal_relaxed(first_type, second_type))           {return true;}
+
+  return false;
+}
+
+
+
+/* A local helper function that transforms strings conatining signed_integers into a normalized
+ * form, so they can be compared for equality.
+ *   examples:
+ *     82  ->  82 
+ *     8_2 ->  82 
+ *    +82  ->  82
+ *    082  ->  82
+ *   +082  ->  82
+ *    -82  -> -82
+ *    -8_2 -> -82
+ *   -082  -> -82
+ */
+#include <string.h>  /* required for strlen() */
+static std::string normalize_integer(symbol_c *symbol) {
+  integer_c *token = dynamic_cast<integer_c *>(symbol);
+  if (NULL == token) ERROR;
+  
+  std::string str = "";
+  bool leading_zero = true;
+  unsigned int offset = 0;
+
+  // handle any possible leading '-' or '+'
+  if        (token->value[0] == '-') {
+      //    '-' -> retained
+      str += token->value[0];
+      offset++;
+  } else if (token->value[0] == '+')
+      //    '+' -> skip, so '+8' and '8' will both result in '8'
+      offset++;
+    
+  for (unsigned int i = offset; i < strlen(token->value); i++) {
+    if (leading_zero && (token->value[i] != '0'))
+      leading_zero = false;
+    if (!leading_zero && token->value[i] != '_')
+      str += token->value[i];
+  }
+  return str;
+}
+
+
+/* A helper method to get_datatype_info_c::is_type_equal()
+ *  Assuming the relaxed datatype model, determine whether the two array datatypes are equal/equivalent
+ */
+bool get_datatype_info_c::is_arraytype_equal_relaxed(symbol_c *first_type, symbol_c *second_type) {
+  symbol_c *basetype_1 = search_base_type_c::get_basetype_decl( first_type);
+  symbol_c *basetype_2 = search_base_type_c::get_basetype_decl(second_type);
+  array_specification_c *array_1 = dynamic_cast<array_specification_c *>(basetype_1);
+  array_specification_c *array_2 = dynamic_cast<array_specification_c *>(basetype_2);
+
+  // are they both array datatypes? 
+  if ((NULL == array_1) || (NULL == array_2))
+    return false;
+  
+  // number of subranges
+  array_subrange_list_c *subrange_list_1 = dynamic_cast<array_subrange_list_c *>(array_1->array_subrange_list);
+  array_subrange_list_c *subrange_list_2 = dynamic_cast<array_subrange_list_c *>(array_2->array_subrange_list);
+  if ((NULL == subrange_list_1) || (NULL == subrange_list_2)) ERROR;
+  if (subrange_list_1->n != subrange_list_2->n)
+    return false;
+  
+  // comparison of each subrange start and end elements
+  for (int i = 0; i < subrange_list_1->n; i++) {
+    subrange_c *subrange_1 = dynamic_cast<subrange_c *>(subrange_list_1->elements[i]);
+    subrange_c *subrange_2 = dynamic_cast<subrange_c *>(subrange_list_2->elements[i]);
+    if ((NULL == subrange_1) || (NULL == subrange_2)) ERROR;
+    #if 0
+    /* An alternative method of checking whether the subranges have the same values, using the result of the constant folding agorithm.
+     * This method has the drawback that it inserts a dependency on having to run the constant folding algorithm before
+     *  the get_datatype_info_c::is_type_equal() method is called.
+     * The probably slower alternative of comparing the strings themselves is therefor used.
+     */
+    if (!constant_folding_c::is_equal_cvalue(subrange_1->lower_limit, subrange_2->lower_limit)) return false;
+    if (!constant_folding_c::is_equal_cvalue(subrange_1->upper_limit, subrange_2->upper_limit)) return false;
+    #endif
+    if (normalize_integer(subrange_1->lower_limit) != normalize_integer(subrange_2->lower_limit)) return false;
+    if (normalize_integer(subrange_1->upper_limit) != normalize_integer(subrange_2->upper_limit)) return false;
+  }
+
+  return is_type_equal(search_base_type_c::get_basetype_decl(array_1->non_generic_type_name),
+                       search_base_type_c::get_basetype_decl(array_2->non_generic_type_name));
+}
+
+
+
 
 
 bool get_datatype_info_c::is_type_valid(symbol_c *type) {
--- a/absyntax_utils/get_datatype_info.hh	Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/get_datatype_info.hh	Sun Nov 16 15:37:12 2014 +0000
@@ -55,6 +55,9 @@
      get_datatype_info_c(void) {};
     ~get_datatype_info_c(void) {};
 
+    // A helper method to get_datatype_info_c::is_type_equal()
+    // Assuming the relaxed datatype model, return whether the two array datatypes are equal/equivalent
+    static bool is_arraytype_equal_relaxed(symbol_c *first_type, symbol_c *second_type);
   
   public:
     static symbol_c   *get_id    (symbol_c *datatype); /* get the identifier (name) of the datatype); returns NULL if anonymous datatype! Does not work for elementary datatypes!*/
@@ -65,14 +68,17 @@
     static symbol_c *get_ref_to                    (symbol_c *type_symbol);    // Defined in IEC 61131-3 v3 (returns the type that is being referenced/pointed to)        
     
     /* Returns true if both datatypes are equivalent (not necessarily equal!).
-     * WARNING: May return true even though the datatypes are not the same/identicial!!!
-     *          This occurs when at least one of the datatypes is of a generic
-     *          datatype (or a REF_TO a generic datatype). 
-     *          (Generic dataypes: ANY, ANY_INT, ANY_NUM, ...)
+     * Two datatype models are supported: relaxed and strict (chosen from a command line option).
+     * WARNING: May return true even though the datatypes are not the same/identical!!!
+     *          In both of the models, this may occur when at least one of the datatypes is of a generic
+     *          datatype (Generic dataypes: ANY, ANY_INT, ANY_NUM, ...), 
+     *          or when two REF_TO datatypes both reference an equivalent datatype.
+     *          In only the relaxed datatype, it may also return true if two array datatypes
+     *          have the same subrange limits, and contain the same data. 
+     *          
      * NOTE: Currently only the ANY generic datatype is implemented!
      * NOTE: Currently stage1_2 only allows the use of the ANY keyword when in conjuntion with
-     *       the REF_TO keyword (i.e. REF_TO ANY), so when handling non REF_TO datatypes,
-     *       this function will currently only return true if the dataypes are identicial.
+     *       the REF_TO keyword (i.e. REF_TO ANY).
      */
     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	Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/search_base_type.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -105,7 +105,9 @@
 /*******************************************/
 /* B 1.1 - Letters, digits and identifiers */
 /*******************************************/
-void *search_base_type_c::visit(identifier_c *type_name) {
+
+
+void *search_base_type_c::handle_datatype_identifier(token_c *type_name) {
   symbol_c *type_decl;
 
   this->current_basetype_name = type_name;
@@ -129,6 +131,9 @@
   return NULL;
 }
 
+void *search_base_type_c::visit(                 identifier_c *type_name) {return handle_datatype_identifier(type_name);}  // still needed to handle FB and program datatypes!
+void *search_base_type_c::visit(derived_datatype_identifier_c *type_name) {return handle_datatype_identifier(type_name);}
+
 
 /*********************/
 /* B 1.2 - Constants */
--- a/absyntax_utils/search_base_type.hh	Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/search_base_type.hh	Sun Nov 16 15:37:12 2014 +0000
@@ -74,6 +74,7 @@
     
   private:  
     static void create_singleton(void);
+    void *handle_datatype_identifier(token_c *type_name);
 
   public:
     search_base_type_c(void);
@@ -88,8 +89,8 @@
   /*******************************************/
   /* B 1.1 - Letters, digits and identifiers */
   /*******************************************/
-    void *visit(identifier_c *type_name);
-
+    void *visit(                 identifier_c *type_name);
+    void *visit(derived_datatype_identifier_c *type_name);
     
   /*********************/
   /* B 1.2 - Constants */
--- a/absyntax_utils/spec_init_separator.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/spec_init_separator.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -74,7 +74,22 @@
 /* B 1.1 - Letters, digits and identifiers */
 /*******************************************/
 // SYM_TOKEN(identifier_c)
-void *spec_init_sperator_c::visit(identifier_c *symbol) {
+/* visitor for identifier_c is necessary because spec_init_sperator_c will be called to analyse PROGRAM identfiers,
+ * which are still transformed into identfier_c, instead of a derived_datatype_identifier_c
+ */
+void *spec_init_sperator_c::visit(                 identifier_c *symbol) {
+  TRACE("spec_init_sperator_c::identifier_c");
+  switch (search_what) {
+    /* if we ever get called sith a simple identifier_c, then it must be a previously declared type... */
+    case search_spec: return symbol;
+    case search_init: return NULL;
+  }
+  ERROR; /* should never occur */
+  return NULL;
+  }
+  
+  
+void *spec_init_sperator_c::visit(derived_datatype_identifier_c *symbol) {
   TRACE("spec_init_sperator_c::identifier_c");
   switch (search_what) {
     /* if we ever get called sith a simple identifier_c, then it must be a previously declared type... */
--- a/absyntax_utils/spec_init_separator.hh	Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/spec_init_separator.hh	Sun Nov 16 15:37:12 2014 +0000
@@ -65,7 +65,8 @@
   /* B 1.1 - Letters, digits and identifiers */
   /*******************************************/
   // SYM_TOKEN(identifier_c)
-  void *visit(identifier_c *symbol);
+  void *visit(                 identifier_c *symbol);
+  void *visit(derived_datatype_identifier_c *symbol);
   
 
   /********************************/
--- a/absyntax_utils/type_initial_value.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/type_initial_value.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -117,8 +117,27 @@
 }
 
 
-
-void *type_initial_value_c::visit(identifier_c *type_name) {
+/* visitor for identifier_c is necessary because type_initial_value_c will be called to analyse PROGRAM identfiers,
+ * which are still transformed into identfier_c, instead of a derived_datatype_identifier_c
+ */
+void *type_initial_value_c::visit(                 identifier_c *type_name) {
+  /* look up the type declaration... */
+  symbol_c *type_decl = type_symtable.find_value(type_name);
+  if (type_decl == type_symtable.end_value())
+    /* Type declaration not found!! */
+    /* NOTE: Variables declared out of function block 'data types',
+     *    for eg:  VAR  timer: TON; END_VAR
+     * do not have a default value, so (TON) will never be found in the
+     * type symbol table. This means we cannot simply consider this
+     * an error and abort, but must rather return a NULL.
+     */
+     return NULL;
+
+  return type_decl->accept(*this);
+}
+
+  
+void *type_initial_value_c::visit(derived_datatype_identifier_c *type_name) {
   /* look up the type declaration... */
   symbol_c *type_decl = type_symtable.find_value(type_name);
   if (type_decl == type_symtable.end_value())
--- a/absyntax_utils/type_initial_value.hh	Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/type_initial_value.hh	Sun Nov 16 15:37:12 2014 +0000
@@ -86,7 +86,8 @@
     void *handle_type_spec(symbol_c *base_type_name, symbol_c *type_spec_init);
 
   private:
-    void *visit(identifier_c *type_name);
+    void *visit(                 identifier_c *type_name);
+    void *visit(derived_datatype_identifier_c *type_name);
 
     /***********************************/
     /* B 1.3.1 - Elementary Data Types */
--- a/main.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/main.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -113,15 +113,8 @@
   printf(" -h : show this help message\n");
   printf(" -v : print version number\n");  
   printf(" -f : display full token location on error messages\n");
-      /******************************************************/
-      /* whether we are supporting safe extensions          */
-      /* as defined in PLCopen - Technical Committee 5      */
-      /* Safety Software Technical Specification,           */
-      /* Part 1: Concepts and Function Blocks,              */
-      /* Version 1.0 is Official Release                    */
-      /******************************************************/
-  printf(" -s : allow use of safe datatypes (SAFEBOOL, etc.)   (defined in PLCOpen Safety)\n");
-  printf(" -n : allow use of nested comments                   (an IEC 61131-3 v3 feature)\n");
+  printf(" -l : use a relaxed datatype equivalence model       (a non-standard extension?)\n");  
+  printf(" -s : allow use of safe datatypes (SAFEBOOL, etc.)   (defined in PLCOpen Safety)\n"); // PLCopen TC5 "Safety Software Technical Specification - Part 1" v1.0
   printf(" -r : allow use of references (REF_TO, REF, ^, NULL) (an IEC 61131-3 v3 feature)\n");
   printf(" -R : allow use of REF_TO ANY datatypes              (a non-standard extension!)\n");
   printf("        as well as REF_TO in ARRAYs and STRUCTs      (a non-standard extension!)\n");
@@ -135,27 +128,32 @@
 }
 
 
+/* declare the global options variable */
+runtime_options_t runtime_options;
+
 
 int main(int argc, char **argv) {
   symbol_c *tree_root;
   char * builddir = NULL;
-  stage1_2_options_t stage1_2_options;
   int optres, errflg = 0;
   int path_len;
 
   /* Default values for the command line options... */
-  stage1_2_options.safe_extensions         = false; /* allow use of SAFExxx datatypes */
-  stage1_2_options.full_token_loc          = false; /* error messages specify full token location */
-  stage1_2_options.conversion_functions    = false; /* Create a conversion function for derived datatype */
-  stage1_2_options.nested_comments         = false; /* Allow the use of nested comments. */
-  stage1_2_options.ref_standard_extensions = false; /* Allow the use of REFerences (keywords REF_TO, REF, DREF, ^, NULL). */
-  stage1_2_options.ref_nonstand_extensions = false; /* Allow the use of non-standard extensions to REF_TO datatypes: REF_TO ANY, and REF_TO in struct elements! */
-  stage1_2_options.includedir              = NULL;  /* Include directory, where included files will be searched for... */
-
+  runtime_options.safe_extensions         = false; /* allow use of SAFExxx datatypes */
+  runtime_options.full_token_loc          = false; /* error messages specify full token location */
+  runtime_options.conversion_functions    = false; /* Create a conversion function for derived datatype */
+  runtime_options.nested_comments         = false; /* Allow the use of nested comments. */
+  runtime_options.ref_standard_extensions = false; /* Allow the use of REFerences (keywords REF_TO, REF, DREF, ^, NULL). */
+  runtime_options.ref_nonstand_extensions = false; /* Allow the use of non-standard extensions to REF_TO datatypes: REF_TO ANY, and REF_TO in struct elements! */
+  runtime_options.includedir              = NULL;  /* Include directory, where included files will be searched for... */
+
+  /* Default values for the command line options... */
+  runtime_options.relaxed_datatype_model    = false; /* by default use the strict datatype equivalence model */
+  
   /******************************************/
   /*   Parse command line options...        */
   /******************************************/
-  while ((optres = getopt(argc, argv, ":nhvfrRscI:T:O:")) != -1) {
+  while ((optres = getopt(argc, argv, ":nhvflsrRcI:T:O:")) != -1) {
     switch(optres) {
     case 'h':
       printusage(argv[0]);
@@ -163,24 +161,28 @@
     case 'v':
       fprintf(stdout, "%s version %s\n" "changeset id: %s\n", PACKAGE_NAME, PACKAGE_VERSION, HGVERSION);      
       return 0;
+    case 'l':
+      runtime_options.relaxed_datatype_model = true;
+      break;
+  
     case 'f':
-      stage1_2_options.full_token_loc = true;
+      runtime_options.full_token_loc = true;
       break;
     case 's':
-      stage1_2_options.safe_extensions = true;
+      runtime_options.safe_extensions = true;
       break;
     case 'R':
-      stage1_2_options.ref_standard_extensions = true; /* use of REF_TO ANY implies activating support for REF extensions! */
-      stage1_2_options.ref_nonstand_extensions = true;
+      runtime_options.ref_standard_extensions = true; /* use of REF_TO ANY implies activating support for REF extensions! */
+      runtime_options.ref_nonstand_extensions = true;
       break;
     case 'r':
-      stage1_2_options.ref_standard_extensions = true;
+      runtime_options.ref_standard_extensions = true;
       break;
     case 'c':
-      stage1_2_options.conversion_functions = true;
+      runtime_options.conversion_functions = true;
       break;
     case 'n':
-      stage1_2_options.nested_comments = true;
+      runtime_options.nested_comments = true;
       break;
     case 'I':
       /* NOTE: To improve the usability under windows:
@@ -190,7 +192,7 @@
        */
       path_len = strlen(optarg) - 1;
       if (optarg[path_len] == '\\') optarg[path_len]= '\0';
-      stage1_2_options.includedir = optarg;
+      runtime_options.includedir = optarg;
       break;
     case 'T':
       /* NOTE: see note above */
@@ -236,7 +238,7 @@
   /*   Run the compiler...   */
   /***************************/
   /* 1st Pass */
-  if (stage1_2(argv[optind], &tree_root, stage1_2_options) < 0)
+  if (stage1_2(argv[optind], &tree_root) < 0)
     return EXIT_FAILURE;
 
   /* 2nd Pass */
@@ -245,7 +247,7 @@
     /* moved to bison, although it could perfectly well still be here instead of in bison code. */
   //add_en_eno_param_decl_c::add_to(tree_root);
 
-  /* Do semantic verification of code (data type and lvalue checking currently implemented) */
+  /* Do semantic verification of code */
   if (stage3(tree_root) < 0)
     return EXIT_FAILURE;
   
--- a/main.hh	Sun Nov 09 22:02:34 2014 +0000
+++ b/main.hh	Sun Nov 16 15:37:12 2014 +0000
@@ -36,6 +36,29 @@
 
 
 
+/* Compiler options, specified at runtime on the command line */
+
+typedef struct {
+   /* options specific to stage1_2 */
+	bool safe_extensions;          /* support SAFE_* datatypes defined in PLCOpen TC5 "Safety Software Technical Specification - Part 1" v1.0 */
+	bool full_token_loc;           /* error messages specify full token location */
+	bool conversion_functions;     /* Create a conversion function for derived datatype */
+	bool nested_comments;          /* Allow the use of nested comments. */
+	bool ref_standard_extensions;  /* Allow the use of REFerences (keywords REF_TO, REF, DREF, ^, NULL). */
+	bool ref_nonstand_extensions;  /* Allow the use of non-standard extensions to REF_TO datatypes: REF_TO ANY, and REF_TO in struct elements! */
+	const char *includedir;        /* Include directory, where included files will be searched for... */
+	
+   /* options specific to stage3 */
+	bool relaxed_datatype_model;   /* Use the relaxed datatype equivalence model, instead of the default strict equivalence model */
+} runtime_options_t;
+
+extern runtime_options_t runtime_options;
+
+
+
+
+
+
  /* Function used throughout the code --> used to report failed assertions (i.e. internal compiler errors)! */
 #include <stddef.h>  /* required for NULL */
  
--- a/stage1_2/iec_bison.yy	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage1_2/iec_bison.yy	Sun Nov 16 15:37:12 2014 +0000
@@ -1608,13 +1608,13 @@
 prev_declared_variable_name       : prev_declared_variable_name_token        {$$ = new identifier_c($1, locloc(@$));};
 prev_declared_fb_name             : prev_declared_fb_name_token              {$$ = new identifier_c($1, locloc(@$));};
 
-prev_declared_simple_type_name    : prev_declared_simple_type_name_token     {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_subrange_type_name  : prev_declared_subrange_type_name_token   {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_enumerated_type_name: prev_declared_enumerated_type_name_token {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_array_type_name     : prev_declared_array_type_name_token      {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_structure_type_name : prev_declared_structure_type_name_token  {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_string_type_name    : prev_declared_string_type_name_token     {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_ref_type_name       : prev_declared_ref_type_name_token        {$$ = new identifier_c($1, locloc(@$));};  /* defined in IEC 61131-3 v3 */
+prev_declared_simple_type_name    : prev_declared_simple_type_name_token     {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_subrange_type_name  : prev_declared_subrange_type_name_token   {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_enumerated_type_name: prev_declared_enumerated_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_array_type_name     : prev_declared_array_type_name_token      {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_structure_type_name : prev_declared_structure_type_name_token  {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_string_type_name    : prev_declared_string_type_name_token     {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_ref_type_name       : prev_declared_ref_type_name_token        {$$ = new derived_datatype_identifier_c($1, locloc(@$));};  /* defined in IEC 61131-3 v3 */
 
 prev_declared_derived_function_name      : prev_declared_derived_function_name_token       {$$ = new identifier_c($1, locloc(@$));};
 prev_declared_derived_function_block_name: prev_declared_derived_function_block_name_token {$$ = new identifier_c($1, locloc(@$));};
@@ -8487,13 +8487,12 @@
 
 
 int stage2__(const char *filename, 
-             symbol_c **tree_root_ref,
-             stage1_2_options_t options
+             symbol_c **tree_root_ref
             ) {             
   char *libfilename = NULL;
 
-  if (options.includedir != NULL) {
-    INCLUDE_DIRECTORIES[0] = options.includedir;
+  if (runtime_options.includedir != NULL) {
+    INCLUDE_DIRECTORIES[0] = runtime_options.includedir;
   }
 
   /* first parse the standard library file... */
@@ -8520,11 +8519,11 @@
 
   allow_function_overloading           = true;
   allow_extensible_function_parameters = true;
-  full_token_loc                       = options.full_token_loc;
-  conversion_functions                 = options.conversion_functions;
-  allow_ref_dereferencing              = options.ref_standard_extensions;
-  allow_ref_to_any                     = options.ref_nonstand_extensions;
-  allow_ref_to_in_derived_datatypes    = options.ref_nonstand_extensions;
+  full_token_loc                       = runtime_options.full_token_loc;
+  conversion_functions                 = runtime_options.conversion_functions;
+  allow_ref_dereferencing              = runtime_options.ref_standard_extensions;
+  allow_ref_to_any                     = runtime_options.ref_nonstand_extensions;
+  allow_ref_to_in_derived_datatypes    = runtime_options.ref_nonstand_extensions;
   if (yyparse() != 0)
       ERROR;
   fclose(libfile);
@@ -8557,11 +8556,11 @@
 
   allow_function_overloading           = false;
   allow_extensible_function_parameters = false;
-  full_token_loc                       = options.full_token_loc;
-  conversion_functions                 = options.conversion_functions;
-  allow_ref_dereferencing              = options.ref_standard_extensions;
-  allow_ref_to_any                     = options.ref_nonstand_extensions;
-  allow_ref_to_in_derived_datatypes    = options.ref_nonstand_extensions;
+  full_token_loc                       = runtime_options.full_token_loc;
+  conversion_functions                 = runtime_options.conversion_functions;
+  allow_ref_dereferencing              = runtime_options.ref_standard_extensions;
+  allow_ref_to_any                     = runtime_options.ref_nonstand_extensions;
+  allow_ref_to_in_derived_datatypes    = runtime_options.ref_nonstand_extensions;
   //allow_ref_to_any = false;    /* we only allow REF_TO ANY in library functions/FBs, no matter what the user asks for in the command line */
 
   if (yyparse() != 0) {
--- a/stage1_2/stage1_2.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage1_2/stage1_2.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -43,6 +43,7 @@
 #include "../absyntax/absyntax.hh"
 
 
+#include "../main.hh"
 #include "stage1_2.hh"
 #include "iec_bison.hh"
 #include "stage1_2_priv.hh"
@@ -51,7 +52,6 @@
 
 
 
-static stage1_2_options_t options_;
 
 /******************************************************/
 /* whether we are supporting safe extensions          */
@@ -60,17 +60,17 @@
 /* Part 1: Concepts and Function Blocks,              */
 /* Version 1.0 – Official Release                   */
 /******************************************************/
-bool get_opt_safe_extensions() {return options_.safe_extensions;}
+bool get_opt_safe_extensions() {return runtime_options.safe_extensions;}
 
 /************************************/
 /* whether to allow nested comments */
 /************************************/
-bool get_opt_nested_comments() {return options_.nested_comments;}
+bool get_opt_nested_comments() {return runtime_options.nested_comments;}
 
 /**************************************************************************/
 /* whether to allow REF(), DREF(), REF_TO, NULL and ^ operators/keywords  */
 /**************************************************************************/
-bool get_opt_ref_standard_extensions() {return options_.ref_standard_extensions;}
+bool get_opt_ref_standard_extensions() {return runtime_options.ref_standard_extensions;}
 
 
 
@@ -226,12 +226,11 @@
 /***********************************************************************/
 
 int stage2__(const char *filename, 
-             symbol_c **tree_root_ref,
-             stage1_2_options_t options
+             symbol_c **tree_root_ref
             );
 
 
-int stage1_2(const char *filename, symbol_c **tree_root_ref, stage1_2_options_t options) {
+int stage1_2(const char *filename, symbol_c **tree_root_ref) {
       /* NOTE: we only call stage2 (bison - syntax analysis) directly, as stage 2 will itself call stage1 (flex - lexical analysis)
        *       automatically as needed
        */
@@ -242,7 +241,6 @@
        *       These callback functions will get their data from local (to this file) global variables...
        *       We now set those variables...
        */
-  options_ = options;
-  return stage2__(filename, tree_root_ref, options);
-}
-
+  return stage2__(filename, tree_root_ref);
+}
+
--- a/stage1_2/stage1_2.hh	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage1_2/stage1_2.hh	Sun Nov 16 15:37:12 2014 +0000
@@ -42,31 +42,10 @@
 
 
 
-/*
- * This file includes the interface through which the main function accesses the stage1_2 services 
- */
+/* This file includes the interface through which the main function accesses the stage1_2 services */
 
 
-
-typedef struct {
-		/******************************************************/
-		/* whether we are suporting safe extensions           */
-		/* as defined in PLCopen - Technical Committee 5      */
-		/* Safety Software Technical Specification,           */
-		/* Part 1: Concepts and Function Blocks,              */
-		/* Version 1.0 – Official Release                     */
-		/******************************************************/
-	bool safe_extensions;
-	bool full_token_loc;           /* error messages specify full token location */
-	bool conversion_functions;     /* Create a conversion function for derived datatype */
-	bool nested_comments;          /* Allow the use of nested comments. */
-	bool ref_standard_extensions;  /* Allow the use of REFerences (keywords REF_TO, REF, DREF, ^, NULL). */
-	bool ref_nonstand_extensions;  /* Allow the use of non-standard extensions to REF_TO datatypes: REF_TO ANY, and REF_TO in struct elements! */
-	const char *includedir;        /* Include directory, where included files will be searched for... */
-} stage1_2_options_t;
-
-
-int stage1_2(const char *filename, symbol_c **tree_root, stage1_2_options_t options);
+int stage1_2(const char *filename, symbol_c **tree_root);
 
 
 
--- a/stage3/constant_folding.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/constant_folding.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -788,8 +788,21 @@
 /***********************************************************************/
 /***********************************************************************/
 
-
-
+#if 0
+// not currently needed, so comment it out!...
+// returns true if both symbols have the same value in all the cvalues
+bool constant_folding_c::is_equal_cvalue(symbol_c *symbol_1, symbol_c *symbol_2) {
+	if (VALID_CVALUE  (real64, symbol_1) != VALID_CVALUE  (real64, symbol_2)) return false;
+	if (VALID_CVALUE  (uint64, symbol_1) != VALID_CVALUE  (uint64, symbol_2)) return false;
+	if (VALID_CVALUE  ( int64, symbol_1) != VALID_CVALUE  ( int64, symbol_2)) return false;
+	if (VALID_CVALUE  (  bool, symbol_1) != VALID_CVALUE  (  bool, symbol_2)) return false;
+	if (VALID_CVALUE  (real64, symbol_1) && !ISEQUAL_CVALUE(real64, symbol_1, symbol_2)) return false;
+	if (VALID_CVALUE  (uint64, symbol_1) && !ISEQUAL_CVALUE(uint64, symbol_1, symbol_2)) return false;
+	if (VALID_CVALUE  ( int64, symbol_1) && !ISEQUAL_CVALUE( int64, symbol_1, symbol_2)) return false;
+	if (VALID_CVALUE  (  bool, symbol_1) && !ISEQUAL_CVALUE(  bool, symbol_1, symbol_2)) return false;
+	return true;
+}
+#endif
 
 
 
--- a/stage3/constant_folding.hh	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/constant_folding.hh	Sun Nov 16 15:37:12 2014 +0000
@@ -66,6 +66,14 @@
 	virtual ~constant_folding_c(void);
 	int get_error_count();
 
+	#if 0
+	// not currently needed, so comment it out!...
+	/* utility functions for other stage3 algorithms to access the contant folded values */
+	/* written as static since we do not need to iteratively visit the symbols! */
+	// returns true if both symbols have the same value in all the cvalues
+	static bool is_equal_cvalue(symbol_c *symbol_1, symbol_c *symbol_2);
+	#endif
+
   private:
     /*********************/
     /* B 1.2 - Constants */
--- a/stage3/fill_candidate_datatypes.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/fill_candidate_datatypes.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -1303,10 +1303,57 @@
 /* B 1.4.3 - Declaration & Initialisation */
 /******************************************/
 
+/* When handling the declaration of variables the fill/narrow algorithm will simply visit the objects
+ * in the abstract syntax tree defining the desired datatype for the variables. Tis is to set the 
+ * symbol->datatype to the basetype of that datatype.
+ *
+ * Note that we do not currently set the symbol->datatype annotation for the identifier_c objects naming the 
+ * variables inside the variable declaration. However, this is liable to change in the future, so do not write
+ * any code that depends on this!
+ * 
+ * example:
+ *    VAR  var1, var2, var3  :  my_type;  END_VAR
+ *   (*    ^^^^  ^^^^  ^^^^                -> will NOT have the symbol->datatype set (for now, may change in the future!) *)
+ *   (*                         ^^^^^^^    -> WILL     have the symbol->datatype set *)
+ * 
+ * (remeber too that the identifier_c objects identifying variables inside ST/IL/SFC code *will* have their 
+ *  symbol->datatype annotation filled by the fill/narrow algorithm)
+ */
+void *fill_candidate_datatypes_c::fill_var_declaration(symbol_c *var_list, symbol_c *type) {
+  /* The type may be either a datatype object (e.g. array_spec_init_c, ...), or a derived_datatype_identifier_c
+   * naming a previously declared datatype.
+   * If it is a derived_datatype_identifier_c, we will search the list of all declared datatypes to determine 
+   * the requested datatype. This is done automatically by the search_base_type_c::get_basetype_decl() method, 
+   * so we do not need to do anything special here!
+   */
+  add_datatype_to_candidate_list(type, search_base_type_c::get_basetype_decl(type));  /* will only add if non NULL */
+  type->accept(*this);
+  // handle the extensible_input_parameter_c, etc...
+  /* The extensible_input_parameter_c will be visited since this class inherits from the iterator_visitor_c.
+   * It needs to be visited in order to handle the datatype of the first_index parameter of that class.
+   */
+  var_list->accept(*this);
+  return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(var1_init_decl_c             *symbol) {return fill_var_declaration(symbol->var1_list,       symbol->spec_init);}
+void *fill_candidate_datatypes_c::visit(array_var_init_decl_c        *symbol) {return fill_var_declaration(symbol->var1_list,       symbol->array_spec_init);}
+void *fill_candidate_datatypes_c::visit(structured_var_init_decl_c   *symbol) {return fill_var_declaration(symbol->var1_list,       symbol->initialized_structure);}
+void *fill_candidate_datatypes_c::visit(fb_name_decl_c               *symbol) {return fill_var_declaration(symbol->fb_name_list,    symbol->fb_spec_init);}
+void *fill_candidate_datatypes_c::visit(array_var_declaration_c      *symbol) {return fill_var_declaration(symbol->var1_list,       symbol->array_specification);}
+void *fill_candidate_datatypes_c::visit(structured_var_declaration_c *symbol) {return fill_var_declaration(symbol->var1_list,       symbol->structure_type_name);}
+void *fill_candidate_datatypes_c::visit(external_declaration_c       *symbol) {return fill_var_declaration(symbol->global_var_name, symbol->specification);}
+void *fill_candidate_datatypes_c::visit(global_var_decl_c            *symbol) {return fill_var_declaration(symbol->global_var_spec, symbol->type_specification);}
+void *fill_candidate_datatypes_c::visit(incompl_located_var_decl_c   *symbol) {return fill_var_declaration(symbol->variable_name,   symbol->var_spec);}
+//void *fill_candidate_datatypes_c::visit(single_byte_string_var_declaration_c *symbol) {return handle_var_declaration(symbol->single_byte_string_spec);}
+//void *fill_candidate_datatypes_c::visit(double_byte_string_var_declaration_c *symbol) {return handle_var_declaration(symbol->double_byte_string_spec);}
+
+
+
+// NOTE: this method is not required since fill_candidate_datatypes_c inherits from iterator_visitor_c. TODO: delete this method!
 void *fill_candidate_datatypes_c::visit(var1_list_c *symbol) {
-  for(int i = 0; i < symbol->n; i++) {
-    symbol->elements[i]->accept(*this); // handle the extensible_input_parameter_c, etc...
-  }
+  for(int i = 0; i < symbol->n; i++) {symbol->elements[i]->accept(*this);}
   return NULL;
 }  
 
@@ -1509,10 +1556,56 @@
 /* B 1.7 Configuration elements */
 /********************************/
 void *fill_candidate_datatypes_c::visit(configuration_declaration_c *symbol) {
-	// TODO !!!
-	/* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
-	return NULL;
-}
+	if (debug) printf("Filling candidate data types list in configuration %s\n", ((token_c *)(symbol->configuration_name))->value);
+	current_scope = symbol;
+//	local_enumerated_value_symtable.reset();  // TODO
+//	symbol->global_var_declarations->accept(populate_enumvalue_symtable);  // TODO
+	
+	search_var_instance_decl = new search_var_instance_decl_c(symbol);
+	symbol->global_var_declarations          ->accept(*this);
+	symbol->resource_declarations            ->accept(*this); // points to a single_resource_declaration_c or a resource_declaration_list_c
+//	symbol->access_declarations              ->accept(*this); // TODO
+//	symbol->instance_specific_initializations->accept(*this); // TODO
+
+	delete search_var_instance_decl;
+	search_var_instance_decl = NULL;
+
+	current_scope = NULL;	
+//	local_enumerated_value_symtable.reset();  // TODO
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(resource_declaration_c *symbol) {
+	if (debug) printf("Filling candidate data types list in resource %s\n", ((token_c *)(symbol->resource_name))->value);
+//	local_enumerated_value_symtable.reset();  // TODO-> this must be replaced with local_enumerated_value_symtable.push(), which is not yet implemented for the dsyntable_c!
+	symbol_c *prev_scope = current_scope;
+	current_scope = symbol;
+	/* TODO Enumeration constants may be defined inside a VAR_GLOBAL .. END_VAR variable declaration list. 
+	 * We currently do not yet consider enumeration values defined in the var declarations inside a resource!
+	 */
+//	symbol->global_var_declarations->accept(populate_enumvalue_symtable);  // TODO!
+	
+	search_var_instance_decl_c *prev_search_var_instance_decl = search_var_instance_decl;
+	search_var_instance_decl  = new  search_var_instance_decl_c(symbol);
+	symbol->global_var_declarations->accept(*this);
+	symbol->resource_declaration   ->accept(*this);  // points to a single_resource_declaration_c!
+
+	delete search_var_instance_decl;
+	search_var_instance_decl = prev_search_var_instance_decl;
+
+	current_scope = prev_scope;	
+//	local_enumerated_value_symtable.reset();  // TODO-> this must be replaced with local_enumerated_value_symtable.pop(), which is not yet implemented for the dsyntable_c!
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(single_resource_declaration_c *symbol) {
+//	symbol->task_configuration_list    ->accept(*this);  // TODO
+//	symbol->program_configuration_list ->accept(*this);  // TODO
+	return NULL;
+}
+
 
 /****************************************/
 /* B.2 - Language IL (Instruction List) */
--- a/stage3/fill_candidate_datatypes.hh	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/fill_candidate_datatypes.hh	Sun Nov 16 15:37:12 2014 +0000
@@ -96,10 +96,11 @@
     void *handle_equality_comparison(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
     void *handle_binary_expression  (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
     void *handle_binary_operator    (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
-    void *handle_conditional_il_flow_control_operator(symbol_c *symbol);
-    void *fill_type_decl(symbol_c *symbol, symbol_c *type_name, symbol_c *spec_init);
-    void *fill_spec_init(symbol_c *symbol, symbol_c *type_spec, symbol_c *init_value);
-    
+    void *handle_conditional_il_flow_control_operator   (symbol_c *symbol);
+    void *fill_type_decl            (symbol_c *symbol,   symbol_c *type_name, symbol_c *spec_init);
+    void *fill_spec_init            (symbol_c *symbol,   symbol_c *type_spec, symbol_c *init_value);
+    void *fill_var_declaration      (symbol_c *var_list, symbol_c *type);
+
     /* a helper function... */
     symbol_c *base_type(symbol_c *symbol);    
     
@@ -230,9 +231,20 @@
     /******************************************/
     /* B 1.4.3 - Declaration & Initialisation */
     /******************************************/
-    void *visit(var1_list_c *symbol);
-    void *visit(location_c *symbol);
-    void *visit(located_var_decl_c *symbol);
+    void *visit(var1_list_c                  *symbol);
+    void *visit(location_c                   *symbol);
+    void *visit(located_var_decl_c           *symbol);
+    void *visit(var1_init_decl_c             *symbol);
+    void *visit(array_var_init_decl_c        *symbol);
+    void *visit(structured_var_init_decl_c   *symbol);
+    void *visit(fb_name_decl_c               *symbol);
+    void *visit(array_var_declaration_c      *symbol);
+    void *visit(structured_var_declaration_c *symbol);
+    void *visit(external_declaration_c       *symbol);
+    void *visit(global_var_decl_c            *symbol);
+    void *visit(incompl_located_var_decl_c   *symbol);
+    //void *visit(single_byte_string_var_declaration_c *symbol);
+    //void *visit(double_byte_string_var_declaration_c *symbol);
 
     /**************************************/
     /* B 1.5 - Program organization units */
@@ -260,7 +272,9 @@
     /********************************/
     /* B 1.7 Configuration elements */
     /********************************/
-    void *visit(configuration_declaration_c *symbol);
+    void *visit(configuration_declaration_c   *symbol);
+    void *visit(resource_declaration_c        *symbol);
+    void *visit(single_resource_declaration_c *symbol);
 
     /****************************************/
     /* B.2 - Language IL (Instruction List) */
--- a/stage3/narrow_candidate_datatypes.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/narrow_candidate_datatypes.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -747,6 +747,44 @@
 /* B 1.4.3 - Declaration & Initialisation */
 /******************************************/
 
+/* When handling the declaration of variables the fill/narrow algorithm will simply visit the objects
+ * in the abstract syntax tree defining the desired datatype for the variables. Tis is to set the 
+ * symbol->datatype to the basetype of that datatype.
+ *
+ * Note that we do not currently set the symbol->datatype annotation for the identifier_c objects naming the 
+ * variables inside the variable declaration. However, this is liable to change in the future, so do not write
+ * any code that depends on this!
+ * 
+ * example:
+ *    VAR  var1, var2, var3  :  my_type;  END_VAR
+ *   (*    ^^^^  ^^^^  ^^^^                -> will NOT have the symbol->datatype set (for now, may change in the future!) *)
+ *   (*                         ^^^^^^^    -> WILL     have the symbol->datatype set *)
+ * 
+ * (remeber too that the identifier_c objects identifying variables inside ST/IL/SFC code *will* have their 
+ *  symbol->datatype annotation filled by the fill/narrow algorithm)
+ */
+void *narrow_candidate_datatypes_c::narrow_var_declaration(symbol_c *type) {
+  if (type->candidate_datatypes.size() == 1)
+    type->datatype = type->candidate_datatypes[0];
+  type->accept(*this); 
+  return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(var1_init_decl_c             *symbol) {return narrow_var_declaration(symbol->spec_init);}
+void *narrow_candidate_datatypes_c::visit(array_var_init_decl_c        *symbol) {return narrow_var_declaration(symbol->array_spec_init);}
+void *narrow_candidate_datatypes_c::visit(structured_var_init_decl_c   *symbol) {return narrow_var_declaration(symbol->initialized_structure);}
+void *narrow_candidate_datatypes_c::visit(fb_name_decl_c               *symbol) {return narrow_var_declaration(symbol->fb_spec_init);}
+void *narrow_candidate_datatypes_c::visit(array_var_declaration_c      *symbol) {return narrow_var_declaration(symbol->array_specification);}
+void *narrow_candidate_datatypes_c::visit(structured_var_declaration_c *symbol) {return narrow_var_declaration(symbol->structure_type_name);}
+void *narrow_candidate_datatypes_c::visit(external_declaration_c       *symbol) {return narrow_var_declaration(symbol->specification);}
+void *narrow_candidate_datatypes_c::visit(global_var_decl_c            *symbol) {return narrow_var_declaration(symbol->type_specification);}
+void *narrow_candidate_datatypes_c::visit(incompl_located_var_decl_c   *symbol) {return narrow_var_declaration(symbol->var_spec);}
+//void *narrow_candidate_datatypes_c::visit(single_byte_string_var_declaration_c *symbol) {return handle_var_declaration(symbol->single_byte_string_spec);}
+//void *narrow_candidate_datatypes_c::visit(double_byte_string_var_declaration_c *symbol) {return handle_var_declaration(symbol->double_byte_string_spec);}
+
+
+
 void *narrow_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++) {
@@ -856,10 +894,36 @@
 /* B 1.7 Configuration elements */
 /********************************/
 void *narrow_candidate_datatypes_c::visit(configuration_declaration_c *symbol) {
-	// TODO !!!
-	/* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
-	return NULL;
-}
+	if (debug) printf("Narrowing candidate data types list in configuration %s\n", ((token_c *)(symbol->configuration_name))->value);
+	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	symbol->global_var_declarations->accept(*this);
+	symbol->resource_declarations            ->accept(*this); // points to a single_resource_declaration_c or a resource_declaration_list_c
+//	symbol->access_declarations              ->accept(*this); // TODO
+//	symbol->instance_specific_initializations->accept(*this); // TODO
+	delete search_varfb_instance_type;
+	search_varfb_instance_type = NULL;
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(resource_declaration_c *symbol) {
+	if (debug) printf("Narrowing candidate data types list in resource %s\n", ((token_c *)(symbol->resource_name))->value);
+	search_varfb_instance_type_c *prev_search_varfb_instance_type = search_varfb_instance_type;
+	search_varfb_instance_type  =  new search_varfb_instance_type_c(symbol);
+	symbol->global_var_declarations->accept(*this);
+	symbol->resource_declaration   ->accept(*this);  // points to a single_resource_declaration_c!
+	delete search_varfb_instance_type;
+	search_varfb_instance_type = prev_search_varfb_instance_type;
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(single_resource_declaration_c *symbol) {
+//	symbol->task_configuration_list    ->accept(*this);  // TODO
+//	symbol->program_configuration_list ->accept(*this);  // TODO
+	return NULL;
+}
+
 
 
 /****************************************/
--- a/stage3/narrow_candidate_datatypes.hh	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/narrow_candidate_datatypes.hh	Sun Nov 16 15:37:12 2014 +0000
@@ -80,9 +80,10 @@
     void *narrow_S_and_R_operator    (symbol_c *symbol, const char *param_name, symbol_c * called_fb_declaration);
     void *narrow_store_operator      (symbol_c *symbol);
     void *narrow_conditional_operator(symbol_c *symbol);
-    void *narrow_binary_operator    (const struct widen_entry widen_table[], symbol_c *symbol,                                     bool *deprecated_operation = NULL);
-    void *narrow_binary_expression  (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL, bool allow_enums = false);
-    void *narrow_equality_comparison(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL);
+    void *narrow_binary_operator     (const struct widen_entry widen_table[], symbol_c *symbol,                                     bool *deprecated_operation = NULL);
+    void *narrow_binary_expression   (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL, bool allow_enums = false);
+    void *narrow_equality_comparison (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL);
+    void *narrow_var_declaration     (symbol_c *type);
 
     void *set_il_operand_datatype    (symbol_c *il_operand, symbol_c *datatype);
 
@@ -201,9 +202,20 @@
     /******************************************/
     /* B 1.4.3 - Declaration & Initialisation */
     /******************************************/
-    void *visit(var1_list_c *symbol);
-    void *visit(location_c *symbol);
-    void *visit(located_var_decl_c *symbol);
+    void *visit(var1_list_c                  *symbol);
+    void *visit(location_c                   *symbol);
+    void *visit(located_var_decl_c           *symbol);
+    void *visit(var1_init_decl_c             *symbol);
+    void *visit(array_var_init_decl_c        *symbol);
+    void *visit(structured_var_init_decl_c   *symbol);
+    void *visit(fb_name_decl_c               *symbol);
+    void *visit(array_var_declaration_c      *symbol);
+    void *visit(structured_var_declaration_c *symbol);
+    void *visit(external_declaration_c       *symbol);
+    void *visit(global_var_decl_c            *symbol);
+    void *visit(incompl_located_var_decl_c   *symbol);
+    //void *visit(single_byte_string_var_declaration_c *symbol);
+    //void *visit(double_byte_string_var_declaration_c *symbol);
 
     /**************************************/
     /* B 1.5 - Program organization units */
@@ -231,7 +243,10 @@
     /********************************/
     /* B 1.7 Configuration elements */
     /********************************/
-    void *visit(configuration_declaration_c *symbol);
+    void *visit(configuration_declaration_c   *symbol);
+    void *visit(resource_declaration_c        *symbol);
+    void *visit(single_resource_declaration_c *symbol);
+
     /****************************************/
     /* B.2 - Language IL (Instruction List) */
     /****************************************/
--- a/stage4/generate_c/generate_c.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -250,7 +250,7 @@
  *     LEN( STRING) : INT     -> prints out ->  INT__STRING
  *     MUL(TIME, INT) : TIME  -> prints out ->  TIME__TIME__INT
  */
-class print_function_parameter_data_types_c: public generate_c_base_c {
+class print_function_parameter_data_types_c: public generate_c_base_and_typeid_c {
   private:
     symbol_c *current_type;
     bool_type_name_c tmp_bool;
@@ -269,7 +269,7 @@
     
   public:
     print_function_parameter_data_types_c(stage4out_c *s4o_ptr): 
-      generate_c_base_c(s4o_ptr)
+      generate_c_base_and_typeid_c(s4o_ptr)
       {current_type = NULL;}
 
     /**************************************/
@@ -752,185 +752,6 @@
 
 
 
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-
-
-identifier_c *generate_unique_id(const char *prefix = "", symbol_c *clone = NULL) {
-  static int counter = 0;
-  
-  counter++;
-  int   len = snprintf(NULL, 0, "%s__UID_%d", prefix, counter); // UID -> Unique IDentifier
-  char *str = (char *)malloc(len+1);
-  if (snprintf(str, len+1,      "%s__UID_%d", prefix, counter) < 0) ERROR;
-  
-  identifier_c *id = new identifier_c(str);
-  if (NULL == id) ERROR;
-  if (NULL != clone)
-    *(dynamic_cast<symbol_c *>(id)) = *(dynamic_cast<symbol_c *>(clone));
-  return id;
-}
-
-
-identifier_c *generate_unique_id(symbol_c *prefix, symbol_c *clone = NULL) {
-  token_c *token = dynamic_cast<token_c *>(prefix);
-  //if (NULL == token) ERROR;
-  if (NULL == token)
-    return generate_unique_id("", clone);
-  return generate_unique_id(token->value, clone);
-}
-
-
-/* This class will generate a new datatype for each implicitly declared array datatype
- * (i.e. arrays declared in a variable declaration, or a struct datatype declaration...)
- * It will do the same for implicitly declared REF_TO datatypes.
- * 
- * The class will be called once for each POU declaration, and once for each derived datatype declaration.
- * 
- * e.g.:
- *      VAR  a: ARRAY [1..3] OF INT; END_VAR   <---- ARRAY datatype is implicitly declared inside the variable declaration
- *      TYPE STRUCT
- *               a: ARRAY [1..3] OF INT;       <---- ARRAY datatype is implicitly declared inside the struct type declaration  
- *               b: INT;
- *            END_STRUCT
- *      END_TYPE
- */
-class generate_c_datatypes_c: public iterator_visitor_c {
-  private:
-    generate_c_typedecl_c generate_c_typedecl;
-    symbol_c *prefix;
-  public:
-    generate_c_datatypes_c(stage4out_c *s4o_incl_ptr)
-      : generate_c_typedecl(s4o_incl_ptr) {
-        prefix = NULL;
-    };
-    virtual ~generate_c_datatypes_c(void) {
-    }
-
-    /*************************/
-    /* B.1 - Common elements */
-    /*************************/
-    /**********************/
-    /* B.1.3 - Data types */
-    /**********************/
-    /********************************/
-    /* B 1.3.3 - Derived data types */
-    /********************************/
-    /*  identifier ':' array_spec_init */
-    void *visit(array_type_declaration_c *symbol) {return NULL;} // This is not an implicitly defined array!
-
-    /* ref_spec:  REF_TO (non_generic_type_name | function_block_type_name) */
-    void *visit(ref_spec_c *symbol) {
-      identifier_c *id = generate_unique_id(prefix, symbol);
-      /* Warning: The following is dangerous... 
-       * We are asking the generate_c_typedecl_c visitor to visit a newly created ref_spec_init_c object
-       * that has not been through stage 3, and therefore does not have stage 3 annotations filled in.
-       * This will only work if generate_c_typedecl_c does ot depend on the stage 3 annotations!
-       */
-      ref_spec_init_c   ref_spec(symbol, NULL);
-      ref_type_decl_c   ref_decl(id, &ref_spec);
-      ref_decl.accept(generate_c_typedecl); // Must be done _before_ adding the annotation, due to the way generate_c_typedecl_c works
-      symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
-      return NULL;
-    }
-
-    /* For the moment, we do not support initialising reference data types */
-    /* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */ 
-    /* NOTE: ref_initialization may be NULL!! */
-    // SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
-    void *visit(ref_spec_init_c *symbol) {
-      symbol->ref_spec->accept(*this);
-      int implicit_id_count = symbol->ref_spec->anotations_map.count("generate_c_annotaton__implicit_type_id");
-      if (implicit_id_count  > 1) ERROR;
-      if (implicit_id_count == 1)
-        symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = symbol->ref_spec->anotations_map["generate_c_annotaton__implicit_type_id"];
-      return NULL;
-    }
-
-    /* ref_type_decl: identifier ':' ref_spec_init */
-    void *visit(ref_type_decl_c *symbol) {return NULL;} // This is not an implicitly defined REF_TO!
-
-    /******************************************/
-    /* B 1.4.3 - Declaration & Initialization */
-    /******************************************/
-    void *visit(edge_declaration_c           *symbol) {return NULL;}
-    void *visit(en_param_declaration_c       *symbol) {return NULL;}
-    void *visit(eno_param_declaration_c      *symbol) {return NULL;}
-
-    /* array_specification [ASSIGN array_initialization] */
-    /* array_initialization may be NULL ! */
-    void *visit(array_spec_init_c *symbol) {
-      symbol->array_specification->accept(*this);
-      int implicit_id_count = symbol->array_specification->anotations_map.count("generate_c_annotaton__implicit_type_id");
-      if (implicit_id_count  > 1) ERROR;
-      if (implicit_id_count == 1)
-        symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = symbol->array_specification->anotations_map["generate_c_annotaton__implicit_type_id"];
-      return NULL;
-    }
-
-    /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
-    void *visit(array_specification_c *symbol) {
-      identifier_c *id = generate_unique_id(prefix, symbol);
-      /* Warning: The following is dangerous... 
-       * We are asking the generate_c_typedecl_c visitor to visit a newly created array_type_declaration_c object
-       * that has not been through stage 3, and therefore does not have stage 3 annotations filled in.
-       * This will only work if generate_c_typedecl_c does ot depend on the stage 3 annotations!
-       */
-      array_spec_init_c        array_spec(symbol, NULL);
-      array_type_declaration_c array_decl(id, &array_spec);
-      array_decl.accept(generate_c_typedecl); // Must be done _before_ adding the annotation, due to the way generate_c_typedecl_c works
-      symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
-      return NULL;
-    }
-    
-    /*  var1_list ':' initialized_structure */
-    // SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure)
-    void *visit(structured_var_init_decl_c   *symbol) {return NULL;}
-
-    /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
-    /* structure_initialization -> may be NULL ! */
-    void *visit(fb_name_decl_c               *symbol) {return NULL;}
-
-    /*  var1_list ':' structure_type_name */
-    //SYM_REF2(structured_var_declaration_c, var1_list, structure_type_name)
-    void *visit(structured_var_declaration_c *symbol) {return NULL;}
-
-
-    /***********************/
-    /* B 1.5.1 - Functions */
-    /***********************/      
-    void *visit(function_declaration_c *symbol) {
-      prefix = symbol->derived_function_name;
-      symbol->var_declarations_list->accept(*this);
-      prefix = NULL;
-      return NULL;
-    }
-    /*****************************/
-    /* B 1.5.2 - Function Blocks */
-    /*****************************/
-    void *visit(function_block_declaration_c *symbol) {
-      prefix = symbol->fblock_name;
-      symbol->var_declarations->accept(*this);
-      prefix = NULL;
-      return NULL;
-    }
-    /**********************/
-    /* B 1.5.3 - Programs */
-    /**********************/    
-    void *visit(program_declaration_c *symbol) {
-      prefix = symbol->program_type_name;
-      symbol->var_declarations->accept(*this);
-      prefix = NULL;
-      return NULL;
-    }
-};
-
-
-
-
 
 
 
@@ -986,8 +807,8 @@
     /*   FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
     /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
     static void handle_function(function_declaration_c *symbol, stage4out_c &s4o, bool print_declaration) {
-      generate_c_vardecl_c *vardecl = NULL;
-      generate_c_base_c     print_base(&s4o);
+      generate_c_vardecl_c          *vardecl = NULL;
+      generate_c_base_and_typeid_c   print_base(&s4o);
       
       TRACE("function_declaration_c");
     
@@ -1123,9 +944,9 @@
     /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
     //SYM_REF4(function_block_declaration_c, fblock_name, var_declarations, fblock_body, unused)
     static void handle_function_block(function_block_declaration_c *symbol, stage4out_c &s4o, bool print_declaration) {
-      generate_c_vardecl_c     *vardecl;
-      generate_c_sfcdecl_c     *sfcdecl;
-      generate_c_base_c         print_base(&s4o);
+      generate_c_vardecl_c          *vardecl;
+      generate_c_sfcdecl_c          *sfcdecl;
+      generate_c_base_and_typeid_c   print_base(&s4o);
       TRACE("function_block_declaration_c");
     
       /* (A) Function Block data structure declaration... */
@@ -1325,9 +1146,9 @@
     /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
     //SYM_REF4(program_declaration_c, program_type_name, var_declarations, function_block_body, unused)
     static void handle_program(program_declaration_c *symbol, stage4out_c &s4o, bool print_declaration) {
-      generate_c_vardecl_c     *vardecl;
-      generate_c_sfcdecl_c     *sfcdecl;
-      generate_c_base_c         print_base(&s4o);
+      generate_c_vardecl_c          *vardecl;
+      generate_c_sfcdecl_c          *sfcdecl;
+      generate_c_base_and_typeid_c   print_base(&s4o);
       TRACE("program_declaration_c");
     
       /* (A) Program data structure declaration... */
@@ -1499,13 +1320,13 @@
 /***********************************************************************/
 /***********************************************************************/
 
-class generate_c_config_c: public generate_c_base_c {
+class generate_c_config_c: public generate_c_base_and_typeid_c {
     private:
     stage4out_c &s4o_incl;
     
     public:
     generate_c_config_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr)
-      : generate_c_base_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) {
+      : generate_c_base_and_typeid_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) {
     };
 
     virtual ~generate_c_config_c(void) {}
@@ -1710,7 +1531,7 @@
 /***********************************************************************/
 
 
-class generate_c_resources_c: public generate_c_typedecl_c {
+class generate_c_resources_c: public generate_c_base_and_typeid_c {
 
   search_var_instance_decl_c *search_config_instance;
   search_var_instance_decl_c *search_resource_instance;
@@ -1726,7 +1547,7 @@
 
   public:
     generate_c_resources_c(stage4out_c *s4o_ptr, symbol_c *config_scope, symbol_c *resource_scope, unsigned long time)
-      : generate_c_typedecl_c(s4o_ptr) {
+      : generate_c_base_and_typeid_c(s4o_ptr) {
       current_configuration = config_scope;
       search_config_instance   = new search_var_instance_decl_c(config_scope);
       search_resource_instance = new search_var_instance_decl_c(resource_scope);
@@ -2237,9 +2058,9 @@
     stage4out_c     located_variables_s4o;
     stage4out_c             variables_s4o;
     
-    generate_c_datatypes_c generate_c_datatypes;
-    generate_c_typedecl_c  generate_c_typedecl;
-    generate_c_pous_c      generate_c_pous;
+    generate_c_typedecl_c          generate_c_typedecl;
+    generate_c_implicit_typedecl_c generate_c_implicit_typedecl;
+    generate_c_pous_c              generate_c_pous;
     
     symbol_c   *current_configuration;
 
@@ -2257,8 +2078,8 @@
             pous_incl_s4o(builddir, "POUS", "h"),
             located_variables_s4o(builddir, "LOCATED_VARIABLES","h"),
             variables_s4o(builddir, "VARIABLES","csv"),
-            generate_c_datatypes(&pous_incl_s4o),
-            generate_c_typedecl (&pous_incl_s4o)
+            generate_c_typedecl         (&pous_incl_s4o),
+            generate_c_implicit_typedecl(&pous_incl_s4o, &generate_c_typedecl)
     {
       current_builddir = builddir;
       current_configuration = NULL;
@@ -2337,7 +2158,7 @@
     /* helper symbol for data_type_declaration */
     void *visit(type_declaration_list_c *symbol) {
       for(int i = 0; i < symbol->n; i++) {
-        symbol->elements[i]->accept(generate_c_datatypes);
+        symbol->elements[i]->accept(generate_c_implicit_typedecl);
         symbol->elements[i]->accept(generate_c_typedecl);
       }
       return NULL;
@@ -2349,14 +2170,14 @@
 #define handle_pou(fname,pname) \
       if (!allow_output) return NULL;\
       if (generate_pou_filepairs__) {\
-	const char *pou_name = get_datatype_info_c::get_id_str(pname);\
+        const char *pou_name = get_datatype_info_c::get_id_str(pname);\
         stage4out_c s4o_c(current_builddir, pou_name, "c");\
         stage4out_c s4o_h(current_builddir, pou_name, "h");\
         s4o_c.print("#include \""); s4o_c.print(pou_name); s4o_c.print(".h\"\n");\
         s4o_h.print("#ifndef __");  s4o_h.print(pou_name); s4o_h.print("_H\n");\
         s4o_h.print("#define __");  s4o_h.print(pou_name); s4o_h.print("_H\n");\
-        generate_c_datatypes_c generate_c_datatypes__(&s4o_h);\
-        symbol->accept(generate_c_datatypes__); /* generate implicitly delcared datatypes (arrays and ref_to) */\
+        generate_c_implicit_typedecl_c generate_c_implicit_typedecl__(&s4o_h);\
+        symbol->accept(generate_c_implicit_typedecl__); /* generate implicitly delcared datatypes (arrays and ref_to) */\
         generate_c_pous_c::fname(symbol, s4o_h, true); /* generate the <pou_name>.h file */\
         generate_c_pous_c::fname(symbol, s4o_c, false);/* generate the <pou_name>.c file */\
         s4o_h.print("#endif /* __");  s4o_h.print(pou_name); s4o_h.print("_H */\n");\
@@ -2368,7 +2189,7 @@
         pous_incl_s4o.print(".h\"\n");\
         pous_s4o.     print(".c\"\n");\
       } else {\
-        symbol->accept(generate_c_datatypes);\
+        symbol->accept(generate_c_implicit_typedecl);\
         generate_c_pous_c::fname(symbol, pous_incl_s4o, true);\
         generate_c_pous_c::fname(symbol, pous_s4o,      false);\
       }
@@ -2403,7 +2224,7 @@
 /********************************/
     void *visit(configuration_declaration_c *symbol) {
       if (symbol->global_var_declarations != NULL)
-        symbol->global_var_declarations->accept(generate_c_datatypes);
+        symbol->global_var_declarations->accept(generate_c_implicit_typedecl);
       static int configuration_count = 0;
 
       if (configuration_count++) {
@@ -2446,7 +2267,7 @@
 
     void *visit(resource_declaration_c *symbol) {
       if (symbol->global_var_declarations != NULL)
-        symbol->global_var_declarations->accept(generate_c_datatypes);
+        symbol->global_var_declarations->accept(generate_c_implicit_typedecl);
       symbol->resource_name->accept(*this);
       stage4out_c resources_s4o(current_builddir, current_name, "c");
       generate_c_resources_c generate_c_resources(&resources_s4o, current_configuration, symbol, common_ticktime);
--- a/stage4/generate_c/generate_c_base.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_base.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -26,6 +26,30 @@
 
 
 
+/*  This file cotains two main classes:
+ *   - generate_c_base_c
+ *   - generate_c_base_and_typeid_c
+ * 
+ *  generate_c_base_c
+ *  -----------------
+ *   This class generates C code for all literals and varables. In short, all the basic stuff
+ *   that will probably be needed in all other code generating classes.
+ *   It does not however handle derived datatypes.
+ *
+ * generate_c_base_and_typeid_c
+ * ----------------------------
+ *   This is similar to the generate_c_base_c (from which it inherits), but it also handles
+ *   all the derived datatypes. Note that it does not generate C code for the declaration of
+ *   those datatypes (that is what generate_c_typedecl_c is for), but rather it merely
+ *   generates the name/id of a derived datatype.
+ *   Note too that not all derived datatypes in the IEC 61131-3 have a name (for example, 
+ *   VAR a: ARRAY [3..5] of INT END_VAR), in which case an alias for this datatype should 
+ *   have been previously generated by either generate_c_typedecl_c or generate_implicit_typedecl_c.
+ */ 
+
+
+
+
 
 typedef struct
 {
@@ -61,6 +85,12 @@
   param_list.clear();
 
 
+/*  generate_c_base_c
+ *  -----------------
+ *   This class generates C code for all literals and varables. In short, all the basic stuff
+ *   that will probably be needed in all other code generating classes.
+ *   It does not however handle derived datatypes.
+ */
 class generate_c_base_c: public iterator_visitor_c {
 
   protected:
@@ -298,6 +328,10 @@
 /* B 1.1 - Letters, digits and identifiers */
 /*******************************************/
     void *visit(identifier_c *symbol) {return print_token(symbol);}
+    /* If you need the derived_datatype_identifier_c visitor, then you should probably be 
+     * inheriting from generate_c_base_and_typeid_c and not generate_c_base_c !!
+     */
+    void *visit(derived_datatype_identifier_c *symbol) {ERROR; return NULL;}
 
 /*********************/
 /* B 1.2 - Constants */
@@ -594,12 +628,11 @@
     /* Currently only used in REF_TO ANY, which is mapped onto (void *) */
     void *visit(generic_type_any_c *symbol)      {s4o.print("void");    return NULL;}
 
+
 /********************************/
 /* B 1.3.3 - Derived data types */
 /********************************/
-  /* leave for derived classes... */
-
-  
+
 /* enumerated_type_name '#' identifier */
 void *visit(enumerated_value_c *symbol) {
   if (NULL == symbol->datatype) {
@@ -619,97 +652,6 @@
 }
 
 
-/*  identifier ':' array_spec_init */
-void *visit(array_type_declaration_c *symbol) {ERROR;/* Should never get called! */ return NULL;}
-
-/* array_specification [ASSIGN array_initialization] */
-/* array_initialization may be NULL ! */
-void *visit(array_spec_init_c *symbol) {
-  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
-  if (implicit_id_count != 1) ERROR;
-  /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
-   * has already been defined. So, we simly print out the id of that C datatpe...
-   */
-  return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
-}
-
-/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
-void *visit(array_specification_c *symbol) {
-  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
-  if (implicit_id_count != 1) ERROR;
-  /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
-   * has already been defined. So, we simly print out the id of that C datatpe...
-   */
-  return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
-}
-
-
-/* ref_spec:  REF_TO (non_generic_type_name | function_block_type_name) */
-void *visit(ref_spec_c *symbol) {
-  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
-  if (implicit_id_count != 1) ERROR;
-  /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
-   * has already been defined. So, we simly print out the id of that C datatpe...
-   */
-  return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
-}
-
-/* For the moment, we do not support initialising reference data types */
-/* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */ 
-/* NOTE: ref_initialization may be NULL!! */
-// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
-void *visit(ref_spec_init_c *symbol) {
-  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
-  if (implicit_id_count != 1) ERROR;
-  /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
-   * has already been defined. So, we simly print out the id of that C datatpe...
-   */
-  return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
-}
-
-/* ref_type_decl: identifier ':' ref_spec_init */
-void *visit(ref_type_decl_c *symbol) {ERROR;/* Should never get called! */ return NULL;}
-
-
-
-
-
-/* NOTE:     visit(subrange_spec_init_c *)
- *      and  visit(subrange_specification_c *)
- *      together simply print out the integer datatype
- *      on which the subrange is based.
- *
- *      Future code clean-ups should delete these two
- *      visit mehotds, and make sure whoever calls them 
- *      uses symbol->datatype instead!
- */ 
-/* subrange_specification ASSIGN signed_integer */
-void *visit(subrange_spec_init_c *symbol) {
-  TRACE("subrange_spec_init_c");
-  symbol->subrange_specification->accept(*this);
-  return NULL;
-}
-
-/*  integer_type_name '(' subrange')' */
-void *visit(subrange_specification_c *symbol) {
-  TRACE("subrange_specification_c");
-  symbol->integer_type_name->accept(*this);
-  return NULL;
-}
-  
-
-/* NOTE: Why is this here? This visit() method should not be here!!
- * TODO: Figure out who is dependent on this method, and move it to its correct location!
- */
-/* helper symbol for array_specification */
-/* array_subrange_list ',' subrange */
-void *visit(array_subrange_list_c *symbol) {
-  TRACE("array_subrange_list_c");
-  print_list(symbol);
-  return NULL;
-}  
-  
-  
 /*********************/
 /* B 1.4 - Variables */
 /*********************/
@@ -720,6 +662,7 @@
   return NULL;
 }
 
+
 /********************************************/
 /* B.1.4.1   Directly Represented Variables */
 /********************************************/
@@ -730,15 +673,12 @@
 }
 
 
-
 /*************************************/
 /* B.1.4.2   Multi-element Variables */
 /*************************************/
-#if 0
 /*  subscripted_variable '[' subscript_list ']' */
-SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
-
-#endif
+//SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+
 
 /*  record_variable '.' field_selector */
 /*  WARNING: input and/or output variables of function blocks
@@ -845,10 +785,205 @@
 
 
 
-
-
-
-
-
-
-
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+
+
+
+/* generate_c_base_and_typeid_c
+ * ----------------------------
+ *   This is similar to the generate_c_base_c (from which it inherits), but it also handles
+ *   all the derived datatypes. Note that it does not generate C code for the declaration of
+ *   those datatypes (that is what generate_c_typedecl_c is for), but rather it merely
+ *   generates the name/id of a derived datatype.
+ *   Note too that not all derived datatypes in the IEC 61131-3 have a name (for example, 
+ *   VAR a: ARRAY [3..5] of INT END_VAR), in which case an alias for this datatype should 
+ *   have been previously generated by either generate_c_typedecl_c or generate_implicit_typedecl_c.
+ */
+class generate_c_base_and_typeid_c: public generate_c_base_c {
+
+  public:
+     generate_c_base_and_typeid_c(stage4out_c *s4o_ptr): generate_c_base_c(s4o_ptr) {}
+    ~generate_c_base_and_typeid_c(void) {}
+
+
+/*************************/
+/* B.1 - Common elements */
+/*************************/
+/*******************************************/
+/* B 1.1 - Letters, digits and identifiers */
+/*******************************************/
+    void *visit(derived_datatype_identifier_c *symbol) {
+      if (get_datatype_info_c::is_array(symbol->datatype)) {
+        return symbol->datatype->accept(*this);
+      }
+      return print_token(symbol);
+    }
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+/**********************/
+/* B.1.3 - Data types */
+/**********************/
+/***********************************/
+/* B 1.3.1 - Elementary Data Types */
+/***********************************/
+/********************************/
+/* B.1.3.2 - Generic data types */
+/********************************/
+    /* Currently only used in REF_TO ANY, which is mapped onto (void *) */
+    void *visit(generic_type_any_c *symbol)      {s4o.print("void");    return NULL;}
+
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+
+/*  subrange_type_name ':' subrange_spec_init */
+void *visit(subrange_type_declaration_c *symbol) {return symbol->subrange_type_name->accept(*this);}
+
+/* subrange_specification ASSIGN signed_integer */
+void *visit(subrange_spec_init_c *symbol) {return symbol->subrange_specification->accept(*this);}
+
+/*  integer_type_name '(' subrange')' */
+void *visit(subrange_specification_c *symbol) {return symbol->integer_type_name->accept(*this);}
+
+/*  enumerated_type_name ':' enumerated_spec_init */
+void *visit(enumerated_type_declaration_c *symbol) {return symbol->enumerated_type_name->accept(*this);}
+
+/* enumerated_specification ASSIGN enumerated_value */
+void *visit(enumerated_spec_init_c *symbol) {return symbol->enumerated_specification->accept(*this);}
+
+
+/* enumerated_type_name '#' identifier */
+/* Handled by generate_c_base_c class!!
+void *visit(enumerated_value_c *symbol) {}
+*/
+
+/*  identifier ':' array_spec_init */
+void *visit(array_type_declaration_c *symbol) {
+  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+  if (1 != implicit_id_count) ERROR;
+  return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
+}
+
+
+
+/* array_specification [ASSIGN array_initialization] */
+/* array_initialization may be NULL ! */
+void *visit(array_spec_init_c *symbol) {
+  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+  if (1 == implicit_id_count) return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
+  if (0 == implicit_id_count) return symbol->datatype->accept(*this);
+  return NULL;
+}
+
+/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+void *visit(array_specification_c *symbol) {
+  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+  if (1 != implicit_id_count) ERROR;
+  return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
+}
+
+
+
+/*  simple_type_name ':' simple_spec_init */
+void *visit(simple_type_declaration_c *symbol) {return symbol->simple_type_name->accept(*this);}
+
+/* simple_specification [ASSIGN constant] */
+//SYM_REF2(simple_spec_init_c, simple_specification, constant)
+// <constant> may be NULL
+void *visit(simple_spec_init_c *symbol) {return symbol->simple_specification->accept(*this);}
+
+/*  structure_type_name ':' structure_specification */
+//SYM_REF2(structure_type_declaration_c, structure_type_name, structure_specification)
+void *visit(structure_type_declaration_c *symbol) {return symbol->structure_type_name->accept(*this);}
+
+/* structure_type_name ASSIGN structure_initialization */
+/* structure_initialization may be NULL ! */
+//SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
+void *visit(initialized_structure_c *symbol) {return symbol->structure_type_name->accept(*this);}
+
+
+
+/* ref_spec:  REF_TO (non_generic_type_name | function_block_type_name) */
+// SYM_REF1(ref_spec_c, type_name)
+void *visit(ref_spec_c *symbol) { 
+  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+  if (implicit_id_count  > 1) ERROR;
+  if (implicit_id_count == 1) {
+      /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
+       * has already been defined. So, we simly print out the id of that C datatpe...
+       */
+    return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
+  }
+  /* This is NOT part of an implicitly declared datatype (i.e. we are being called from an visit(ref_type_decl_c *),
+   * through the visit(ref_spec_init_c*)), so we need to simply print out the name of the datatype we reference to.
+   */
+  //debug_c::print(symbol); ERROR;
+  symbol->type_name->accept(*this);
+  s4o.print("*");
+  return NULL;
+}
+
+/* For the moment, we do not support initialising reference data types */
+/* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */ 
+/* NOTE: ref_initialization may be NULL!! */
+// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+void *visit(ref_spec_init_c *symbol) {
+  /* NOTE  An ref_type_decl_c will be created in stage4 for each implicitly defined REF_TO datatype,
+   *       and this generate_c_typedecl_c will be called to define that REF_TO datatype in C.
+   *       However, every implictly defined REF_TO datatype with the exact same parameters will be mapped
+   *       to the same identifier (e.g: __REF_TO_INT).
+   *       In order for the C compiler not to find the same datatype being defined two or more times, 
+   *       we will keep track of the datatypes that have already been declared, and henceforth
+   *       only declare the datatypes that have not been previously defined.
+   */
+  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+  if (1  < implicit_id_count) ERROR;
+  if (1 == implicit_id_count)
+    return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
+  return symbol->ref_spec->accept(*this); // this is probably pointing to an identifier_c !!
+}
+
+/* ref_type_decl: identifier ':' ref_spec_init */
+// SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
+void *visit(ref_type_decl_c *symbol) {
+  TRACE("ref_type_decl_c");
+  /* NOTE  An ref_type_decl_c will be created in stage4 for each implicitly defined REF_TO datatype,
+   *       and this generate_c_typedecl_c will be called to define that REF_TO datatype in C.
+   *       However, every implictly defined REF_TO datatype with the exact same parameters will be mapped
+   *       to the same identifier (e.g: __REF_TO_INT).
+   *       In order for the C compiler not to find the same datatype being defined two or more times, 
+   *       we will keep track of the datatypes that have already been declared, and henceforth
+   *       only declare the datatypes that have not been previously defined.
+   */
+  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+  if (0 != implicit_id_count) ERROR;
+  //symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(generate_c_base);
+  return symbol->ref_type_name->accept(*this);
+}
+
+
+}; /* class generate_c_base_and_typeid_c */
+
+
+
+
+
+
+
+
+
+
+
+
+
--- a/stage4/generate_c/generate_c_configbody.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_configbody.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -22,11 +22,11 @@
  * used in safety-critical situations without a full and competent review.
  */
 
-class generate_c_configbody_c: public generate_c_base_c {
+class generate_c_configbody_c: public generate_c_base_and_typeid_c {
 
   public:
     generate_c_configbody_c(stage4out_c *s4o_ptr)
-    : generate_c_base_c(s4o_ptr) {
+    : generate_c_base_and_typeid_c(s4o_ptr) {
       current_resource_name = NULL;
     }
 
--- a/stage4/generate_c/generate_c_il.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_il.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -126,7 +126,7 @@
 
 
 
-class generate_c_il_c: public generate_c_base_c, il_default_variable_visitor_c {
+class generate_c_il_c: public generate_c_base_and_typeid_c, il_default_variable_visitor_c {
 
   public:
     typedef enum {
@@ -197,7 +197,7 @@
 
   public:
     generate_c_il_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
-    : generate_c_base_c(s4o_ptr),
+    : generate_c_base_and_typeid_c(s4o_ptr),
       implicit_variable_current    (IL_DEFVAR,      NULL),
       implicit_variable_result     (IL_DEFVAR,      NULL),
       implicit_variable_result_back(IL_DEFVAR_BACK, NULL)
--- a/stage4/generate_c/generate_c_inlinefcall.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_inlinefcall.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -26,7 +26,7 @@
 #define INLINE_RESULT_TEMP_VAR "__res"
 #define INLINE_PARAM_COUNT "__PARAM_COUNT"
 
-class generate_c_inlinefcall_c: public generate_c_base_c {
+class generate_c_inlinefcall_c: public generate_c_base_and_typeid_c {
 
   public:
     typedef enum {
@@ -76,7 +76,7 @@
 
   public:
     generate_c_inlinefcall_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
-    : generate_c_base_c(s4o_ptr),
+    : generate_c_base_and_typeid_c(s4o_ptr),
       implicit_variable_current(IL_DEFVAR, NULL)
     {
       search_varfb_instance_type = new search_varfb_instance_type_c(scope);
--- a/stage4/generate_c/generate_c_sfc.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_sfc.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -34,7 +34,7 @@
 /***********************************************************************/
 /***********************************************************************/
 
-class generate_c_sfc_elements_c: public generate_c_base_c {
+class generate_c_sfc_elements_c: public generate_c_base_and_typeid_c {
   
   public:
     typedef enum {
@@ -63,7 +63,7 @@
     
   public:
     generate_c_sfc_elements_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
-    : generate_c_base_c(s4o_ptr) {
+    : generate_c_base_and_typeid_c(s4o_ptr) {
       generate_c_il = new generate_c_il_c(s4o_ptr, name, scope, variable_prefix);
       generate_c_st = new generate_c_st_c(s4o_ptr, name, scope, variable_prefix);
       generate_c_code = new generate_c_SFC_IL_ST_c(s4o_ptr, name, scope, variable_prefix);
@@ -655,7 +655,7 @@
 /***********************************************************************/
 /***********************************************************************/
 
-class generate_c_sfc_c: public generate_c_base_c {
+class generate_c_sfc_c: public generate_c_base_and_typeid_c {
   
   private:
     std::list<VARIABLE> variable_list;
@@ -665,7 +665,7 @@
     
   public:
     generate_c_sfc_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
-    : generate_c_base_c(s4o_ptr) {
+    : generate_c_base_and_typeid_c(s4o_ptr) {
       generate_c_sfc_elements = new generate_c_sfc_elements_c(s4o_ptr, name, scope, variable_prefix);
       search_var_instance_decl = new search_var_instance_decl_c(scope);
       this->set_variable_prefix(variable_prefix);
--- a/stage4/generate_c/generate_c_sfcdecl.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_sfcdecl.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -32,7 +32,7 @@
 /***********************************************************************/
 /***********************************************************************/
 
-class generate_c_sfcdecl_c: protected generate_c_base_c {
+class generate_c_sfcdecl_c: protected generate_c_base_and_typeid_c {
   
   public:
       typedef enum {
@@ -59,7 +59,7 @@
     
   public:
     generate_c_sfcdecl_c(stage4out_c *s4o_ptr, symbol_c *scope, const char *variable_prefix = NULL)
-    : generate_c_base_c(s4o_ptr) {
+    : generate_c_base_and_typeid_c(s4o_ptr) {
       this->set_variable_prefix(variable_prefix);
       search_var_instance_decl = new search_var_instance_decl_c(scope);
     }
--- a/stage4/generate_c/generate_c_st.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_st.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -44,7 +44,7 @@
 /***********************************************************************/
 
 
-class generate_c_st_c: public generate_c_base_c {
+class generate_c_st_c: public generate_c_base_and_typeid_c {
 
   public:
     typedef enum {
@@ -93,7 +93,7 @@
 
   public:
     generate_c_st_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
-    : generate_c_base_c(s4o_ptr) {
+    : generate_c_base_and_typeid_c(s4o_ptr) {
       search_fb_instance_decl    = new search_fb_instance_decl_c   (scope);
       search_varfb_instance_type = new search_varfb_instance_type_c(scope);
       search_var_instance_decl   = new search_var_instance_decl_c  (scope);
--- a/stage4/generate_c/generate_c_typedecl.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_typedecl.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -23,6 +23,221 @@
  */
 #include <stdlib.h>
 
+
+/* Ths class contains two main classes:
+ *    - generate_c_typedecl_c
+ *    - generate_c_implicit_typedecl_c
+ * 
+ * and an auxiliary class
+ *    - generate_datatypes_aliasid_c
+ * 
+ * 
+ * Both the generate_c_typedecl_c and the generate_c_implicit_typedecl_c may set a stage4
+ * annotation (in the stage4 annotation map of each symbol_c) named 
+ *   "generate_c_annotaton__implicit_type_id"
+ * If this annotation is set, the generate_c_base_c will print out this value instead of 
+ * the datatype's name!
+ * 
+ * 
+ * 
+ * generate_c_typedecl_c
+ * ---------------------
+ *   Given a datatype object (i.e. an object in the AST that is also used to define a datatype,
+ *    typically one that may be returned by search_basetype_c), this class will generate the 
+ *    C code to declare an equivakent datatype in C.
+ *   Note that array datatypes are handled in a special way; instead of using the name given
+ *    to it in the IEC 61131-3 source code, and new alias is created for the datatype name in C.
+ *    Eplanations why we do this may be found further on...
+ * 
+ * 
+ * generate_c_implicit_typedecl_c
+ * ------------------------------
+ *   Given a POU or a derived datatype declaration, it will search for any implicitly defined 
+ *    datatypes in that POU/datatype declaration. Implicit datatypes are datatypes that are not 
+ *    explicitly declared and given a name. Example:
+ *       VAR a: ARRAY [9..11] of INT; END_VAR
+ *    Here, the array is implictly delcared.
+ *    For eac implicitly defined datatype, an alias for that datatype is created (by calling
+ *    generate_datatypes_aliasid_c), and a C declaration is generated in C source code (by
+ *    calling generate_c_typedecl_c).
+ * 
+ * 
+ * generate_datatypes_aliasid_c
+ * ----------------------------
+ *   Given a datatype object (i.e. an object in the AST that defines a datatype), it will create
+ *    an alias name for that datatype.
+ *    This class is used by both the generate_c_implicit_typedecl_c, and the generate_c_typedecl_c
+ *    classes!
+ */
+
+
+
+
+
+
+/* generate an alias/name (identifier) for array and REF_TO datatypes */
+/*
+ *  The generated alias is created based on the structure of the datatype itself, in order to
+ *  guarantee that any two datatypes that have the same internal format will result in the same
+ *  alias.
+ *   examples:
+ *      ARRAY [9..11] of INT        --> __ARRAY_9_11_OF_INT
+ *      REF_TO INT                  --> __REF_TO_INT
+ *      ARRAY [9..11] of REF_TO INT --> __ARRAY_9_11_OF___REF_TO_INT
+ */
+class generate_datatypes_aliasid_c: fcall_visitor_c {
+
+  private:
+    //std::map<std::string, int> inline_array_defined;
+    std::string current_array_name;
+    static generate_datatypes_aliasid_c *singleton_;
+
+  public:
+    generate_datatypes_aliasid_c(void) {};
+
+    virtual ~generate_datatypes_aliasid_c(void) {
+      //inline_array_defined.clear(); // Not really necessary...
+    }
+
+    /* implement the virtual member function declared in fcall_visitor_c */
+    // by default generate an ERROR if a visit method is called, unless it is explicitly handled in generate_datatypes_aliasid_c
+    void fcall(symbol_c *symbol) {ERROR;} 
+
+    static identifier_c *create_id(symbol_c *symbol) {
+      if (NULL == singleton_) singleton_ = new generate_datatypes_aliasid_c();
+      if (NULL == singleton_) ERROR;
+      singleton_->current_array_name = "";
+      symbol->accept(*singleton_);
+      const char *str1 = singleton_->current_array_name.c_str();
+      char       *str2 = (char *)malloc(strlen(str1)+1);
+      if (NULL == str2) ERROR;
+      strcpy(str2, str1);
+      identifier_c *id = new identifier_c(str2);
+      /* Copy all the anotations in the symbol_c object 'symbol' to the newly created 'id' object
+       *   This includes the location (in the IEC 61131-3 source file) annotations set in stage1_2,
+       *   the symbol->datatype set in stage3, and any other anotaions that may be created in the future!
+       */
+      *(dynamic_cast<symbol_c *>(id)) = *(dynamic_cast<symbol_c *>(symbol));
+      return id;
+    }
+    
+    /*************************/
+    /* B.1 - Common elements */
+    /*************************/
+    /**********************/
+    /* B.1.3 - Data types */
+    /**********************/
+    /***********************************/
+    /* B 1.3.1 - Elementary Data Types */
+    /***********************************/
+    /***********************************/
+    /* B 1.3.2 - Generic Data Types    */
+    /***********************************/
+    /********************************/
+    /* B 1.3.3 - Derived data types */
+    /********************************/
+    /* ref_spec:  REF_TO (non_generic_type_name | function_block_type_name) */
+    void *visit(ref_spec_c *symbol) {
+      current_array_name = "__REF_TO_";
+      current_array_name += get_datatype_info_c::get_id_str(symbol->type_name);
+      return NULL;
+    }
+
+    /******************************************/
+    /* B 1.4.3 - Declaration & Initialization */
+    /******************************************/
+    /* array_specification [ASSIGN array_initialization] */
+    /* array_initialization may be NULL ! */
+    void *visit(array_spec_init_c *symbol) {
+      if (NULL == symbol->datatype) ERROR;
+      symbol->datatype->accept(*this); // the base datatype should be an array_specification_c !!
+      return NULL;
+    }
+
+    /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+    void *visit(array_specification_c *symbol) {
+      current_array_name = "__ARRAY_OF_";
+      if (    get_datatype_info_c::is_ref_to(symbol->non_generic_type_name)
+          && (get_datatype_info_c::get_ref_to(symbol->non_generic_type_name) != NULL)) {
+        /* handle situations where we have 2 impliclitly defined datatype, namely a REF_TO inside an ARRAY
+         *    e.g. TYPE array_of_ref_to_sint : ARRAY [1..3] OF  REF_TO  SINT; END_TYPE
+         * The second condition (get_datatype_info_c::get_ref_to(symbol->non_generic_type_name) != NULL)
+         * in the above if() is to make sure we use the standard algorithm if the array is of a previously 
+         * defined REF_TO type, in which case symbol->non_generic_type_name will reference an identifier_c!
+         *    e.g. TYPE array_of_ref_to_sint : ARRAY [1..3] OF  REF_TO  SINT; END_TYPE
+         */
+        current_array_name += "__REF_TO_";
+        current_array_name += get_datatype_info_c::get_id_str(get_datatype_info_c::get_ref_to(symbol->non_generic_type_name));
+      } else {
+        current_array_name += get_datatype_info_c::get_id_str(symbol->non_generic_type_name);
+      }
+      symbol->array_subrange_list->accept(*this);
+      return NULL;
+    }
+
+    /* helper symbol for array_specification */
+    /* array_subrange_list ',' subrange */
+    void *visit(array_subrange_list_c *symbol) {
+      for(int i = 0; i < symbol->n; i++) {symbol->elements[i]->accept(*this);}
+      return NULL;
+    }
+
+    /*  signed_integer DOTDOT signed_integer */
+    //SYM_REF2(subrange_c, lower_limit, upper_limit)
+    void *visit(subrange_c *symbol) {
+      current_array_name += "_";
+      std::stringstream ss;
+      ss << symbol->dimension;
+      current_array_name += ss.str();
+      return NULL;
+    }
+
+
+};
+
+
+generate_datatypes_aliasid_c *generate_datatypes_aliasid_c::singleton_ = NULL;
+
+
+
+
+
+
+
+/***************************************************************************************/
+/***************************************************************************************/
+/***************************************************************************************/
+/***************************************************************************************/
+
+/* Given an object in the AST that defines a datatype, generate the C source code that declares an
+ * equivalent dataype in C.
+ * WARNING: This class maintains internal state in the datatypes_already_defined map.
+ *          Using multiple isntances of this class may result in different C source code
+ *          compared to when a single instance of this class is used for all datatype declarations!
+ * 
+ * Except for arrays, the C datatype will have the same name as the name of the datatype in the
+ * IEC 61131-3 source code.
+ * For arrays an alias is created for each datatype. This alias has the property of being equal
+ * for arrays with the same internal structure.
+ * 
+ * Example:
+ *  TYPE
+ *      array1: ARRAY [9..11] of INT;
+ *      array2: ARRAY [9..11] of INT;
+ *  END_TYPE
+ * 
+ * will result in both arrays having the same name (__ARRAY_9_11_OF_INT) in the C source code.
+ * 
+ * A single C datatype declaration will be generated for both arrays
+ *  (the datatypes_already_defined keeps track of which datatypes have already been declared in C)
+ * This method of handling arrays is needed when the relaxed datatype model is used 
+ * (see get_datatype_info_c for explanation on the relaxed datatype model).
+ */
+/* Notice that this class inherits from generate_c_base_c, and not from generate_c_base_and_typeid_c.
+ * This is intentional! 
+ * Whenever this class needs to print out the id of a datatype, it will explicitly use a private instance
+ * (generate_c_typeid) of generate_c_base_and_typeid_c!
+ */
 class generate_c_typedecl_c: public generate_c_base_c {
 
   protected:
@@ -30,18 +245,18 @@
 
   private:
     symbol_c* current_type_name;
-    bool array_is_derived;
-    generate_c_base_c *basedecl;
-
+    generate_c_base_and_typeid_c *generate_c_typeid;
+    std::map<std::string, int> datatypes_already_defined;
+    
   public:
-    generate_c_typedecl_c(stage4out_c *s4o_ptr): generate_c_base_c(s4o_ptr), s4o_incl(*s4o_ptr) {
+    generate_c_typedecl_c(stage4out_c *s4o_ptr): generate_c_base_c(s4o_ptr), s4o_incl(*s4o_ptr) /*, generate_c_print_typename(s4o_ptr) */{
       current_typedefinition = none_td;
       current_basetypedeclaration = none_bd;
       current_type_name = NULL;
-      basedecl = new generate_c_base_c(&s4o_incl);
+      generate_c_typeid = new generate_c_base_and_typeid_c(&s4o_incl);
     }
     ~generate_c_typedecl_c(void) {
-      delete basedecl;
+      delete generate_c_typeid;
     }
 
     typedef enum {
@@ -71,13 +286,11 @@
       if (visitor == NULL) visitor = this;
 
       if (list->n > 0) {
-//std::cout << "generate_c_base_c::print_list(n = " << list->n << ")   000\n";
         s4o_incl.print(pre_elem_str);
         list->elements[0]->accept(*visitor);
       }
 
       for(int i = 1; i < list->n; i++) {
-//std::cout << "generate_c_base_c::print_list   " << i << "\n";
         s4o_incl.print(inter_elem_str);
         list->elements[i]->accept(*visitor);
       }
@@ -100,8 +313,6 @@
 /*******************************************/
 /* B 1.1 - Letters, digits and identifiers */
 /*******************************************/
-  /* done in base class(es) */
-
 /*********************/
 /* B 1.2 - Constants */
 /*********************/
@@ -154,7 +365,7 @@
   current_type_name = symbol->subrange_type_name;
 
   s4o_incl.print("__DECLARE_DERIVED_TYPE(");
-  current_type_name->accept(*basedecl);
+  current_type_name->accept(*generate_c_typeid);
   s4o_incl.print(",");
   current_basetypedeclaration = subrangebasetype_bd;
   symbol->subrange_spec_init->accept(*this);
@@ -184,16 +395,16 @@
   if (current_typedefinition == subrange_td) {
     switch (current_basetypedeclaration) {
       case subrangebasetype_bd:
-        symbol->integer_type_name->accept(*basedecl);
+        symbol->integer_type_name->accept(*generate_c_typeid);
         break;
       case subrangetest_bd:
         if (symbol->subrange != NULL) {
           s4o_incl.print("static inline ");
-          current_type_name->accept(*basedecl);
+          current_type_name->accept(*generate_c_typeid);
           s4o_incl.print(" __CHECK_");
-          current_type_name->accept(*basedecl);
+          current_type_name->accept(*generate_c_typeid);
           s4o_incl.print("(");
-          current_type_name->accept(*basedecl);
+          current_type_name->accept(*generate_c_typeid);
           s4o_incl.print(" value) {\n");
           s4o_incl.indent_right();
 
@@ -217,9 +428,9 @@
         }
         else {
           s4o_incl.print("#define __CHECK_");
-          current_type_name->accept(*basedecl);
+          current_type_name->accept(*generate_c_typeid);
           s4o_incl.print(" __CHECK_");
-          symbol->integer_type_name->accept(*basedecl);
+          symbol->integer_type_name->accept(*generate_c_typeid);
           s4o_incl.print("\n");
         }
         break;
@@ -247,19 +458,19 @@
       break;
     case subrange_td:
       s4o_incl.print(s4o_incl.indent_spaces + "if (value < ");
-      symbol->lower_limit->accept(*basedecl);
+      symbol->lower_limit->accept(*generate_c_typeid);
       s4o_incl.print(")\n");
       s4o_incl.indent_right();
       s4o_incl.print(s4o_incl.indent_spaces + "return ");
-      symbol->lower_limit->accept(*basedecl);
+      symbol->lower_limit->accept(*generate_c_typeid);
       s4o_incl.print(";\n");
       s4o_incl.indent_left();
       s4o_incl.print(s4o_incl.indent_spaces + "else if (value > ");
-      symbol->upper_limit->accept(*basedecl);
+      symbol->upper_limit->accept(*generate_c_typeid);
       s4o_incl.print(")\n");
       s4o_incl.indent_right();
       s4o_incl.print(s4o_incl.indent_spaces + "return ");
-      symbol->upper_limit->accept(*basedecl);
+      symbol->upper_limit->accept(*generate_c_typeid);
       s4o_incl.print(";\n");
       s4o_incl.indent_left();
       s4o_incl.print(s4o_incl.indent_spaces + "else\n");
@@ -280,7 +491,7 @@
   current_type_name = symbol->enumerated_type_name;
 
   s4o_incl.print("__DECLARE_ENUMERATED_TYPE(");
-  current_type_name->accept(*basedecl);
+  current_type_name->accept(*generate_c_typeid);
   s4o_incl.print(",\n");
   s4o_incl.indent_right();
   symbol->enumerated_spec_init->accept(*this);
@@ -299,7 +510,7 @@
   if (current_typedefinition == enumerated_td)
     symbol->enumerated_specification->accept(*this);
   else
-    symbol->enumerated_specification->accept(*basedecl);
+    symbol->enumerated_specification->accept(*generate_c_typeid);
   return NULL;
 }
 
@@ -319,22 +530,40 @@
 /*  identifier ':' array_spec_init */
 void *visit(array_type_declaration_c *symbol) {
   TRACE("array_type_declaration_c");
+  
+  // NOTE: remeber that symbol->array_spec_init may point to an identifier_c, which is why we use symbol->array_spec_init->datatype instead!
+  if (NULL == symbol->array_spec_init->datatype) ERROR;
+  identifier_c *id = generate_datatypes_aliasid_c::create_id(symbol->array_spec_init->datatype);
+  
+  /* NOTE  An array_type_declaration_c will be created in stage4 for each implicitly defined array,
+   *       and this generate_c_typedecl_c will be called to define that array in C.
+   *       However, every implictly defined array with the exact same parameters will be mapped
+   *       to the same identifier (e.g: __ARRAY_OF_INT_33 where 33 is the number of elements in the array).
+   *       In order for the C compiler not to find the same datatype being defined two or more times, 
+   *       we will keep track of the array datatypes that have already been declared, and henceforth
+   *       only declare arrays that have not been previously defined.
+   */
+  if (datatypes_already_defined.find(id->value) != datatypes_already_defined.end())
+    goto end; // already defined. No need to define it again!!
+  datatypes_already_defined[id->value] = 1; // insert this datatype into the list of already defined arrays!
+  
   current_typedefinition = array_td;
-  current_type_name = symbol->identifier;
-
-  int implicit_id_count = symbol->array_spec_init->anotations_map.count("generate_c_annotaton__implicit_type_id");
-  if (implicit_id_count  > 1) ERROR;
-  if (implicit_id_count == 1)
-    s4o_incl.print("__DECLARE_DERIVED_TYPE(");
-  else
-    s4o_incl.print("__DECLARE_ARRAY_TYPE(");
-  current_type_name->accept(*basedecl);
+  current_type_name = id;
+
+  s4o_incl.print("__DECLARE_ARRAY_TYPE(");
+  current_type_name->accept(*generate_c_typeid);
   s4o_incl.print(",");
   symbol->array_spec_init->accept(*this);
   s4o_incl.print(")\n");
 
   current_type_name = NULL;
   current_typedefinition = none_td;
+
+end:  
+  symbol                 ->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
+  symbol->datatype       ->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
+  symbol->array_spec_init->anotations_map["generate_c_annotaton__implicit_type_id"] = id; // probably not needed, bu let's play safe.
+  
   return NULL;
 }
 
@@ -344,16 +573,6 @@
 /* array_initialization may be NULL ! */
 void *visit(array_spec_init_c *symbol) {
   TRACE("array_spec_init_c");  
-  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
-  if (implicit_id_count  > 1) ERROR;
-  if (implicit_id_count == 1) {
-      /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
-       * has already been defined. So, we simly print out the id of that C datatpe...
-       */
-    symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*basedecl);
-    return NULL;
-  }
-//   if (current_typedefinition != array_td) {debug_c::print(symbol); ERROR;}
   symbol->array_specification->accept(*this);
   return NULL;
 }
@@ -361,17 +580,8 @@
 /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
 void *visit(array_specification_c *symbol) {
   TRACE("array_specification_c");
-  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
-  if (implicit_id_count  > 1) ERROR;
-  if (implicit_id_count == 1) {
-      /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
-       * has already been defined. So, we simly print out the id of that C datatpe...
-       */
-    symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*basedecl);
-    return NULL;
-  }
   // The 2nd and 3rd argument of a call to the __DECLARE_ARRAY_TYPE macro!
-  symbol->non_generic_type_name->accept(*this);
+  symbol->non_generic_type_name->accept(/*generate_c_print_typename*/*generate_c_typeid);
   s4o_incl.print(",");
   current_basetypedeclaration = arraysubrange_bd;
   symbol->array_subrange_list->accept(*this);
@@ -399,14 +609,14 @@
   TRACE("simple_type_declaration_c");
 
   s4o_incl.print("__DECLARE_DERIVED_TYPE(");
-  symbol->simple_type_name->accept(*basedecl);
+  symbol->simple_type_name->accept(*generate_c_typeid);
   s4o_incl.print(",");
   symbol->simple_spec_init->accept(*this);
   s4o_incl.print(")\n");
 
   if (get_datatype_info_c::is_subrange(symbol->simple_type_name)) {
     s4o_incl.print("#define __CHECK_");
-    current_type_name->accept(*basedecl);
+    current_type_name->accept(*generate_c_typeid);
     s4o_incl.print(" __CHECK_");
     symbol->simple_spec_init->accept(*this);
     s4o_incl.print("\n");
@@ -420,7 +630,7 @@
 // <constant> may be NULL
 void *visit(simple_spec_init_c *symbol) {
   TRACE("simple_spec_init_c");
-  symbol->simple_specification->accept(*basedecl);
+  symbol->simple_specification->accept(*generate_c_typeid);
   return NULL;
 }
 
@@ -482,7 +692,7 @@
   current_typedefinition = struct_td;
 
   s4o_incl.print("__DECLARE_STRUCT_TYPE(");
-  symbol->structure_type_name->accept(*basedecl);
+  symbol->structure_type_name->accept(*generate_c_typeid);
   s4o_incl.print(",");
   symbol->structure_specification->accept(*this);
   s4o_incl.print(")\n");
@@ -497,9 +707,7 @@
 //SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
 void *visit(initialized_structure_c *symbol) {
   TRACE("initialized_structure_c");
-  
-  symbol->structure_type_name->accept(*basedecl);
-  
+  symbol->structure_type_name->accept(*generate_c_typeid);
   return NULL;
 }
 
@@ -525,9 +733,9 @@
 void *visit(structure_element_declaration_c *symbol) {
   TRACE("structure_element_declaration_c");
 
-  symbol->spec_init->accept(*this);
+  symbol->spec_init->accept(/*generate_c_print_typename*/*generate_c_typeid);
   s4o_incl.print(" ");
-  symbol->structure_element_name->accept(*basedecl);
+  symbol->structure_element_name->accept(*generate_c_typeid);
   s4o_incl.print(";\n");
   s4o_incl.print(s4o_incl.indent_spaces);
 
@@ -628,20 +836,8 @@
 
 /* ref_spec:  REF_TO (non_generic_type_name | function_block_type_name) */
 // SYM_REF1(ref_spec_c, type_name)
-void *visit(ref_spec_c *symbol) {
-  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
-  if (implicit_id_count  > 1) ERROR;
-  if (implicit_id_count == 1) {
-      /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
-       * has already been defined. So, we simly print out the id of that C datatpe...
-       */
-    symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*basedecl);
-    return NULL;
-  }
-  /* This is NOT part of an implicitly declared datatype (i.e. we are being called from an visit(ref_type_decl_c *),
-   * through the visit(ref_spec_init_c*)), so we need to simply print out the name of the datatype we reference to.
-   */
-  symbol->type_name->accept(*this);
+void *visit(ref_spec_c *symbol) { 
+  symbol->type_name->accept(/*generate_c_print_typename*/*generate_c_typeid);
   s4o_incl.print("*");
   return NULL;
 }
@@ -651,31 +847,31 @@
 /* NOTE: ref_initialization may be NULL!! */
 // SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
 void *visit(ref_spec_init_c *symbol) {
-  int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
-  if (implicit_id_count  > 1) ERROR;
-  if (implicit_id_count == 1) {
-      /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
-       * has already been defined. So, we simly print out the id of that C datatpe...
-       */
-    symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*basedecl);
-    return NULL;
-  }
-  /* This is NOT part of an implicitly declared datatype (i.e. we are being called from an visit(ref_type_decl_c *)),
-   * so we need to simply print out the name of the datatype we reference to.
-   */
-  return symbol->ref_spec->accept(*this);
+  return symbol->ref_spec->accept(*generate_c_typeid);
 }
 
 /* ref_type_decl: identifier ':' ref_spec_init */
 // SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
 void *visit(ref_type_decl_c *symbol) {
   TRACE("ref_type_decl_c");
+
+  /* NOTE  An ref_type_decl_c will be created in stage4 for each implicitly defined REF_TO datatype,
+   *       and this generate_c_typedecl_c will be called to define that REF_TO datatype in C.
+   *       However, every implictly defined REF_TO datatype with the exact same parameters will be mapped
+   *       to the same identifier (e.g: __REF_TO_INT).
+   *       In order for the C compiler not to find the same datatype being defined two or more times, 
+   *       we will keep track of the datatypes that have already been declared, and henceforth
+   *       only declare the datatypes that have not been previously defined.
+   */
+  if (datatypes_already_defined.find(((identifier_c *)(symbol->ref_type_name))->value) != datatypes_already_defined.end())
+    return NULL; // already defined. No need to define it again!!
+  datatypes_already_defined[((identifier_c *)(symbol->ref_type_name))->value] = 1; // insert this datatype into the list of already defined arrays!
   
   current_type_name = NULL;
   current_typedefinition = none_td;
 
   s4o_incl.print("__DECLARE_REFTO_TYPE(");
-  symbol->ref_type_name->accept(*basedecl);
+  symbol->ref_type_name->accept(*generate_c_typeid);
   s4o_incl.print(", ");
   symbol->ref_spec_init->accept(*this);
   s4o_incl.print(")\n");
@@ -688,10 +884,6 @@
 
 
 
-
-
-
-
 /*********************/
 /* B 1.4 - Variables */
 /*********************/
@@ -793,10 +985,176 @@
 /********************************/
   /* leave for derived classes... */
 
-
-
-
 }; /* generate_c_typedecl_c */
 
 
 
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+
+
+/* This class will generate a new datatype for each implicitly declared array datatype
+ * (i.e. arrays declared in a variable declaration, or a struct datatype declaration...)
+ * It will do the same for implicitly declared REF_TO datatypes.
+ * 
+ * Each new implicitly datatype will be atributed an alias, and a C datatype will be declared for that alias.
+ * The alias itself will be stored (annotated) in the datatype object in the AST, using the annotation
+ * map reserved for stage4 anotations. The alias is stored under the "generate_c_annotaton__implicit_type_id"
+ * entry, and this entry will then be used whenever the name of the datatype is needed (to declare a varable,
+ * for example). 
+ * 
+ * The class will be called once for each POU declaration, and once for each derived datatype declaration.
+ * 
+ * e.g.:
+ *      VAR  x: ARRAY [1..3] OF INT; END_VAR   <---- ARRAY  datatype is implicitly declared inside the variable declaration
+ *      VAR  y: REF_TO INT;          END_VAR   <---- REF_TO datatype is implicitly declared inside the variable declaration
+ *      TYPE STRUCT
+ *               a: ARRAY [1..3] OF INT;       <---- ARRAY  datatype is implicitly declared inside the struct type declaration  
+ *               b: REF_TO INT;                <---- REF_TO datatype is implicitly declared inside the struct type declaration
+ *               c: INT;
+ *            END_STRUCT
+ *      END_TYPE
+ */
+class generate_c_implicit_typedecl_c: public iterator_visitor_c {
+  private:
+    generate_c_typedecl_c *generate_c_typedecl_;
+    generate_c_typedecl_c  generate_c_typedecl_local;
+    symbol_c *prefix;
+  public:
+    generate_c_implicit_typedecl_c(stage4out_c *s4o, generate_c_typedecl_c *generate_c_typedecl=NULL) 
+      : generate_c_typedecl_local(s4o) {
+        generate_c_typedecl_ = generate_c_typedecl;
+        if (NULL == generate_c_typedecl_) 
+          generate_c_typedecl_ = &generate_c_typedecl_local;
+        prefix = NULL;
+    };
+    virtual ~generate_c_implicit_typedecl_c(void) {
+    }
+
+    /*************************/
+    /* B.1 - Common elements */
+    /*************************/
+    /**********************/
+    /* B.1.3 - Data types */
+    /**********************/
+    /********************************/
+    /* B 1.3.3 - Derived data types */
+    /********************************/
+    /*  identifier ':' array_spec_init */
+    void *visit(array_type_declaration_c *symbol) {return NULL;} // This is not an implicitly defined array!
+
+    /* ref_spec:  REF_TO (non_generic_type_name | function_block_type_name) */
+    void *visit(ref_spec_c *symbol) {
+      identifier_c *id = generate_datatypes_aliasid_c::create_id(symbol);
+      /* Warning: The following is dangerous... 
+       * We are asking the generate_c_typedecl_c visitor to visit a newly created ref_spec_init_c object
+       * that has not been through stage 3, and therefore does not have stage 3 annotations filled in.
+       * This will only work if generate_c_typedecl_c does ot depend on the stage 3 annotations!
+       */
+      ref_spec_init_c   ref_spec(symbol, NULL);
+      ref_type_decl_c   ref_decl(id, &ref_spec);
+      ref_decl.accept(*generate_c_typedecl_);
+      symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
+      return NULL;
+    }
+
+    /* For the moment, we do not support initialising reference data types */
+    /* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */ 
+    /* NOTE: ref_initialization may be NULL!! */
+    // SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+    void *visit(ref_spec_init_c *symbol) {
+      symbol->ref_spec->accept(*this);
+      int implicit_id_count = symbol->ref_spec->anotations_map.count("generate_c_annotaton__implicit_type_id");
+      if (implicit_id_count  > 1) ERROR;
+      if (implicit_id_count == 1)
+        symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = symbol->ref_spec->anotations_map["generate_c_annotaton__implicit_type_id"];
+      return NULL;
+    }
+
+    /* ref_type_decl: identifier ':' ref_spec_init */
+    void *visit(ref_type_decl_c *symbol) {return NULL;} // This is not an implicitly defined REF_TO!
+
+    /******************************************/
+    /* B 1.4.3 - Declaration & Initialization */
+    /******************************************/
+    void *visit(edge_declaration_c           *symbol) {return NULL;}
+    void *visit(en_param_declaration_c       *symbol) {return NULL;}
+    void *visit(eno_param_declaration_c      *symbol) {return NULL;}
+
+    /* array_specification [ASSIGN array_initialization] */
+    /* array_initialization may be NULL ! */
+    void *visit(array_spec_init_c *symbol) {
+      symbol->array_specification->accept(*this);
+      int implicit_id_count = symbol->array_specification->anotations_map.count("generate_c_annotaton__implicit_type_id");
+      if (implicit_id_count  > 1) ERROR;
+      if (implicit_id_count == 1)
+        symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = symbol->array_specification->anotations_map["generate_c_annotaton__implicit_type_id"];
+      return NULL;
+    }
+
+    /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+    void *visit(array_specification_c *symbol) {
+      identifier_c *id = generate_datatypes_aliasid_c::create_id(symbol);
+      /* Warning: The following is dangerous... 
+       * We are asking the generate_c_typedecl_c visitor to visit a newly created array_type_declaration_c object
+       * that has not been through stage 3, and therefore does not have stage 3 annotations filled in.
+       * This will only work if generate_c_typedecl_c does ot depend on the stage 3 annotations!
+       */
+      array_spec_init_c        array_spec(symbol, NULL);
+      array_type_declaration_c array_decl(id, &array_spec);
+      array_decl.datatype = symbol->datatype;
+      array_spec.datatype = symbol->datatype;
+      array_decl.accept(*generate_c_typedecl_);
+      symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
+      return NULL;
+    }
+    
+    /*  var1_list ':' initialized_structure */
+    // SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure)
+    void *visit(structured_var_init_decl_c   *symbol) {return NULL;}
+
+    /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
+    /* structure_initialization -> may be NULL ! */
+    void *visit(fb_name_decl_c               *symbol) {return NULL;}
+
+    /*  var1_list ':' structure_type_name */
+    //SYM_REF2(structured_var_declaration_c, var1_list, structure_type_name)
+    void *visit(structured_var_declaration_c *symbol) {return NULL;}
+
+
+    /***********************/
+    /* B 1.5.1 - Functions */
+    /***********************/      
+    void *visit(function_declaration_c *symbol) {
+      prefix = symbol->derived_function_name;
+      symbol->var_declarations_list->accept(*this);
+      prefix = NULL;
+      return NULL;
+    }
+    /*****************************/
+    /* B 1.5.2 - Function Blocks */
+    /*****************************/
+    void *visit(function_block_declaration_c *symbol) {
+      prefix = symbol->fblock_name;
+      symbol->var_declarations->accept(*this);
+      prefix = NULL;
+      return NULL;
+    }
+    /**********************/
+    /* B 1.5.3 - Programs */
+    /**********************/    
+    void *visit(program_declaration_c *symbol) {
+      prefix = symbol->program_type_name;
+      symbol->var_declarations->accept(*this);
+      prefix = NULL;
+      return NULL;
+    }
+};
+
+
+
+
+
--- a/stage4/generate_c/generate_c_vardecl.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_vardecl.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -60,7 +60,7 @@
 
 
 // Does this class really need to derive from generate_c_typedecl_c ???
-class generate_c_array_initialization_c: public generate_c_typedecl_c {
+class generate_c_array_initialization_c: public generate_c_base_and_typeid_c {
 
   public:
     typedef enum {
@@ -83,7 +83,7 @@
     unsigned long long int current_initialization_count;
 
   public:
-    generate_c_array_initialization_c(stage4out_c *s4o_ptr): generate_c_typedecl_c(s4o_ptr) {}
+    generate_c_array_initialization_c(stage4out_c *s4o_ptr): generate_c_base_and_typeid_c(s4o_ptr) {}
     ~generate_c_array_initialization_c(void) {}
 
     void init_array_size(symbol_c *array_specification) {
@@ -149,9 +149,7 @@
         case arraysize_am:
           /* look up the type declaration... */
           type_decl = type_symtable.find_value(type_name);
-          if (type_decl == type_symtable.end_value())
-            /* Type declaration not found!! */
-            ERROR;
+          if (type_decl == type_symtable.end_value())   ERROR;  // Type declaration not found!!
           type_decl->accept(*this);
           break;
         default:
@@ -495,7 +493,12 @@
     }
 };
 
-class generate_c_structure_initialization_c: public generate_c_typedecl_c {
+
+
+
+
+
+class generate_c_structure_initialization_c: public generate_c_base_and_typeid_c {
 
   public:
     typedef enum {
@@ -513,7 +516,7 @@
     symbol_c* current_element_default_value;
 
   public:
-    generate_c_structure_initialization_c(stage4out_c *s4o_ptr): generate_c_typedecl_c(s4o_ptr) {}
+    generate_c_structure_initialization_c(stage4out_c *s4o_ptr): generate_c_base_and_typeid_c(s4o_ptr) {}
     ~generate_c_structure_initialization_c(void) {}
 
     void init_structure_default(symbol_c *structure_type_name) {
@@ -572,6 +575,24 @@
       return NULL;
     }
     
+    void *visit(derived_datatype_identifier_c *type_name) {
+      symbol_c *type_decl;
+      switch (current_mode) {
+        case initdefault_sm:
+          /* look up the type declaration... */
+          type_decl = type_symtable.find_value(type_name);
+          if (type_decl == type_symtable.end_value())
+            /* Type declaration not found!! */
+            ERROR;
+          type_decl->accept(*this);
+          break;
+        default:
+          print_token(type_name);
+          break;
+      }
+      return NULL;
+    }
+    
     void *visit(var1_list_c *symbol) {
       int i, j;
       
@@ -689,7 +710,7 @@
 
 
 
-class generate_c_vardecl_c: protected generate_c_base_c {
+class generate_c_vardecl_c: protected generate_c_base_and_typeid_c {
 
   /* A Helper class to the main class... */
   /* print a string, except the first time it is called */
@@ -890,8 +911,11 @@
     void update_type_init(symbol_c *symbol /* a spec_init_c, subrange_spec_init_c, etc... */ ) {
       this->current_var_type_symbol = spec_init_sperator_c::get_spec(symbol);
       this->current_var_init_symbol = spec_init_sperator_c::get_init(symbol);
-      if (NULL == this->current_var_type_symbol)
-        ERROR;
+      if (NULL == this->current_var_type_symbol) ERROR;
+      if (NULL == this->current_var_type_symbol->datatype) {debug_c::print(this->current_var_type_symbol); ERROR;}
+      if (get_datatype_info_c::is_array(this->current_var_type_symbol))
+        this->current_var_type_symbol = this->current_var_type_symbol->datatype; 
+      if (NULL == this->current_var_type_symbol) ERROR;
       if (NULL == this->current_var_init_symbol) {
         /* We try to find the data type's default value... */
         this->current_var_init_symbol = type_initial_value_c::get(this->current_var_type_symbol);
@@ -1097,7 +1121,7 @@
 
   public:
     generate_c_vardecl_c(stage4out_c *s4o_ptr, varformat_t varformat, unsigned int vartype, symbol_c* res_name = NULL)
-    : generate_c_base_c(s4o_ptr) {
+    : generate_c_base_and_typeid_c(s4o_ptr) {
       wanted_varformat = varformat;
       wanted_vartype   = vartype;
       current_vartype  = none_vt;
@@ -1408,7 +1432,8 @@
   /* Start off by setting the current_var_type_symbol and
    * current_var_init_symbol private variables...
    */
-  update_type_init(symbol->array_spec_init);
+  if (NULL == symbol->array_spec_init->datatype) ERROR;
+  update_type_init(symbol->array_spec_init->datatype); // we want to print the name of the base datatype, and nt the derived datatype, so we use '->datatype'!
 
   /* now to produce the c equivalent... */
   if (wanted_varformat == constructorinit_vf) {
@@ -1550,7 +1575,8 @@
   /* Start off by setting the current_var_type_symbol and
    * current_var_init_symbol private variables...
    */
-  update_type_init(symbol->array_specification);
+  if (symbol->array_specification->datatype == NULL) {debug_c::print(symbol->array_specification); ERROR;}
+  update_type_init(symbol->array_specification->datatype); // we want to print the name of the base datatype, and nt the derived datatype, so we use '->datatype'!
 
   /* now to produce the c equivalent... */
   if (wanted_varformat == constructorinit_vf) {
@@ -1839,8 +1865,9 @@
   /* Start off by setting the current_var_type_symbol and
    * current_var_init_symbol private variables...
    */
-  this->current_var_type_symbol = symbol->specification;
-  this->current_var_init_symbol = NULL;
+  update_type_init(symbol->specification);
+  this->current_var_init_symbol = NULL; // We do NOt want to initialize external variables.
+
   if(!get_datatype_info_c::is_type_valid(this->current_var_type_symbol)) ERROR;
   bool is_fb = get_datatype_info_c::is_function_block(this->current_var_type_symbol);
 
--- a/stage4/generate_c/generate_var_list.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_var_list.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -184,7 +184,7 @@
 /***********************************************************************/
 /***********************************************************************/
 
-class generate_var_list_c: protected generate_c_typedecl_c {
+class generate_var_list_c: protected generate_c_base_and_typeid_c {
   
   public:
     typedef struct {
@@ -222,7 +222,7 @@
     
   public:
     generate_var_list_c(stage4out_c *s4o_ptr, symbol_c *scope)
-    : generate_c_typedecl_c(s4o_ptr) {
+    : generate_c_base_and_typeid_c(s4o_ptr) {
       search_type_symbol = new search_type_symbol_c(scope);
       current_var_number = 0;
       current_var_type_symbol = NULL;
--- a/stage4/generate_iec/generate_iec.cc	Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_iec/generate_iec.cc	Sun Nov 16 15:37:12 2014 +0000
@@ -253,7 +253,8 @@
 /*******************************************/
 /* B 1.1 - Letters, digits and identifiers */
 /*******************************************/
-void *visit(identifier_c *symbol) {return print_token(symbol);}
+void *visit(                 identifier_c *symbol) {return print_token(symbol);}
+void *visit(derived_datatype_identifier_c *symbol) {return print_token(symbol);}
 
 /*********************/
 /* B 1.2 - Constants */