merge
authormjsousa
Tue, 11 Feb 2014 10:55:27 +0000
changeset 864 300c27c08753
parent 862 2b6b1202f8a8 (diff)
parent 863 06820d03a433 (current diff)
child 865 7365c3e5c9ae
merge
stage4/generate_c/generate_c.cc
stage4/generate_c/generate_c_st.cc
--- a/absyntax/absyntax.def	Mon Jan 06 12:25:21 2014 +0000
+++ b/absyntax/absyntax.def	Tue Feb 11 10:55:27 2014 +0000
@@ -862,6 +862,10 @@
 /* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
 SYM_REF5(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, enumvalue_symtable_t enumvalue_symtable;)
 
+/* intermediate helper symbol for configuration_declaration  */
+/*  { global_var_declarations_list }   */
+SYM_LIST(global_var_declarations_list_c)
+
 /* helper symbol for configuration_declaration */
 SYM_LIST(resource_declaration_list_c)
 
--- a/absyntax_utils/get_datatype_info.cc	Mon Jan 06 12:25:21 2014 +0000
+++ b/absyntax_utils/get_datatype_info.cc	Tue Feb 11 10:55:27 2014 +0000
@@ -292,7 +292,7 @@
 
 
 bool get_datatype_info_c::is_subrange(symbol_c *type_symbol) {
-  symbol_c *type_decl = search_base_type_c::get_basetype_decl(type_symbol); /* NOTE: will work correctly once we update the way search_base_type_c works, by adding a new search_effective_type:c */
+  symbol_c *type_decl = search_base_type_c::get_equivtype_decl(type_symbol); /* NOTE: do NOT call search_base_type_c !! */
   if (NULL == type_decl)                                             {return false;}
   
   if (typeid(*type_decl) == typeid(subrange_type_declaration_c))     {return true;}   /*  subrange_type_name ':' subrange_spec_init */
--- a/absyntax_utils/search_base_type.cc	Mon Jan 06 12:25:21 2014 +0000
+++ b/absyntax_utils/search_base_type.cc	Tue Feb 11 10:55:27 2014 +0000
@@ -54,7 +54,7 @@
 
 
 
-search_base_type_c::search_base_type_c(void) {current_type_name = NULL; current_basetype = NULL;}
+search_base_type_c::search_base_type_c(void) {current_basetype_name = NULL; current_basetype = NULL; current_equivtype = NULL;}
 
 /* static method! */
 void search_base_type_c::create_singleton(void) {
@@ -63,11 +63,25 @@
 }
 
 /* static method! */
+symbol_c *search_base_type_c::get_equivtype_decl(symbol_c *symbol) {
+  create_singleton();
+  if (NULL == symbol)    return NULL; 
+  search_base_type_singleton->current_basetype_name = NULL;
+  search_base_type_singleton->current_basetype  = NULL; 
+  search_base_type_singleton->current_equivtype = NULL; 
+  symbol_c *basetype = (symbol_c *)symbol->accept(*search_base_type_singleton);
+  if (NULL != search_base_type_singleton->current_equivtype)
+    return search_base_type_singleton->current_equivtype;
+  return basetype;
+}
+
+/* static method! */
 symbol_c *search_base_type_c::get_basetype_decl(symbol_c *symbol) {
   create_singleton();
   if (NULL == symbol)    return NULL; 
-  search_base_type_singleton->current_type_name = NULL;
+  search_base_type_singleton->current_basetype_name = NULL;
   search_base_type_singleton->current_basetype  = NULL; 
+  search_base_type_singleton->current_equivtype = NULL; 
   return (symbol_c *)symbol->accept(*search_base_type_singleton);
 }
 
@@ -75,10 +89,11 @@
 symbol_c *search_base_type_c::get_basetype_id  (symbol_c *symbol) {
   create_singleton();
   if (NULL == symbol)    return NULL; 
-  search_base_type_singleton->current_type_name = NULL;
+  search_base_type_singleton->current_basetype_name = NULL;
   search_base_type_singleton->current_basetype  = NULL; 
+  search_base_type_singleton->current_equivtype = NULL; 
   symbol->accept(*search_base_type_singleton);
-  return (symbol_c *)search_base_type_singleton->current_type_name;
+  return (symbol_c *)search_base_type_singleton->current_basetype_name;
 }
 
 
@@ -93,7 +108,7 @@
 void *search_base_type_c::visit(identifier_c *type_name) {
   symbol_c *type_decl;
 
-  this->current_type_name = type_name;
+  this->current_basetype_name = type_name;
   /* if we have reached this point, it is because the current_basetype is not yet pointing to the base datatype we are looking for,
    * so we will be searching for the delcaration of the type named in type_name, which might be the base datatype (we search recursively!)
    */
@@ -210,16 +225,21 @@
 
 /*  subrange_type_name ':' subrange_spec_init */
 void *search_base_type_c::visit(subrange_type_declaration_c *symbol) {
+  this->current_equivtype = symbol;
   return symbol->subrange_spec_init->accept(*this);
 }
 
 /* subrange_specification ASSIGN signed_integer */
 void *search_base_type_c::visit(subrange_spec_init_c *symbol) {
+  if (NULL == this->current_equivtype)
+    this->current_equivtype = symbol;
   return symbol->subrange_specification->accept(*this);
 }
 
 /*  integer_type_name '(' subrange')' */
 void *search_base_type_c::visit(subrange_specification_c *symbol) {
+  if (NULL == this->current_equivtype)
+    this->current_equivtype = symbol;
   return symbol->integer_type_name->accept(*this);
 }
 
@@ -228,7 +248,7 @@
 
 /*  enumerated_type_name ':' enumerated_spec_init */
 void *search_base_type_c::visit(enumerated_type_declaration_c *symbol) {
-  this->current_type_name = symbol->enumerated_type_name;
+  this->current_basetype_name = symbol->enumerated_type_name;
   /* NOTE: We want search_base_type_c to return a enumerated_type_declaration_c as the base datatpe if possible
    *       (i.e. if it is a named datatype declared inside a TYPE ... END_TYPE declarations, as opposed to an
    *        anonymous datatype declared in a VAR ... AND_VAR declaration).
@@ -266,7 +286,7 @@
 
 /*  identifier ':' array_spec_init */
 void *search_base_type_c::visit(array_type_declaration_c *symbol) {
-  this->current_type_name = symbol->identifier;
+  this->current_basetype_name = symbol->identifier;
   return symbol->array_spec_init->accept(*this);
 }
 
@@ -303,7 +323,7 @@
  *       structure_element_declaration_list_c
  */
 void *search_base_type_c::visit(structure_type_declaration_c *symbol)  {
-  this->current_type_name = symbol->structure_type_name;
+  this->current_basetype_name = symbol->structure_type_name;
   return symbol->structure_specification->accept(*this);
 }
 
@@ -370,14 +390,14 @@
 /* INITIAL_STEP step_name ':' action_association_list END_STEP */
 // SYM_REF2(initial_step_c, step_name, action_association_list)
 void *search_base_type_c::visit(initial_step_c *symbol) {
-  this->current_type_name = NULL; /* this pseudo data type does not have a type name! */
+  this->current_basetype_name = NULL; /* this pseudo data type does not have a type name! */
   return (void *)symbol;
 }
 
 /* STEP step_name ':' action_association_list END_STEP */
 // SYM_REF2(step_c, step_name, action_association_list)
 void *search_base_type_c::visit(step_c *symbol) {
-  this->current_type_name = NULL; /* this pseudo data type does not have a type name! */
+  this->current_basetype_name = NULL; /* this pseudo data type does not have a type name! */
   return (void *)symbol;
 }
 
--- a/absyntax_utils/search_base_type.hh	Mon Jan 06 12:25:21 2014 +0000
+++ b/absyntax_utils/search_base_type.hh	Tue Feb 11 10:55:27 2014 +0000
@@ -31,19 +31,35 @@
  */
 
 
-/* Determine the data type on which another data type is based on.
- * If a new default initial value is given, we DO NOT consider it a
- * new base class, and continue looking further!
- *
- * E.g. TYPE new_int_t : INT; END_TYPE;
- *      TYPE new_int2_t : INT = 2; END_TYPE;
- *      TYPE new_subr_t : INT (4..5); END_TYPE;
- *
- *    new_int_t is really an INT!!
- *    new_int2_t is also really an INT!!
- *    new_subr_t is also really an INT!!
- *
- * Note that a FB declaration is also considered a base type, as
+/* Determine the data type on which another data type is based on. */
+
+/*
+ * What is a Base Type?
+ *    A base type is the fundamental data type from which the type is derived.
+ *    The main idea is that if two datatyes (A and B) share a common base type, 
+ *    then these two datatypes may be used interchangeably in an expression.
+ * 
+ * What is an Equivalent Type? 
+ *    An equivalent type is the data type from which the type is derived.
+ *    The Base type and the Equivalent type will always be the same, with the
+ *    exception of subranges!
+ *
+ * E.g. TYPE new_int_t  : INT; END_TYPE;
+ *      TYPE new_int2_t : INT := 2; END_TYPE;
+ *      TYPE new_int3_t : new_int2_t := 3; END_TYPE;
+ *      TYPE new_sub_t  : INT (4..10); END_TYPE;
+ *      TYPE new_sub2_t : new_sub_t  := 5 ; END_TYPE;
+ *      TYPE new_sub3_t : new_sub2_t := 6 ; END_TYPE;
+ *      TYPE new_sub4_t : new_int3_t (4..10); END_TYPE;    <-----  This is NOT legal syntax!
+ *
+ *    new_int_t   : base type->INT          equivalent type->INT
+ *    new_int2_t  : base type->INT          equivalent type->INT
+ *    new_int3_t  : base type->INT          equivalent type->INT
+ *    new_sub_t   : base type->INT          equivalent type->new_sub_t
+ *    new_sub2_t  : base type->INT          equivalent type->new_sub_t
+ *    new_sub3_t  : base type->INT          equivalent type->new_sub_t
+ *
+ * Note too that a FB declaration is also considered a base type, as
  * we may have FB instances declared of a specific FB type.
  */
 
@@ -51,8 +67,9 @@
 class search_base_type_c: public null_visitor_c {
 
   private:
-    symbol_c *current_type_name;
+    symbol_c *current_basetype_name;
     symbol_c *current_basetype;
+    symbol_c *current_equivtype;
     static search_base_type_c *search_base_type_singleton; // Make this a singleton class!
     
   private:  
@@ -60,8 +77,9 @@
 
   public:
     search_base_type_c(void);
-    static symbol_c *get_basetype_decl (symbol_c *symbol);
-    static symbol_c *get_basetype_id   (symbol_c *symbol);
+    static symbol_c *get_equivtype_decl(symbol_c *symbol);  /* get the Equivalent Type declaration */
+    static symbol_c *get_basetype_decl (symbol_c *symbol);  /* get the Base       Type declaration */
+    static symbol_c *get_basetype_id   (symbol_c *symbol);  /* get the Base       Type identifier  */
 
   public:
   /*************************/
--- a/stage1_2/iec_bison.yy	Mon Jan 06 12:25:21 2014 +0000
+++ b/stage1_2/iec_bison.yy	Tue Feb 11 10:55:27 2014 +0000
@@ -1046,7 +1046,7 @@
 //  - configuration_declaration
 //  - resource_declaration
 //
-%type  <leaf>	optional_global_var_declarations
+%type  <list>	global_var_declarations_list
 // helper symbol for configuration_declaration
 %type  <leaf>	optional_access_declarations
 // helper symbol for configuration_declaration
@@ -5563,7 +5563,7 @@
 
 configuration_declaration:
   CONFIGURATION configuration_name
-   optional_global_var_declarations
+   global_var_declarations_list
    single_resource_declaration
    {variable_name_symtable.pop();
     direct_variable_symtable.pop();}
@@ -5576,7 +5576,7 @@
 	 direct_variable_symtable.pop();
 	}
 | CONFIGURATION configuration_name
-   optional_global_var_declarations
+   global_var_declarations_list
    resource_declaration_list
    optional_access_declarations
    optional_instance_specific_initializations
@@ -5588,7 +5588,7 @@
 }
 /* ERROR_CHECK_BEGIN */
 | CONFIGURATION 
-   optional_global_var_declarations
+   global_var_declarations_list
    single_resource_declaration
    {variable_name_symtable.pop();
     direct_variable_symtable.pop();}
@@ -5597,14 +5597,14 @@
   END_CONFIGURATION
   {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no configuration name defined in configuration declaration."); yynerrs++;}
 | CONFIGURATION
-   optional_global_var_declarations
+   global_var_declarations_list
    resource_declaration_list
    optional_access_declarations
    optional_instance_specific_initializations
   END_CONFIGURATION
   {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no configuration name defined in configuration declaration."); yynerrs++;}
 | CONFIGURATION error
-   optional_global_var_declarations
+   global_var_declarations_list
    single_resource_declaration
    {variable_name_symtable.pop();
     direct_variable_symtable.pop();}
@@ -5613,27 +5613,27 @@
   END_CONFIGURATION
   {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid configuration name defined in configuration declaration."); yyerrok;}
 | CONFIGURATION error
-   optional_global_var_declarations
+   global_var_declarations_list
    resource_declaration_list
    optional_access_declarations
    optional_instance_specific_initializations
   END_CONFIGURATION
   {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid configuration name defined in configuration declaration."); yyerrok;}
 | CONFIGURATION configuration_name
-   optional_global_var_declarations
+   global_var_declarations_list
    optional_access_declarations
    optional_instance_specific_initializations
   END_CONFIGURATION
   {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no resource(s) defined in configuration declaration."); yynerrs++;}
 | CONFIGURATION configuration_name
-   optional_global_var_declarations
+   global_var_declarations_list
    error
    optional_access_declarations
    optional_instance_specific_initializations
   END_CONFIGURATION
   {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid resource(s) defined in configuration declaration."); yyerrok;}
 /*| CONFIGURATION configuration_name
-   optional_global_var_declarations
+   global_var_declarations_list
    single_resource_declaration
    {variable_name_symtable.pop();
     direct_variable_symtable.pop();}
@@ -5642,7 +5642,7 @@
   END_OF_INPUT
   {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed configuration declaration."); yyerrok;}*/
 | CONFIGURATION configuration_name
-   optional_global_var_declarations
+   global_var_declarations_list
    resource_declaration_list
    optional_access_declarations
    optional_instance_specific_initializations
@@ -5657,12 +5657,30 @@
 //  - configuration_declaration
 //  - resource_declaration
 //
-optional_global_var_declarations:
+/* NOTE: The IEC 61131-3 v2 standard defines this list as being: [global_var_declarations]
+ *        e.g.:
+ *          'CONFIGURATION' configuration_name  [global_var_declarations] ...
+ *
+ *       However, this means that a single VAR_GLOBAL ... END_VAR construct is allowed
+ *       in each CONFIGURATION or RESOURCE declaration. If the user wishes to have global
+ *       variables with distinct properties (e.g. some with RETAIN, others with CONSTANT,
+ *       and yet other variables with none of these qualifiers), the syntax defined in the 
+ *       standard does not allow this.
+ *       Amazingly, IEC 61131-3 v3 also does not seem to allow it either!!
+ *       Since this is most likely a bug in the standard, we are changing the syntax slightly
+ *       to become:
+ *          'CONFIGURATION' configuration_name  {global_var_declarations} ...
+ *
+ *       Remember that:
+ *          {S}, closure, meaning zero or more concatenations of S.
+ *          [S], option, meaning zero or one occurrence of S.
+ */
+global_var_declarations_list:
   // empty
-	{$$ = NULL;}
-| global_var_declarations
-;
-
+	{$$ = new global_var_declarations_list_c(locloc(@$));}
+| global_var_declarations_list global_var_declarations
+	{$$ = $1; $$->add_element($2);}
+;
 
 // helper symbol for configuration_declaration //
 optional_access_declarations:
@@ -5693,7 +5711,7 @@
 
 resource_declaration:
   RESOURCE {variable_name_symtable.push();direct_variable_symtable.push();} resource_name {variable_name_symtable.insert($3, prev_declared_resource_name_token);} ON resource_type_name
-   optional_global_var_declarations
+   global_var_declarations_list
    single_resource_declaration
   END_RESOURCE
 	{$$ = new resource_declaration_c($3, $6, $7, $8, locloc(@$));
@@ -5703,12 +5721,12 @@
 	}
 /* ERROR_CHECK_BEGIN */
 | RESOURCE {variable_name_symtable.push();direct_variable_symtable.push();} ON resource_type_name
-   optional_global_var_declarations
+   global_var_declarations_list
    single_resource_declaration
   END_RESOURCE
   {$$ = NULL; print_err_msg(locl(@1), locf(@3), "no resource name defined in resource declaration."); yynerrs++;}
 /*|	RESOURCE {variable_name_symtable.push();direct_variable_symtable.push();} resource_name ON resource_type_name
-   optional_global_var_declarations
+   global_var_declarations_list
    single_resource_declaration
   END_OF_INPUT
 	{$$ = NULL; print_err_msg(locf(@1), locl(@5), "unclosed resource declaration."); yyerrok;}*/
--- a/stage4/generate_c/generate_c.cc	Mon Jan 06 12:25:21 2014 +0000
+++ b/stage4/generate_c/generate_c.cc	Tue Feb 11 10:55:27 2014 +0000
@@ -713,15 +713,13 @@
     } inlinearray_mode_t;
 
   private:
-    stage4out_c *s4o_ptr;
     std::map<std::string, int> inline_array_defined;
     std::string current_array_name;
     inlinearray_mode_t current_mode;
 
   public:
     generate_c_datatypes_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr)
-      : generate_c_typedecl_c(s4o_ptr, s4o_incl_ptr) {
-      generate_c_datatypes_c::s4o_ptr = s4o_ptr;
+      : generate_c_typedecl_c(s4o_incl_ptr) {
       current_mode = none_im;
     };
     virtual ~generate_c_datatypes_c(void) {
@@ -907,11 +905,20 @@
     void *visit(array_spec_init_c *symbol) {
       switch (current_mode) {
         case arraydeclaration_im:
+          {
+            array_specification_c *specification = dynamic_cast<array_specification_c*>(symbol->array_specification);
+            if (specification != NULL)
+              symbol->array_specification->accept(*this);
+          }
+          break;
         case arrayname_im:
           {
             array_specification_c *specification = dynamic_cast<array_specification_c*>(symbol->array_specification);
             if (specification != NULL)
               symbol->array_specification->accept(*this);
+            identifier_c *name = dynamic_cast<identifier_c*>(symbol->array_specification);
+            if (name != NULL)
+              s4o_incl.print(name->value);
           }
           break;
         default:
@@ -1138,14 +1145,13 @@
 /***********************************************************************/
 
 
-class generate_c_pous_c: public generate_c_typedecl_c {
+class generate_c_pous_c: public generate_c_base_c {
   private:
-    stage4out_c *s4o_ptr;
+    stage4out_c &s4o_incl;
     
   public:
     generate_c_pous_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr)
-      : generate_c_typedecl_c(s4o_ptr, s4o_incl_ptr) {
-      generate_c_pous_c::s4o_ptr = s4o_ptr;
+      : generate_c_base_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) {
     };
     virtual ~generate_c_pous_c(void) {}
 
@@ -1179,8 +1185,8 @@
 /********************/
 /* 2.1.6 - Pragmas  */
 /********************/
-void *visit(enable_code_generation_pragma_c * symbol)   {s4o_ptr->enable_output();  return NULL;}
-void *visit(disable_code_generation_pragma_c * symbol)  {s4o_ptr->disable_output(); return NULL;} 
+void *visit(enable_code_generation_pragma_c * symbol)   {s4o.enable_output();  return NULL;}
+void *visit(disable_code_generation_pragma_c * symbol)  {s4o.disable_output(); return NULL;} 
 
 /*************************/
 /* B.1 - Common elements */
@@ -1742,16 +1748,13 @@
 /***********************************************************************/
 /***********************************************************************/
 
-class generate_c_config_c: public generate_c_typedecl_c {
+class generate_c_config_c: public generate_c_base_c {
     private:
-    stage4out_c *s4o_ptr;
-    stage4out_c *s4o_incl_ptr;
+    stage4out_c &s4o_incl;
     
     public:
     generate_c_config_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr)
-      : generate_c_typedecl_c(s4o_ptr, s4o_incl_ptr) {
-      generate_c_config_c::s4o_ptr = s4o_ptr;
-      generate_c_config_c::s4o_incl_ptr = s4o_incl_ptr;
+      : generate_c_base_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) {
     };
 
     virtual ~generate_c_config_c(void) {}
@@ -1771,14 +1774,14 @@
 /* 2.1.6 - Pragmas  */
 /********************/
 void *visit(enable_code_generation_pragma_c * symbol)   {
-    s4o_ptr->enable_output();
-    s4o_incl_ptr->enable_output();
+    s4o.enable_output();
+    s4o_incl.enable_output();
     return NULL;
 }
 
 void *visit(disable_code_generation_pragma_c * symbol)  {
-    s4o_ptr->disable_output();
-    s4o_incl_ptr->disable_output();    
+    s4o.disable_output();
+    s4o_incl.disable_output();    
     return NULL;
 }
     
--- a/stage4/generate_c/generate_c_base.cc	Mon Jan 06 12:25:21 2014 +0000
+++ b/stage4/generate_c/generate_c_base.cc	Tue Feb 11 10:55:27 2014 +0000
@@ -583,6 +583,60 @@
 /********************************/
   /* leave for derived classes... */
 
+  
+/* enumerated_type_name '#' identifier */
+void *visit(enumerated_value_c *symbol) {
+  if (NULL == symbol->datatype) {
+    debug_c::print(symbol);
+    ERROR;
+  }
+  
+  symbol_c *type_name = get_datatype_info_c::get_id(symbol->datatype);
+  if (NULL == type_name) {
+    ERROR_MSG("C code generator does not currently support anonymous enumerated data types.");
+  }
+  
+  type_name->accept(*this);
+  s4o.print("__");
+  symbol->value->accept(*this);
+  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;
+}
+  
+  
+/* 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 */
 /*********************/
--- a/stage4/generate_c/generate_c_il.cc	Mon Jan 06 12:25:21 2014 +0000
+++ b/stage4/generate_c/generate_c_il.cc	Tue Feb 11 10:55:27 2014 +0000
@@ -126,7 +126,7 @@
 
 
 
-class generate_c_il_c: public generate_c_typedecl_c, il_default_variable_visitor_c {
+class generate_c_il_c: public generate_c_base_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_typedecl_c(s4o_ptr),
+    : generate_c_base_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	Mon Jan 06 12:25:21 2014 +0000
+++ b/stage4/generate_c/generate_c_inlinefcall.cc	Tue Feb 11 10:55:27 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_typedecl_c {
+class generate_c_inlinefcall_c: public generate_c_base_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_typedecl_c(s4o_ptr),
+    : generate_c_base_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	Mon Jan 06 12:25:21 2014 +0000
+++ b/stage4/generate_c/generate_c_sfc.cc	Tue Feb 11 10:55:27 2014 +0000
@@ -657,7 +657,7 @@
 /***********************************************************************/
 /***********************************************************************/
 
-class generate_c_sfc_c: public generate_c_typedecl_c {
+class generate_c_sfc_c: public generate_c_base_c {
   
   private:
     std::list<VARIABLE> variable_list;
@@ -667,7 +667,7 @@
     
   public:
     generate_c_sfc_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
-    : generate_c_typedecl_c(s4o_ptr) {
+    : generate_c_base_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	Mon Jan 06 12:25:21 2014 +0000
+++ b/stage4/generate_c/generate_c_sfcdecl.cc	Tue Feb 11 10:55:27 2014 +0000
@@ -32,7 +32,7 @@
 /***********************************************************************/
 /***********************************************************************/
 
-class generate_c_sfcdecl_c: protected generate_c_typedecl_c {
+class generate_c_sfcdecl_c: protected generate_c_base_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_typedecl_c(s4o_ptr) {
+    : generate_c_base_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	Mon Jan 06 12:25:21 2014 +0000
+++ b/stage4/generate_c/generate_c_st.cc	Tue Feb 11 10:55:27 2014 +0000
@@ -44,7 +44,7 @@
 /***********************************************************************/
 
 
-class generate_c_st_c: public generate_c_typedecl_c {
+class generate_c_st_c: public generate_c_base_c {
 
   public:
     typedef enum {
@@ -95,7 +95,7 @@
 
   public:
     generate_c_st_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
-    : generate_c_typedecl_c(s4o_ptr) {
+    : generate_c_base_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);
@@ -864,20 +864,20 @@
 
 
 /* fb_name '(' [param_assignment_list] ')' */
-/* param_assignment_list -> may be NULL ! */
-//SYM_REF2(fb_invocation_c, fb_name, param_assignment_list)
+/*    formal_param_list -> may be NULL ! */
+/* nonformal_param_list -> may be NULL ! */
+/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */
+// SYM_REF3(fb_invocation_c, fb_name, formal_param_list, nonformal_param_list, symbol_c *called_fb_declaration;)
 void *visit(fb_invocation_c *symbol) {
   TRACE("fb_invocation_c");
-  /* first figure out what is the name of the function block type of the function block being called... */
-  symbol_c *function_block_type_name = this->search_fb_instance_decl->get_type_name(symbol->fb_name);
-    /* should never occur. The function block instance MUST have been declared... */
-  if (function_block_type_name == NULL) ERROR;
-
-  /* Now find the declaration of the function block type being called... */
-  function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(function_block_type_name);
-    /* should never occur. The function block type being called MUST be in the symtable... */
-  if (fb_decl == function_block_type_symtable.end_value()) ERROR;
-
+  
+  /* find the declaration of the function block type being called... */
+  symbol_c *fb_decl = symbol->called_fb_declaration;
+  if (fb_decl == NULL) ERROR;
+  /* figure out the name of the function block type of the function block being called... */
+  symbol_c *function_block_type_name = get_datatype_info_c::get_id(fb_decl);
+  if (NULL == function_block_type_name) ERROR;
+  
   /* loop through each function block parameter, find the value we should pass
    * to it, and then output the c equivalent...
    */
--- a/stage4/generate_c/generate_c_typedecl.cc	Mon Jan 06 12:25:21 2014 +0000
+++ b/stage4/generate_c/generate_c_typedecl.cc	Tue Feb 11 10:55:27 2014 +0000
@@ -31,16 +31,9 @@
   private:
     symbol_c* current_type_name;
     bool array_is_derived;
-
     generate_c_base_c *basedecl;
 
   public:
-    generate_c_typedecl_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr): generate_c_base_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) {
-      current_typedefinition = none_td;
-      current_basetypedeclaration = none_bd;
-      current_type_name = NULL;
-      basedecl = new generate_c_base_c(&s4o_incl);
-    }
     generate_c_typedecl_c(stage4out_c *s4o_ptr): generate_c_base_c(s4o_ptr), s4o_incl(*s4o_ptr) {
       current_typedefinition = none_td;
       current_basetypedeclaration = none_bd;
@@ -190,6 +183,7 @@
 
 /*  integer_type_name '(' subrange')' */
 void *visit(subrange_specification_c *symbol) {
+  TRACE("subrange_specification_c");
   if (current_typedefinition == subrange_td) {
     switch (current_basetypedeclaration) {
       case subrangebasetype_bd:
@@ -197,45 +191,52 @@
         break;
       case subrangetest_bd:
         if (symbol->subrange != NULL) {
-          current_type_name->accept(*this);
-          s4o.print(" __CHECK_");
-          current_type_name->accept(*this);
-          s4o.print("(");
-          current_type_name->accept(*this);
-          s4o.print(" value) {\n");
-          s4o.indent_right();
-
+          s4o_incl.print("static inline ");
+          current_type_name->accept(*basedecl);
+          s4o_incl.print(" __CHECK_");
+          current_type_name->accept(*basedecl);
+          s4o_incl.print("(");
+          current_type_name->accept(*basedecl);
+          s4o_incl.print(" value) {\n");
+          s4o_incl.indent_right();
+
+          /* NOTE: IEC 61131-3 v2 syntax mandates that the integer type name be one of SINT, ..., LINT, USINT, ... ULIT */
+          /*       For this reason, the following condition will always be false, and therefore this is a block
+           *       of dead code. However, let's not delete it for now. It might come in useful for IEC 61131-3 v3.
+           *       For the moment, we just comment it out!
+           */
+          /*
           if (get_datatype_info_c::is_subrange(symbol->integer_type_name)) {
-            s4o.print(s4o.indent_spaces + "value = __CHECK_");
+            s4o_incl.print(s4o_incl.indent_spaces + "value = __CHECK_");
             symbol->integer_type_name->accept(*this);
-            s4o.print("(value);\n");
+            s4o_incl.print("(value);\n");
           }
+          */
 
           symbol->subrange->accept(*this);
 
-          s4o.indent_left();
-          s4o.print("}\n");
+          s4o_incl.indent_left();
+          s4o_incl.print("}\n");
         }
         else {
-          s4o.print("#define __CHECK_");
-          current_type_name->accept(*this);
-          s4o.print(" __CHECK_");
-          symbol->integer_type_name->accept(*this);
-          s4o.print("\n");
+          s4o_incl.print("#define __CHECK_");
+          current_type_name->accept(*basedecl);
+          s4o_incl.print(" __CHECK_");
+          symbol->integer_type_name->accept(*basedecl);
+          s4o_incl.print("\n");
         }
         break;
       default:
         break;
     }
   }
-  else {
-    symbol->integer_type_name->accept(*basedecl);
-  }
-  return NULL;
-}
+  return NULL;
+}
+
 
 /*  signed_integer DOTDOT signed_integer */
 void *visit(subrange_c *symbol) {
+  TRACE("subrange_c");
   int dimension;
   switch (current_typedefinition) {
     case array_td:
@@ -248,26 +249,26 @@
         symbol->lower_limit->accept(*this);
       break;
     case subrange_td:
-      s4o.print(s4o.indent_spaces + "if (value < ");
-      symbol->lower_limit->accept(*this);
-      s4o.print(")\n");
-      s4o.indent_right();
-      s4o.print(s4o.indent_spaces + "return ");
-      symbol->lower_limit->accept(*this);
-      s4o.print(";\n");
-      s4o.indent_left();
-      s4o.print(s4o.indent_spaces + "else if (value > ");
-      symbol->upper_limit->accept(*this);
-      s4o.print(")\n");
-      s4o.indent_right();
-      s4o.print(s4o.indent_spaces + "return ");
-      symbol->upper_limit->accept(*this);
-      s4o.print(";\n");
-      s4o.indent_left();
-      s4o.print(s4o.indent_spaces + "else\n");
-      s4o.indent_right();
-      s4o.print(s4o.indent_spaces + "return value;\n");
-      s4o.indent_left();
+      s4o_incl.print(s4o_incl.indent_spaces + "if (value < ");
+      symbol->lower_limit->accept(*basedecl);
+      s4o_incl.print(")\n");
+      s4o_incl.indent_right();
+      s4o_incl.print(s4o_incl.indent_spaces + "return ");
+      symbol->lower_limit->accept(*basedecl);
+      s4o_incl.print(";\n");
+      s4o_incl.indent_left();
+      s4o_incl.print(s4o_incl.indent_spaces + "else if (value > ");
+      symbol->upper_limit->accept(*basedecl);
+      s4o_incl.print(")\n");
+      s4o_incl.indent_right();
+      s4o_incl.print(s4o_incl.indent_spaces + "return ");
+      symbol->upper_limit->accept(*basedecl);
+      s4o_incl.print(";\n");
+      s4o_incl.indent_left();
+      s4o_incl.print(s4o_incl.indent_spaces + "else\n");
+      s4o_incl.indent_right();
+      s4o_incl.print(s4o_incl.indent_spaces + "return value;\n");
+      s4o_incl.indent_left();
     default:
       break;
   }
@@ -308,29 +309,15 @@
 /* helper symbol for enumerated_specification->enumerated_spec_init */
 /* enumerated_value_list ',' enumerated_value */
 void *visit(enumerated_value_list_c *symbol) {
+  TRACE("enumerated_value_list_c");
   print_list_incl(symbol, s4o_incl.indent_spaces, ",\n"+s4o_incl.indent_spaces, "\n");
   return NULL;
 }
 
 /* enumerated_type_name '#' identifier */
-void *visit(enumerated_value_c *symbol) {
-  if (current_typedefinition == enumerated_td)
-    current_type_name->accept(*basedecl);
-  else {
-    if (NULL == symbol->datatype) {
-      debug_c::print(symbol);
-      ERROR;
-    }
-    symbol_c *type_name = get_datatype_info_c::get_id(symbol->datatype);
-    if (NULL == type_name) {
-//       ERROR_MSG("generate_c does not support anonymous enumerated data types.");
-    } else
-    type_name->accept(*basedecl);
-  }
-  s4o_incl.print("__");
-  symbol->value->accept(*basedecl);
-  return NULL;
-}
+/* Handled by generate_c_base_c class!!
+void *visit(enumerated_value_c *symbol) {}
+*/
 
 /*  identifier ':' array_spec_init */
 void *visit(array_type_declaration_c *symbol) {
@@ -393,6 +380,7 @@
 
 /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
 void *visit(array_specification_c *symbol) {
+  TRACE("array_specification_c");
   switch (current_basetypedeclaration) {
     case arraybasetype_bd:
       symbol->non_generic_type_name->accept(*this);
@@ -409,18 +397,12 @@
   return NULL;
 }
 
-/* helper symbol for array_specification */
-/* array_subrange_list ',' subrange */
-void *visit(array_subrange_list_c *symbol) {
-  print_list(symbol);
-  return NULL;
-}
 
 /*  TYPE type_declaration_list END_TYPE */
 void *visit(data_type_declaration_c *symbol) {
   TRACE("data_type_declaration_c");
   symbol->type_declaration_list->accept(*this);
-  s4o.print("\n\n");
+  s4o_incl.print("\n\n");
   return NULL;
 }
 
@@ -441,11 +423,11 @@
   s4o_incl.print(")\n");
 
   if (get_datatype_info_c::is_subrange(symbol->simple_type_name)) {
-    s4o.print("#define __CHECK_");
-    current_type_name->accept(*this);
-    s4o.print(" __CHECK_");
+    s4o_incl.print("#define __CHECK_");
+    current_type_name->accept(*basedecl);
+    s4o_incl.print(" __CHECK_");
     symbol->simple_spec_init->accept(*this);
-    s4o.print("\n");
+    s4o_incl.print("\n");
   }
 
   return NULL;
@@ -565,7 +547,7 @@
   s4o_incl.print(" ");
   symbol->structure_element_name->accept(*basedecl);
   s4o_incl.print(";\n");
-  s4o_incl.print(s4o.indent_spaces);
+  s4o_incl.print(s4o_incl.indent_spaces);
 
   return NULL;
 }
--- a/stage4/generate_iec/generate_iec.cc	Mon Jan 06 12:25:21 2014 +0000
+++ b/stage4/generate_iec/generate_iec.cc	Tue Feb 11 10:55:27 2014 +0000
@@ -1422,6 +1422,10 @@
 }
 
 
+/* intermediate helper symbol for configuration_declaration  */
+/*  { global_var_declarations_list }   */
+void *visit(global_var_declarations_list_c *symbol) {return print_list(symbol);}
+
 /* helper symbol for configuration_declaration */
 /*| resource_declaration_list resource_declaration */
 void *visit(resource_declaration_list_c *symbol) {return print_list(symbol);}