merge
authorEdouard Tisserant
Wed, 28 May 2014 11:32:09 +0200
changeset 894 39086e324665
parent 882 18a39a545ed9 (current diff)
parent 892 54d5d185d6e2 (diff)
child 902 38dca2e264b6
merge
lib/accessor.h
stage1_2/iec_bison.yy
stage4/generate_c/generate_c.cc
--- a/absyntax/absyntax.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/absyntax/absyntax.cc	Wed May 28 11:32:09 2014 +0200
@@ -57,6 +57,7 @@
   this->last_column  = last_column;
   this->last_order   = last_order;
   this->datatype     = NULL;
+  this->scope        = NULL;
   this->const_value._real64.status   = cs_undefined;
   this->const_value._int64.status    = cs_undefined;
   this->const_value._uint64.status   = cs_undefined;
--- a/absyntax/absyntax.hh	Thu Mar 20 17:27:29 2014 +0100
+++ b/absyntax/absyntax.hh	Wed May 28 11:32:09 2014 +0200
@@ -131,6 +131,10 @@
      * Otherwise, it points to an object of the apropriate data type (e.g. int_type_name_c, bool_type_name_c, ...)
      */
     symbol_c *datatype;
+    /* The POU in which the symbolic variable (or structured variable, or array variable, or located variable, - any more?)
+     * was declared. This will point to a Configuration, Resource, Program, FB, or Function.
+     */
+    symbol_c *scope;    
 
     /*** constant folding ***/
     /* During stage 3 (semantic analysis/checking) we will be doing constant folding.
--- a/absyntax_utils/get_var_name.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/absyntax_utils/get_var_name.cc	Wed May 28 11:32:09 2014 +0200
@@ -35,26 +35,6 @@
  *  appear in the variable declaration.
  */
 
-/*  For ex.:
- *       VAR
- *          A : int;
- *          B : ARRAY [1..9] of int;
- *          C : some_struct_t;
- *       END_VAR
- *
- *          A    := 56;
- *          B[8] := 99;
- *          C.e  := 77;
- *
- *       Calling this visitor class with symbolic_variable_c instance referencing 'A' in
- *       the line 'A := 56', will return the string "A".
- *
- *       Calling this visitor class with array_variable_c instance referencing 'B[8]' in
- *       the line 'B[8] := 99', will return the string "B".
- *
- *       Calling this visitor class with array_variable_c instance referencing 'C.e' in
- *       the line 'C.e := 77', will return the string "C".
- */
 
 
 #include "absyntax_utils.hh"
@@ -68,6 +48,26 @@
 
 
 
+/*  For ex.:
+ *       VAR
+ *          A : int;
+ *          B : ARRAY [1..9] of int;
+ *          C : some_struct_t;
+ *       END_VAR
+ *
+ *          A    := 56;
+ *          B[8] := 99;
+ *          C.e  := 77;
+ *
+ *       Calling this method with symbolic_variable_c instance referencing 'A' in
+ *       the line 'A := 56', will return the string "A".
+ *
+ *       Calling this method with array_variable_c instance referencing 'B[8]' in
+ *       the line 'B[8] := 99', will return the string "B".
+ *
+ *       Calling this method with array_variable_c instance referencing 'C.e' in
+ *       the line 'C.e := 77', will return the string "C".
+ */
 
 token_c *get_var_name_c::get_name(symbol_c *symbol) {
   if (NULL == singleton_instance_) singleton_instance_ = new get_var_name_c(); 
@@ -77,6 +77,24 @@
 }
 
 
+/*  Return the last field of a structured variable...
+ * 
+ *          A    := 56;   --> returns A
+ *          B[8] := 99;   --> returns B
+ *          C.e  := 77;   --> returns e   !!!
+ */
+symbol_c *get_var_name_c::get_last_field(symbol_c *symbol) {
+  if (NULL == singleton_instance_) singleton_instance_ = new get_var_name_c(); 
+  if (NULL == singleton_instance_) ERROR; 
+  
+  singleton_instance_->last_field = NULL;
+  symbol_c *res = (symbol_c*)(symbol->accept(*singleton_instance_));
+  return (NULL != singleton_instance_->last_field)? singleton_instance_->last_field : res;
+}
+
+
+
+
 /*************************/
 /* B.1 - Common elements */
 /*************************/
@@ -114,7 +132,11 @@
  *           this into account!
  */
 // SYM_REF2(structured_variable_c, record_variable, field_selector)
-void *get_var_name_c::visit(structured_variable_c *symbol) {return symbol->record_variable->accept(*this);}
+void *get_var_name_c::visit(structured_variable_c *symbol) {
+  void *res = symbol->record_variable->accept(*this);
+  last_field = symbol->field_selector;
+  return res;
+}
 
 
 
--- a/absyntax_utils/get_var_name.hh	Thu Mar 20 17:27:29 2014 +0100
+++ b/absyntax_utils/get_var_name.hh	Wed May 28 11:32:09 2014 +0200
@@ -63,10 +63,12 @@
   public:
     get_var_name_c(void)  {};
     ~get_var_name_c(void) {};  
-    static token_c *get_name(symbol_c *symbol);
-
+    static token_c  *get_name(symbol_c *symbol);
+    static symbol_c *get_last_field(symbol_c *symbol);
+    
   private:
     static get_var_name_c *singleton_instance_;
+    symbol_c *last_field;
     
   private:  
     /*************************/
--- a/lib/accessor.h	Thu Mar 20 17:27:29 2014 +0100
+++ b/lib/accessor.h	Wed May 28 11:32:09 2014 +0200
@@ -113,15 +113,15 @@
 
 
 // variable setting macros
-#define __SET_VAR(prefix, name, new_value, ...)\
-	if (!(prefix name.flags & __IEC_FORCE_FLAG)) prefix name.value __VA_ARGS__ = new_value
-#define __SET_EXTERNAL(prefix, name, new_value, ...)\
-	{extern IEC_BYTE __IS_GLOBAL_##name##_FORCED(void);\
-     if (!(prefix name.flags & __IEC_FORCE_FLAG || __IS_GLOBAL_##name##_FORCED()))\
-		 (*(prefix name.value)) __VA_ARGS__ = new_value;}
-#define __SET_EXTERNAL_FB(prefix, name, new_value, ...)\
-	__SET_VAR((*(prefix name)), __VA_ARGS__, new_value)
-#define __SET_LOCATED(prefix, name, new_value, ...)\
-	if (!(prefix name.flags & __IEC_FORCE_FLAG)) *(prefix name.value) __VA_ARGS__ = new_value
+#define __SET_VAR(prefix, name, suffix, new_value)\
+	if (!(prefix name.flags & __IEC_FORCE_FLAG)) prefix name.value suffix = new_value
+#define __SET_EXTERNAL(prefix, name, suffix, new_value)\
+	{extern IEC_BYTE __IS_GLOBAL_##name##_FORCED();\
+    if (!(prefix name.flags & __IEC_FORCE_FLAG || __IS_GLOBAL_##name##_FORCED()))\
+		(*(prefix name.value)) suffix = new_value;}
+#define __SET_EXTERNAL_FB(prefix, name, suffix, new_value)\
+	__SET_VAR((*(prefix name)), suffix, new_value)
+#define __SET_LOCATED(prefix, name, suffix, new_value)\
+	if (!(prefix name.flags & __IEC_FORCE_FLAG)) *(prefix name.value) suffix = new_value
 
 #endif //__ACCESSOR_H
--- a/lib/rtc.txt	Thu Mar 20 17:27:29 2014 +0100
+++ b/lib/rtc.txt	Wed May 28 11:32:09 2014 +0200
@@ -29,7 +29,7 @@
      CURRENT_TIME : DT;
    END_VAR
 
-   {__SET_VAR(data__->,CURRENT_TIME,__CURRENT_TIME)}
+   {__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME)}
 
    IF IN
    THEN
--- a/lib/timer.txt	Thu Mar 20 17:27:29 2014 +0100
+++ b/lib/timer.txt	Wed May 28 11:32:09 2014 +0200
@@ -90,7 +90,7 @@
     CURRENT_TIME, START_TIME : TIME;
   END_VAR
 
-  {__SET_VAR(data__->,CURRENT_TIME,__CURRENT_TIME)}
+  {__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME)}
 
   IF ((STATE = 0) AND NOT(PREV_IN) AND IN)   (* found rising edge on IN *)
   THEN
@@ -171,7 +171,7 @@
     CURRENT_TIME, START_TIME : TIME;
   END_VAR
 
-  {__SET_VAR(data__->,CURRENT_TIME,__CURRENT_TIME)}
+  {__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME)}
 
   IF ((STATE = 0) AND NOT(PREV_IN) AND IN)   (* found rising edge on IN *)
   THEN
@@ -255,7 +255,7 @@
     CURRENT_TIME, START_TIME : TIME;
   END_VAR
 
-  {__SET_VAR(data__->,CURRENT_TIME,__CURRENT_TIME)}
+  {__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME)}
 
   IF ((STATE = 0) AND PREV_IN AND NOT(IN))   (* found falling edge on IN *)
   THEN
--- a/main.hh	Thu Mar 20 17:27:29 2014 +0100
+++ b/main.hh	Wed May 28 11:32:09 2014 +0200
@@ -78,14 +78,16 @@
 
 #include <float.h>
 #if    (LDBL_MANT_DIG == 53) /* NOTE: 64 bit IEC559 real has 53 bits for mantissa! */
-  #define long_double long double
-  #define real64_t long_double /* so we can later use #if (real64_t == long_double) directives in the code! */
+  #define real64_tX long_double /* so we can later use #if (real64_t == long_double) directives in the code! */
+  #define real64_t  long double /* NOTE: no underscore '_' between 'long' and 'double' */
   #define REAL64_MAX  LDBL_MAX
 #elif  ( DBL_MANT_DIG == 53) /* NOTE: 64 bit IEC559 real has 53 bits for mantissa! */
-  #define real64_t double
+  #define real64_tX double
+  #define real64_t  double
   #define REAL64_MAX  DBL_MAX
 #elif  ( FLT_MANT_DIG == 53) /* NOTE: 64 bit IEC559 real has 53 bits for mantissa! */
-  #define real64_t float
+  #define real64_tX float
+  #define real64_t  float
   #define REAL64_MAX  FLT_MAX
 #else 
   #error Could not find a 64 bit floating point data type on this platform. Aborting...
@@ -93,16 +95,16 @@
 
 
 #if    (LDBL_MANT_DIG == 24) /* NOTE: 32 bit IEC559 real has 24 bits for mantissa! */
-  #ifndef long_double 
-    #define long_double long double
-  #endif  
-  #define real32_t long_double /* so we can later use #if (real32_t == long_double) directives in the code! */
+  #define real32_tX long_double /* so we can later use #if (real32_t == long_double) directives in the code! */
+  #define real32_t  long double /* NOTE: no underscore '_' between 'long' and 'double' */
   #define REAL32_MAX  LDBL_MAX
 #elif  ( DBL_MANT_DIG == 24) /* NOTE: 32 bit IEC559 real has 24 bits for mantissa! */
-  #define real32_t double
+  #define real32_tX double
+  #define real32_t  double
   #define REAL32_MAX  DBL_MAX
 #elif  ( FLT_MANT_DIG == 24) /* NOTE: 32 bit IEC559 real has 24 bits for mantissa! */
-  #define real32_t float
+  #define real32_tX float
+  #define real32_t  float
   #define REAL32_MAX  FLT_MAX
 #else 
   #error Could not find a 32 bit floating point data type on this platform. Aborting...
--- a/stage1_2/iec_bison.yy	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage1_2/iec_bison.yy	Wed May 28 11:32:09 2014 +0200
@@ -4116,7 +4116,7 @@
 	 variable_name_symtable.insert($1, prev_declared_fb_name_token);
 	}
 | global_var_name ':' ref_spec /* defined in IEC 61131-3 v3   (REF_TO ...)*/
-	{$$ = new external_declaration_c($1, new fb_spec_init_c($3, NULL, locloc(@3)), locloc(@$));
+	{$$ = new external_declaration_c($1, $3, locloc(@$));
 	 variable_name_symtable.insert($1, prev_declared_fb_name_token);
 	}
 /* ERROR_CHECK_BEGIN */
--- a/stage3/constant_folding.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage3/constant_folding.cc	Wed May 28 11:32:09 2014 +0200
@@ -379,14 +379,14 @@
   else ERROR;
     
   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
-  #if    (real64_t  == float)
+  #if    (real64_tX  == float)
     ret = strtof(str.c_str(),  &endptr);
-  #elif  (real64_t  == double)
+  #elif  (real64_tX  == double)
     ret = strtod(str.c_str(),  &endptr);
-  #elif  (real64_t  == long_double)
+  #elif  (real64_tX  == long_double)
     ret = strtold(str.c_str(), &endptr);
   #else 
-    #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting!
+    #error Could not determine which data type is being used for real64_t (defined in main.hh). Aborting!
   #endif
   if (overflow != NULL)
     *overflow = (errno == ERANGE);
--- a/stage3/declaration_check.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage3/declaration_check.cc	Wed May 28 11:32:09 2014 +0200
@@ -70,6 +70,162 @@
 }
 
 
+
+
+
+
+
+
+
+#include <set>
+class check_extern_c: public iterator_visitor_c {
+  public:
+  
+  private:
+    int current_display_error_level;
+    symbol_c *current_pou_decl;
+    symbol_c *current_resource_decl;
+    static std::set<symbol_c *> checked_decl; // A set with all the declarations that have already been checked, so we don't recheck it again!
+  
+  
+  public:
+    static int error_count;
+    
+    check_extern_c(symbol_c *current_pou, symbol_c *current_resource) {
+      current_display_error_level = 0;
+      current_pou_decl      = current_pou;
+      current_resource_decl = current_resource;
+    }
+        
+    ~check_extern_c(void) {}
+    
+    
+    
+    void check_global_decl(symbol_c *p_decl) {
+      if (NULL == current_pou_decl) ERROR;
+      
+      if (checked_decl.find(p_decl) != checked_decl.end()) return; // has already been checked!
+      checked_decl.insert(p_decl);
+
+      search_var_instance_decl_c search_var_instance_pou_glo_decl(current_pou_decl);
+      search_var_instance_decl_c search_var_instance_res_glo_decl(current_resource_decl);
+      search_var_instance_decl_c search_var_instance_ext_decl(p_decl);
+      function_param_iterator_c  fpi(p_decl);
+      
+      symbol_c *var_name;
+      while((var_name = fpi.next()) != NULL) {            
+        if (fpi.param_direction() == function_param_iterator_c::direction_extref) {
+          /* found an external reference parameter. */
+          symbol_c *ext_decl = search_var_instance_ext_decl.get_decl(var_name);
+          
+          // NOTE: Must check the POU first, and RESOURCE second!
+          symbol_c                                       *glo_decl =  search_var_instance_res_glo_decl.get_decl(var_name);           
+              search_var_instance_decl_c *search_var_instance_glo_decl = &search_var_instance_res_glo_decl;
+          if (NULL == glo_decl) {
+            glo_decl                     =  search_var_instance_pou_glo_decl.get_decl(var_name);
+            search_var_instance_glo_decl = &search_var_instance_pou_glo_decl;
+          }
+          
+          if (NULL == glo_decl) {
+            STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error. The external variable does not match with any global variable.");
+            continue;
+          }
+    
+          /* Check whether variable's constness (CONSTANT) is compatible.
+           *        VAR_GLOBAL is contant     => VAR_EXTERNAL must also be CONSTANT
+           *        VAR_GLOBAL is not contant => VAR_EXTERNAL may be CONSTANT, or not!
+           */
+          search_var_instance_decl_c::opt_t ext_opt = search_var_instance_ext_decl. get_option(var_name);
+          search_var_instance_decl_c::opt_t glo_opt = search_var_instance_glo_decl->get_option(var_name);
+          if ((glo_opt == search_var_instance_decl_c::constant_opt) && (ext_opt != search_var_instance_decl_c::constant_opt))
+            STAGE3_ERROR(0, glo_decl, glo_decl, "Declaration error. The external variable must be declared as constant, as it maps to a constant global variable.");
+    
+          /* TODO: Check redefinition data type.
+           *       We need a new class (like search_base_type class) to get type id by variable declaration.
+           *  symbol_c *glo_type = ????;
+           *  symbol_c *ext_type = fpi.param_type();
+           */
+          /* For the moment, we will just use search_base_type_c instead... */
+          symbol_c *glo_type = search_base_type_c::get_basetype_decl(glo_decl);
+          symbol_c *ext_type = search_base_type_c::get_basetype_decl(ext_decl);
+          if (! get_datatype_info_c::is_type_equal(glo_type, ext_type))
+            STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error.  Data type mismatch between external and global variable declarations.");
+        }
+      }
+    }
+    
+    
+    
+    /********************************/
+    /* B 1.3.3 - Derived data types */
+    /********************************/
+    /*  function_block_type_name ASSIGN structure_initialization */
+    /* structure_initialization -> may be NULL ! */
+    //SYM_REF2(fb_spec_init_c, function_block_type_name, structure_initialization)
+    /* NOTE: This class is only used when declaring FB variables, as in:
+     * name_list ':' function_block_type_name ASSIGN structure_initialization
+     *               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+     *                      fb_spec_init_c                                   
+     * Here, fb_spec_init_c is used whether it is an external, local, or global variable!
+     * Note too that we must also check the datatypes of external and global variables!! 
+     */
+    void *visit(fb_spec_init_c *symbol) {
+      symbol_c *fb_decl = function_block_type_symtable.find_value(symbol->function_block_type_name);
+      /* stage1_2 guarantees that we are sure to find a declaration in FB or Program symtable. */
+      if (fb_decl == function_block_type_symtable.end_value())
+        ERROR;
+      fb_decl->accept(*this);
+      return NULL;
+    }
+    
+    /*****************************/
+    /* B 1.5.2 - Function Blocks */
+    /*****************************/
+    /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
+    // SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body)
+    void *visit(function_block_declaration_c *symbol) {
+      check_global_decl(symbol);
+      /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside FBs!
+       * current_pou_decl = symbol;  
+       * current_resource_decl = NULL;  
+       */
+      /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
+      if (NULL != symbol->var_declarations)
+        symbol->var_declarations->accept(*this);  // This will eventually call the visit(fb_spec_init_c *) method, if any FB are declared here!
+      return NULL;
+    }
+    
+    /******************************************/
+    /* B 1.5.3 - Declaration & Initialisation */
+    /******************************************/
+    /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
+    // SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body)
+    void *visit(program_declaration_c *symbol) {
+      check_global_decl(symbol);
+      /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside PROGRAMs!
+       * current_pou_decl = symbol;  
+       * current_resource_decl = NULL;  
+       */
+      /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
+      if (NULL != symbol->var_declarations)
+        symbol->var_declarations->accept(*this);  // This will eventually call the visit(fb_spec_init_c *) method, if any FB are declared here!
+      return NULL;
+    }
+    
+};
+
+int check_extern_c::error_count = 0;
+std::set<symbol_c *> check_extern_c::checked_decl;
+
+
+
+
+
+
+
+
+
+
 declaration_check_c::declaration_check_c(symbol_c *ignore) {
   current_display_error_level = 0;
   current_pou_decl = NULL;
@@ -82,92 +238,26 @@
 }
 
 int declaration_check_c::get_error_count() {
-  return error_count;
-}
-
-void declaration_check_c::check_global_decl(symbol_c *p_decl) {
-  if (NULL == current_pou_decl) ERROR;
-  
-  search_var_instance_decl_c search_var_instance_pou_glo_decl(current_pou_decl);
-  search_var_instance_decl_c search_var_instance_res_glo_decl(current_resource_decl);
-  search_var_instance_decl_c search_var_instance_ext_decl(p_decl);
-  function_param_iterator_c  fpi(p_decl);
-  
-  symbol_c *var_name;
-  while((var_name = fpi.next()) != NULL) {
-    if (fpi.param_direction() == function_param_iterator_c::direction_extref) {
-      /* found an external reference parameter. */
-      symbol_c *ext_decl = search_var_instance_ext_decl.get_decl(var_name);
-      
-      // NOTE: Must check the POU first, and RESOURCE second!
-      symbol_c                                       *glo_decl =  search_var_instance_res_glo_decl.get_decl(var_name);           
-      search_var_instance_decl_c *search_var_instance_glo_decl = &search_var_instance_res_glo_decl;
-      if (NULL == glo_decl) {
-        glo_decl                     =  search_var_instance_pou_glo_decl.get_decl(var_name);
-        search_var_instance_glo_decl = &search_var_instance_pou_glo_decl;
-      }
-      
-      if (NULL == glo_decl) {
-        STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error. The external variable does not match with any global variable.");
-        continue;
-      }
-      
-      /* Check whether variable's constness (CONSTANT) is compatible.
-       *        VAR_GLOBAL is contant     => VAR_EXTERNAL must also be CONSTANT
-       *        VAR_GLOBAL is not contant => VAR_EXTERNAL may be CONSTANT, or not!
-       */
-      search_var_instance_decl_c::opt_t ext_opt = search_var_instance_ext_decl. get_option(var_name);
-      search_var_instance_decl_c::opt_t glo_opt = search_var_instance_glo_decl->get_option(var_name);
-      if ((glo_opt == search_var_instance_decl_c::constant_opt) && (ext_opt != search_var_instance_decl_c::constant_opt))
-        STAGE3_ERROR(0, glo_decl, glo_decl, "Declaration error. The external variable must be declared as constant, as it maps to a constant global variable.");
-
-      /* TODO: Check redefinition data type.
-       *       We need a new class (like search_base_type class) to get type id by variable declaration.
-       *  symbol_c *glo_type = ????;
-       *  symbol_c *ext_type = fpi.param_type();
-       */
-      /* For the moment, we will just use search_base_type_c instead... */
-      symbol_c *glo_type = search_base_type_c::get_basetype_decl(glo_decl);
-      symbol_c *ext_type = search_base_type_c::get_basetype_decl(ext_decl);
-      if (! get_datatype_info_c::is_type_equal(glo_type, ext_type))
-        STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error.  Data type mismatch between external and global variable declarations.");
-    }
-  }
-}
-
-
+  return check_extern_c::error_count;
+}
 
 /*****************************/
 /* B 1.5.2 - Function Blocks */
 /*****************************/
 /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
 // SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body)
-void *declaration_check_c::visit(function_block_declaration_c *symbol) {
-  /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside FBs!
-   * current_pou_decl = symbol;  
-   * current_resource_decl = NULL;  
-   */
-  /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
-  if (NULL != symbol->var_declarations)
-    symbol->var_declarations->accept(*this);
-  return NULL;
-}
+void *declaration_check_c::visit(function_block_declaration_c *symbol)
+  {return NULL;} // We only check the declarations that are used to instantiate variables. This is done in the configuration!
 
 /******************************************/
 /* B 1.5.3 - Declaration & Initialisation */
 /******************************************/
 /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
 // SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body)
-void *declaration_check_c::visit(program_declaration_c *symbol) {
-  /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside PROGRAMs!
-   * current_pou_decl = symbol;  
-   * current_resource_decl = NULL;  
-   */
-  /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
-  if (NULL != symbol->var_declarations)
-    symbol->var_declarations->accept(*this);
-  return NULL;
-}
+void *declaration_check_c::visit(program_declaration_c *symbol) 
+  {return NULL;} // We only check the declarations that are used to instantiate variables. This is done in the configuration!
+
+
 
 /********************************/
 /* B 1.7 Configuration elements */
@@ -199,8 +289,11 @@
 /* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
 // SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration, enumvalue_symtable_t enumvalue_symtable;)
 void *declaration_check_c::visit(resource_declaration_c *symbol) {
+  // check if any FB instantiated inside this resource (in a VAR_GLOBAL) has any VAR_EXTERNAL declarations incompatible with the configuration's VAR_GLOBALs
+  check_extern_c check_extern(current_pou_decl, current_resource_decl);
+  symbol->global_var_declarations->accept(check_extern);   
+  // Now check the Programs instantiated in this resource
   current_resource_decl = symbol;
-  /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
   symbol->resource_declaration->accept(*this);
   current_resource_decl = NULL;  
   return NULL;
@@ -211,10 +304,11 @@
   symbol_c *p_decl = program_type_symtable.find_value(symbol->program_type_name);
   if (p_decl == program_type_symtable.end_value())
     p_decl = function_block_type_symtable.find_value(symbol->program_type_name);
-  /* stage1_2 guarantees that we are sure to find a declaration in FB or Program symtable. */
   if (p_decl == function_block_type_symtable.end_value())
-    ERROR;
-  check_global_decl(p_decl);
+    ERROR;  // Should never occur! stage1_2 guarantees that we are sure to find a declaration in FB or Program symtable.
+  
+  check_extern_c check_extern(current_pou_decl, current_resource_decl);
+  p_decl->accept(check_extern);
   return NULL;
 }
 
--- a/stage3/narrow_candidate_datatypes.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage3/narrow_candidate_datatypes.cc	Wed May 28 11:32:09 2014 +0200
@@ -70,6 +70,7 @@
 	fake_prev_il_instruction = NULL;
 	current_il_instruction   = NULL;
 	il_operand = NULL;
+	current_scope = NULL;
 }
 
 narrow_candidate_datatypes_c::~narrow_candidate_datatypes_c(void) {
@@ -651,6 +652,7 @@
 /*********************/
 // SYM_REF1(symbolic_variable_c, var_name)
 void *narrow_candidate_datatypes_c::visit(symbolic_variable_c *symbol) {
+	symbol->scope = current_scope;  // the scope in which this variable was declared!
 	symbol->var_name->datatype = symbol->datatype;
 	return NULL;
 }
@@ -674,6 +676,8 @@
 	if (symbol->subscripted_variable->candidate_datatypes.size() == 1)
 	  symbol->subscripted_variable->datatype = symbol->subscripted_variable->candidate_datatypes[0]; // set the datatype
 
+	// the scope in which this variable was declared! It will be the same as the subscripted variable (a symbolic_variable_ !)
+	symbol->scope = symbol->subscripted_variable->scope;	
 	return NULL;
 }
 
@@ -708,6 +712,7 @@
 	if (symbol->record_variable->candidate_datatypes.size() == 1)
 	  symbol->record_variable->datatype = symbol->record_variable->candidate_datatypes[0]; // set the datatype
 
+	symbol->scope = symbol->record_variable->datatype;	// the scope in which this variable was declared!
 	return NULL;
 }
 
@@ -764,12 +769,14 @@
 	symbol->type_name->datatype = search_base_type_c::get_basetype_decl(symbol->type_name);
 	symbol->datatype = symbol->type_name->datatype;
 	
+	current_scope = symbol;	
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
 	symbol->var_declarations_list->accept(*this);
 	if (debug) printf("Narrowing candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
 	symbol->function_body->accept(*this);
 	delete search_varfb_instance_type;
 	search_varfb_instance_type = NULL;
+	current_scope = NULL;	
 	return NULL;
 }
 
@@ -777,13 +784,15 @@
 /* B 1.5.2 Function blocks */
 /***************************/
 void *narrow_candidate_datatypes_c::visit(function_block_declaration_c *symbol) {
+	current_scope = symbol;	
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
 	symbol->var_declarations->accept(*this);
 	if (debug) printf("Narrowing candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
 	symbol->fblock_body->accept(*this);
 	delete search_varfb_instance_type;
 	search_varfb_instance_type = NULL;
-	
+	current_scope = NULL;	
+
 	// A FB declaration can also be used as a Datatype! We now do the narrow algorithm considering it as such!
 	if (symbol->candidate_datatypes.size() == 1)
 		symbol->datatype = symbol->candidate_datatypes[0];
@@ -794,12 +803,14 @@
 /* B 1.5.3 Programs */
 /********************/
 void *narrow_candidate_datatypes_c::visit(program_declaration_c *symbol) {
+	current_scope = symbol;	
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
 	symbol->var_declarations->accept(*this);
 	if (debug) printf("Narrowing candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
 	symbol->function_block_body->accept(*this);
 	delete search_varfb_instance_type;
 	search_varfb_instance_type = NULL;
+	current_scope = NULL;	
 	return NULL;
 }
 
--- a/stage3/narrow_candidate_datatypes.hh	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage3/narrow_candidate_datatypes.hh	Wed May 28 11:32:09 2014 +0200
@@ -65,6 +65,7 @@
 
   private:
     search_varfb_instance_type_c *search_varfb_instance_type;
+    symbol_c *current_scope;
     symbol_c *il_operand;
     il_instruction_c *fake_prev_il_instruction;
     il_instruction_c   *current_il_instruction;
--- a/stage4/generate_c/generate_c.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage4/generate_c/generate_c.cc	Wed May 28 11:32:09 2014 +0200
@@ -386,6 +386,131 @@
 /***********************************************************************/
 /***********************************************************************/
 /***********************************************************************/
+/* A helper class that analyses if the datatype of a variable is 'complex'. */
+/* 'complex' means that it is either a strcuture or an array!               */
+class print_getter_c: public search_visitor_c {
+  private:
+    static print_getter_c *singleton_;
+
+  public:
+    print_getter_c(void) {};
+    
+    static bool is_complex_type(symbol_c *symbol) {
+      if (NULL == symbol) ERROR;
+      if (!get_datatype_info_c::is_type_valid     (symbol->datatype)) return false;
+      return (   get_datatype_info_c::is_structure(symbol->datatype) 
+              || get_datatype_info_c::is_array    (symbol->datatype) 
+             );
+    }
+
+    
+  private:
+    symbol_c *last_fb, *first_non_fb_identifier;
+
+  public:  
+    /* returns the first element (from left to right) in a structured variable that is not a FB, i.e. is either a structure or an array! */
+    /* eg:
+     *      fb1.fb2.fb3.real       returns ??????
+     *      fb1.fb2.struct1.real   returns struct1
+     *      struct1.real           returns struct1
+     */
+    static symbol_c *find_first_nonfb(symbol_c *symbol) {
+      if (NULL == singleton_)       singleton_ = new print_getter_c();
+      if (NULL == singleton_)       ERROR;
+      if (NULL == symbol)           ERROR;
+      
+      singleton_->last_fb                 = NULL;
+      singleton_->first_non_fb_identifier = NULL;
+      return (symbol_c *)symbol->accept(*singleton_);
+    }
+    
+    /* returns true if a strcutured variable (e.g. fb1.fb2.strcut1.real) contains a structure or array */
+    /* eg:
+     *      fb1.fb2.fb3.real       returns FALSE
+     *      fb1.fb2.struct1.real   returns TRUE
+     *      struct1.real           returns TRUE
+     */
+    static bool contains_complex_type(symbol_c *symbol) {
+      if (NULL == symbol) ERROR;
+      if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR;
+      
+      symbol_c *first_non_fb = (symbol_c *)find_first_nonfb(symbol);
+      return is_complex_type(first_non_fb->datatype);
+    }
+    
+    
+    /* returns the datatype of the variable returned by find_first_nonfb() */
+    /* eg:
+     *      fb1.fb2.fb3.real       returns ??????
+     *      fb1.fb2.struct1.real   returns datatype of struct1
+     *      struct1.real           returns datatype of struct1
+     */
+    static search_var_instance_decl_c::vt_t first_nonfb_vardecltype(symbol_c *symbol, symbol_c *scope) {
+      if (NULL == symbol) ERROR;
+      if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR;
+      
+      symbol_c *first_non_fb = (symbol_c *)find_first_nonfb(symbol);
+      if (NULL != singleton_->last_fb) {
+        scope = singleton_->last_fb->datatype;
+        symbol = singleton_->first_non_fb_identifier;
+      }
+      
+      search_var_instance_decl_c search_var_instance_decl(scope);
+      
+      return search_var_instance_decl.get_vartype(symbol);
+    }
+    
+    
+    /*********************/
+    /* B 1.4 - Variables */
+    /*********************/
+    void *visit(symbolic_variable_c *symbol) {
+      if (!get_datatype_info_c::is_type_valid    (symbol->datatype)) ERROR;
+      if (!get_datatype_info_c::is_function_block(symbol->datatype)) {
+         first_non_fb_identifier = symbol; 
+         return (void *)symbol;
+      }
+      last_fb = symbol;
+      return NULL;
+    }
+    
+    /*************************************/
+    /* B.1.4.2   Multi-element Variables */
+    /*************************************/
+    
+    // SYM_REF2(structured_variable_c, record_variable, field_selector)
+    void *visit(structured_variable_c *symbol) {
+      symbol_c *res = (symbol_c *)symbol->record_variable->accept(*this);
+      if (NULL != res) return res;
+      
+      if (!get_datatype_info_c::is_type_valid    (symbol->datatype)) ERROR;
+      if (!get_datatype_info_c::is_function_block(symbol->datatype)) {
+         first_non_fb_identifier = symbol->field_selector; 
+         return (void *)symbol;
+      }
+
+      last_fb = symbol;      
+      return NULL;      
+    }
+    
+    /*  subscripted_variable '[' subscript_list ']' */
+    //SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+    void *visit(array_variable_c *symbol) {
+      void *res = symbol->subscripted_variable->accept(*this);
+      if (NULL != res) return res;
+      return (void *)symbol;      
+    }
+
+    
+};
+
+print_getter_c *print_getter_c::singleton_ = NULL;
+
+
+
+
+
+
 
 /* A helper class that analyses if the datatype of a variable is 'complex'. */
 /* 'complex' means that it is either a strcuture or an array!               */
@@ -1573,7 +1698,7 @@
   s4o.print(SET_VAR);
   s4o.print("(");
   s4o.print(FB_FUNCTION_PARAM);
-  s4o.print("->,ENO,__BOOL_LITERAL(FALSE));\n");
+  s4o.print("->,ENO,,__BOOL_LITERAL(FALSE));\n");
   s4o.print(s4o.indent_spaces + "return;\n");
   s4o.indent_left();
   s4o.print(s4o.indent_spaces + "}\n");
@@ -1583,7 +1708,7 @@
   s4o.print(SET_VAR);
   s4o.print("(");
   s4o.print(FB_FUNCTION_PARAM);
-  s4o.print("->,ENO,__BOOL_LITERAL(TRUE));\n");
+  s4o.print("->,ENO,,__BOOL_LITERAL(TRUE));\n");
   s4o.indent_left();
   s4o.print(s4o.indent_spaces + "}\n");
 
@@ -2403,7 +2528,7 @@
             s4o.print(SET_VAR);
             s4o.print("(");
             current_task_name->accept(*this);
-            s4o.print("_R_TRIG.,CLK, *");
+            s4o.print("_R_TRIG.,CLK,, *");
             symbol->single_data_source->accept(*this);
             s4o.print(");}\n");
             s4o.print(s4o.indent_spaces + "R_TRIG");
--- a/stage4/generate_c/generate_c_base.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage4/generate_c/generate_c_base.cc	Wed May 28 11:32:09 2014 +0200
@@ -270,10 +270,9 @@
 
     /* Do not use print_token() as it will change everything into uppercase */
     void *visit(pragma_c *symbol) {
-        s4o.print(s4o.indent_spaces);
         s4o.print("#define GetFbVar(var,...) __GET_VAR(data__->var,__VA_ARGS__)\n");
         s4o.print(s4o.indent_spaces);
-        s4o.print("#define SetFbVar(var,val,...) __SET_VAR(data__->,var,val,__VA_ARGS__)\n");
+        s4o.print("#define SetFbVar(var,val,...) __SET_VAR(data__->,var,__VA_ARGS__,val)\n");
         s4o.print(symbol->value);
         s4o.print("\n");
         s4o.print(s4o.indent_spaces);
--- a/stage4/generate_c/generate_c_il.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage4/generate_c/generate_c_il.cc	Wed May 28 11:32:09 2014 +0200
@@ -445,8 +445,8 @@
         wanted_variablegeneration = complextype_base_assignment_vg;
       else
         wanted_variablegeneration = assignment_vg;
-
       symbol->accept(*this);
+/*
       s4o.print(",");
       if (negative) {
         if (get_datatype_info_c::is_BOOL_compatible(this->current_operand->datatype))
@@ -464,6 +464,24 @@
       s4o.print(")");
       wanted_variablegeneration = expression_vg;
       return NULL;
+*/
+      s4o.print(",");
+      if (type_is_complex) {
+        wanted_variablegeneration = complextype_suffix_vg;
+        symbol->accept(*this);
+      }
+      s4o.print(",");
+      if (negative) {
+        if (get_datatype_info_c::is_BOOL_compatible(this->current_operand->datatype))
+          s4o.print("!");
+        else
+          s4o.print("~");
+      }
+      wanted_variablegeneration = expression_vg;
+      print_check_function(type, value, fb_value);
+      s4o.print(")");
+      wanted_variablegeneration = expression_vg;
+      return NULL;
     }
 
 public:
--- a/stage4/generate_c/generate_c_inlinefcall.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage4/generate_c/generate_c_inlinefcall.cc	Wed May 28 11:32:09 2014 +0200
@@ -281,7 +281,7 @@
       else
         s4o.print(SET_VAR);
       s4o.print("(,");
-
+/*
       wanted_variablegeneration = complextype_base_vg;
       symbol->accept(*this);
       s4o.print(",");
@@ -295,6 +295,20 @@
       s4o.print(")");
       wanted_variablegeneration = expression_vg;
       return NULL;
+*/
+      wanted_variablegeneration = complextype_base_vg;
+      symbol->accept(*this);
+      s4o.print(",");
+      if (analyse_variable_c::contains_complex_type(symbol)) {
+        wanted_variablegeneration = complextype_suffix_vg;
+        symbol->accept(*this);
+      }
+      s4o.print(",");
+      wanted_variablegeneration = expression_vg;
+      print_check_function(type, value, NULL, true);
+      s4o.print(")");
+      wanted_variablegeneration = expression_vg;
+      return NULL;
     }
 
     /*********************/
--- a/stage4/generate_c/generate_c_sfc.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage4/generate_c/generate_c_sfc.cc	Wed May 28 11:32:09 2014 +0200
@@ -136,7 +136,7 @@
       s4o.print(SET_VAR);
       s4o.print("(");
       print_step_argument(step_name, "state", true);
-      s4o.print(",0);\n");
+      s4o.print(",,0);\n");
     }
     
     void print_set_step(symbol_c *step_name) {
@@ -144,7 +144,7 @@
       s4o.print(SET_VAR);
       s4o.print("(");
       print_step_argument(step_name, "state", true);
-      s4o.print(",1);\n" + s4o.indent_spaces);
+      s4o.print(",,1);\n" + s4o.indent_spaces);
       print_step_argument(step_name, "elapsed_time");
       s4o.print(" = __time_to_timespec(1, 0, 0, 0, 0, 0);\n");
     }
@@ -299,7 +299,7 @@
           print_variable_prefix();
           s4o.print(",__transition_list[");
           print_transition_number();
-          s4o.print("],0);\n");
+          s4o.print("],,0);\n");
           s4o.indent_left();
           s4o.print(s4o.indent_spaces + "}\n");
           break;
@@ -358,7 +358,7 @@
               s4o.print("__");
             s4o.print("transition_list[");
             print_transition_number();
-            s4o.print("],");
+            s4o.print("],,");
             generate_c_il->print_implicit_variable_back();
             // generate_c_il->reset_default_variable_name(); // generate_c_il does not require his anymore
             s4o.print(");\n");
@@ -376,7 +376,7 @@
               s4o.print("__");
             s4o.print("transition_list[");
             print_transition_number();
-            s4o.print("],");
+            s4o.print("],,");
             symbol->transition_condition_st->accept(*generate_c_st);
             s4o.print(");\n");
           }
@@ -389,7 +389,7 @@
             print_variable_prefix();
             s4o.print(",__debug_transition_list[");
             print_transition_number();
-            s4o.print("],");
+            s4o.print("],,");
             s4o.print(GET_VAR);
             s4o.print("(");
             print_variable_prefix();
@@ -514,7 +514,7 @@
             s4o.print(SET_VAR);
             s4o.print("(");
             print_action_argument(symbol->action_name, "state", true);
-            s4o.print(",1);\n");
+            s4o.print(",,1);\n");
             s4o.indent_left();
             s4o.print(s4o.indent_spaces + "}");
           }
@@ -575,7 +575,7 @@
                 print_variable_prefix();
                 s4o.print(",");
                 current_action->accept(*this);
-                s4o.print(",1);\n");
+                s4o.print(",,1);\n");
                 s4o.indent_left();
                 s4o.print(s4o.indent_spaces + "}\n");
                 s4o.print(s4o.indent_spaces + "else if (active) {\n");
@@ -591,14 +591,14 @@
                 print_variable_prefix();
                 s4o.print(",");
                 current_action->accept(*this);
-                s4o.print(",0);\n");
+                s4o.print(",,0);\n");
               }
 
               else {
                 s4o.print(SET_VAR);
                 s4o.print("(");
                 print_action_argument(current_action, "state", true);
-                s4o.print(",1);\n");
+                s4o.print(",,1);\n");
               }
             }
             if (strcmp(qualifier, "S") == 0 || strcmp(qualifier, "SL") == 0) {
@@ -773,7 +773,7 @@
       s4o.print(SET_VAR);
       s4o.print("(");
       print_variable_prefix();
-      s4o.print(",__action_list[i].state,0);\n");
+      s4o.print(",__action_list[i].state,,0);\n");
       s4o.print(s4o.indent_spaces);
       print_variable_prefix();
       s4o.print("__action_list[i].set = 0;\n");
@@ -895,7 +895,7 @@
       s4o.print(SET_VAR);
       s4o.print("(");
       print_variable_prefix();
-      s4o.print(",__action_list[i].state,");
+      s4o.print(",__action_list[i].state,,");
       s4o.print(GET_VAR);
       s4o.print("(");
       print_variable_prefix();
@@ -932,7 +932,7 @@
             print_variable_prefix();
             s4o.print(",");
             pt->symbol->accept(*this);
-            s4o.print(",0);\n");
+            s4o.print(",,0);\n");
             s4o.indent_left();
             s4o.print(s4o.indent_spaces + "}\n");
             s4o.print(s4o.indent_spaces + "else if (");
@@ -953,7 +953,7 @@
             print_variable_prefix();
             s4o.print(",");
             pt->symbol->accept(*this);
-            s4o.print(",1);\n");
+            s4o.print(",,1);\n");
             s4o.indent_left();
             s4o.print(s4o.indent_spaces + "}\n");
           }
--- a/stage4/generate_c/generate_c_sfcdecl.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage4/generate_c/generate_c_sfcdecl.cc	Wed May 28 11:32:09 2014 +0200
@@ -252,7 +252,7 @@
           print_variable_prefix();
           s4o.print(",__step_list[");
           s4o.print(step_number);
-          s4o.print("].state,1);\n");
+          s4o.print("].state,,1);\n");
           step_number++;
           break;
         case stepdef_sd:
--- a/stage4/generate_c/generate_c_st.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage4/generate_c/generate_c_st.cc	Wed May 28 11:32:09 2014 +0200
@@ -49,9 +49,7 @@
   public:
     typedef enum {
       expression_vg,
-      assignment_vg,
       complextype_base_vg,
-      complextype_base_assignment_vg,
       complextype_suffix_vg,
       fparam_output_vg
     } variablegeneration_t;
@@ -157,9 +155,10 @@
     else
       s4o.print(GET_VAR);
   }
+  
+  variablegeneration_t old_wanted_variablegeneration = wanted_variablegeneration;
   s4o.print("(");
-
-  variablegeneration_t old_wanted_variablegeneration = wanted_variablegeneration;
+  print_variable_prefix();  
   wanted_variablegeneration = complextype_base_vg;
   symbol->accept(*this);
   s4o.print(",");
@@ -177,14 +176,14 @@
         symbol_c* value,
         symbol_c* fb_symbol = NULL,
         symbol_c* fb_value = NULL) {
-  
-  bool type_is_complex = false;
+ 
   if (fb_symbol == NULL) {
     unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol, scope_);
-    type_is_complex = analyse_variable_c::contains_complex_type(symbol);
+    symbol_c *first_nonfb = analyse_variable_c::find_first_nonfb(symbol);
+    if (first_nonfb == NULL) ERROR;
     if (vartype == search_var_instance_decl_c::external_vt) {
-      if (!get_datatype_info_c::is_type_valid    (symbol->datatype)) ERROR;
-      if ( get_datatype_info_c::is_function_block(symbol->datatype))
+      if (!get_datatype_info_c::is_type_valid    (first_nonfb->datatype)) ERROR;
+      if ( get_datatype_info_c::is_function_block(first_nonfb->datatype)) // handle situation where we are copying a complete fb -> fb1.fb2.fb3 := fb4 (and fb3 is external!)
         s4o.print(SET_EXTERNAL_FB);
       else
         s4o.print(SET_EXTERNAL);
@@ -202,26 +201,29 @@
       s4o.print(SET_VAR);
   }
   s4o.print("(");
-
+  
   if (fb_symbol != NULL) {
     print_variable_prefix();
+    // It is my (MJS) conviction that by this time the following will always be true...
+    //   wanted_variablegeneration == expression_vg;
     fb_symbol->accept(*this);
     s4o.print(".,");
-  }
-  else if (type_is_complex)
-    wanted_variablegeneration = complextype_base_assignment_vg;
-  else
-    wanted_variablegeneration = assignment_vg;
-  
-  symbol->accept(*this);
-  s4o.print(",");
-  wanted_variablegeneration = expression_vg;
-  print_check_function(type, value, fb_value);
-  if (type_is_complex) {
+    symbol->accept(*this);
+    s4o.print(",");
+    s4o.print(",");    
+  }
+  else {
+    print_variable_prefix();
+    s4o.print(",");    
+    wanted_variablegeneration = complextype_base_vg;
+    symbol->accept(*this);
     s4o.print(",");
     wanted_variablegeneration = complextype_suffix_vg;
     symbol->accept(*this);
-  }
+    s4o.print(",");
+  }
+  wanted_variablegeneration = expression_vg;
+  print_check_function(type, value, fb_value);
   s4o.print(")");
   wanted_variablegeneration = expression_vg;
   return NULL;
@@ -264,14 +266,8 @@
 /*********************/
 void *visit(symbolic_variable_c *symbol) {
   switch (wanted_variablegeneration) {
-    case complextype_base_assignment_vg:
-    case assignment_vg:
-      this->print_variable_prefix();
-      s4o.print(",");
-      symbol->var_name->accept(*this);
-      break;
     case complextype_base_vg:
-      generate_c_base_c::visit(symbol);
+      symbol->var_name->accept(*this); //generate_c_base_c::visit(symbol);
       break;
     case complextype_suffix_vg:
       break;
@@ -321,8 +317,9 @@
   }
   this->print_variable_prefix();
   s4o.printlocation(symbol->value + 1);
-  if ((this->is_variable_prefix_null() && wanted_variablegeneration != fparam_output_vg) ||
-      wanted_variablegeneration != assignment_vg)
+  if (( this->is_variable_prefix_null() && (wanted_variablegeneration != fparam_output_vg)) ||
+      (!this->is_variable_prefix_null() && (wanted_variablegeneration == expression_vg   )) ||
+      (!this->is_variable_prefix_null() && (wanted_variablegeneration == fparam_output_vg)))
     s4o.print(")");
   return NULL;
 }
@@ -334,28 +331,26 @@
 // SYM_REF2(structured_variable_c, record_variable, field_selector)
 void *visit(structured_variable_c *symbol) {
   TRACE("structured_variable_c");
-  bool type_is_complex = analyse_variable_c::is_complex_type(symbol->record_variable);
   switch (wanted_variablegeneration) {
     case complextype_base_vg:
-    case complextype_base_assignment_vg:
       symbol->record_variable->accept(*this);
-      if (!type_is_complex) {
+      if ( get_datatype_info_c::is_function_block(symbol->record_variable->datatype)) {
+        if (NULL == symbol->record_variable->scope) ERROR;
+        search_var_instance_decl_c search_var_instance_decl(symbol->record_variable->scope);
+        if (search_var_instance_decl_c::external_vt == search_var_instance_decl.get_vartype(get_var_name_c::get_last_field(symbol->record_variable)))
+          s4o.print("->");
+        else  
+          s4o.print(".");
+        symbol->field_selector->accept(*this);
+      }
+      break;
+    case complextype_suffix_vg:
+      symbol->record_variable->accept(*this);
+      if (!get_datatype_info_c::is_function_block(symbol->record_variable->datatype)) { // if the record variable is not a FB, then it will certainly be a structure!
         s4o.print(".");
         symbol->field_selector->accept(*this);
       }
       break;
-    case complextype_suffix_vg:
-      symbol->record_variable->accept(*this);
-      if (type_is_complex) {
-        s4o.print(".");
-        symbol->field_selector->accept(*this);
-      }
-      break;
-    case assignment_vg:
-      symbol->record_variable->accept(*this);
-      s4o.print(".");
-      symbol->field_selector->accept(*this);
-      break;
     default:
       if (this->is_variable_prefix_null()) {
         symbol->record_variable->accept(*this);
@@ -374,7 +369,6 @@
 void *visit(array_variable_c *symbol) {
   switch (wanted_variablegeneration) {
     case complextype_base_vg:
-    case complextype_base_assignment_vg:
       symbol->subscripted_variable->accept(*this);
       break;
     case complextype_suffix_vg:
@@ -482,6 +476,7 @@
     variablegeneration_t old_wanted_variablegeneration = wanted_variablegeneration; 
     s4o.print("(");
     wanted_variablegeneration = complextype_base_vg;
+    print_variable_prefix();
     symbol->exp->accept(*this);
     s4o.print(",");
     wanted_variablegeneration = complextype_suffix_vg;
--- a/stage4/generate_c/generate_c_vardecl.cc	Thu Mar 20 17:27:29 2014 +0100
+++ b/stage4/generate_c/generate_c_vardecl.cc	Wed May 28 11:32:09 2014 +0200
@@ -169,7 +169,7 @@
         print_variable_prefix();
         s4o.print(",");
         symbol->elements[i]->accept(*this);
-        s4o.print(",temp);\n");
+        s4o.print(",,temp);\n");
       }
       return NULL;
     }
@@ -577,7 +577,7 @@
         print_variable_prefix();
         s4o.print(",");
         symbol->elements[i]->accept(*this);
-        s4o.print(",temp);\n");
+        s4o.print(",,temp);\n");
       }
       return NULL;
     }
@@ -1000,7 +1000,7 @@
               s4o.print("}\n");
             }
             else if (wanted_varformat == init_vf) {
-              s4o.print(",");
+              s4o.print(",,");
               this->current_var_init_symbol->accept(*this);
               s4o.print(");\n");
             }