stage4/generate_c/generate_c.cc
changeset 258 d7d92b2f87e9
parent 257 90782e241346
parent 250 5d2927300e2c
child 262 197ba42d78b2
--- a/stage4/generate_c/generate_c.cc	Wed Mar 30 19:53:32 2011 +0100
+++ b/stage4/generate_c/generate_c.cc	Thu Mar 31 10:45:34 2011 +0100
@@ -122,23 +122,38 @@
 
 #define SFC_STEP_ACTION_PREFIX "__SFC_"
 
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-
-#include "generate_c_base.cc"
-#include "generate_c_typedecl.cc"
-#include "generate_c_sfcdecl.cc"
-#include "generate_c_vardecl.cc"
-#include "generate_c_configbody.cc"
-#include "generate_location_list.cc"
-#include "generate_var_list.cc"
-
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
+
+/* Variable declaration symbol for accessor macros */
+#define DECLARE_VAR "__DECLARE_VAR"
+#define DECLARE_GLOBAL "__DECLARE_GLOBAL"
+#define DECLARE_GLOBAL_LOCATION "__DECLARE_GLOBAL_LOCATION"
+#define DECLARE_GLOBAL_LOCATED "__DECLARE_GLOBAL_LOCATED"
+#define DECLARE_EXTERNAL "__DECLARE_EXTERNAL"
+#define DECLARE_LOCATED "__DECLARE_LOCATED"
+
+/* Variable declaration symbol for accessor macros */
+#define INIT_VAR "__INIT_VAR"
+#define INIT_GLOBAL "__INIT_GLOBAL"
+#define INIT_GLOBAL_LOCATED "__INIT_GLOBAL_LOCATED"
+#define INIT_EXTERNAL "__INIT_EXTERNAL"
+#define INIT_LOCATED "__INIT_LOCATED"
+#define INIT_LOCATED_VALUE "__INIT_LOCATED_VALUE"
+
+
+/* Variable getter symbol for accessor macros */
+#define GET_VAR "__GET_VAR"
+#define GET_EXTERNAL "__GET_EXTERNAL"
+#define GET_LOCATED "__GET_LOCATED"
+#define GET_VAR_BY_REF "__GET_VAR_BY_REF"
+#define GET_EXTERNAL_BY_REF "__GET_EXTERNAL_BY_REF"
+#define GET_LOCATED_BY_REF "__GET_LOCATED_BY_REF"
+
+/* Variable setter symbol for accessor macros */
+#define SET_VAR "__SET_VAR"
+#define SET_EXTERNAL "__SET_EXTERNAL"
+#define SET_COMPLEX_EXTERNAL "__SET_COMPLEX_EXTERNAL"
+#define SET_LOCATED "__SET_LOCATED"
+
 
 /* Generate a name for a temporary variable.
  * Each new name generated is appended a different number,
@@ -149,8 +164,27 @@
 #define TEMP_VAR VAR_LEADER "TMP_"
 #define SOURCE_VAR VAR_LEADER "SRC_"
 
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+
+#include "generate_c_base.cc"
+#include "generate_c_typedecl.cc"
+#include "generate_c_sfcdecl.cc"
+#include "generate_c_vardecl.cc"
+#include "generate_c_configbody.cc"
+#include "generate_location_list.cc"
+#include "generate_var_list.cc"
+
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+
 #include "generate_c_st.cc"
 #include "generate_c_il.cc"
+#include "generate_c_inlinefcall.cc"
 
 #include "generate_c.hh"
 
@@ -165,13 +199,13 @@
 /* A helper class that knows how to generate code for both the IL and ST languages... */
 class calculate_time_c: public iterator_visitor_c {
   private:
-    unsigned long time;
+    unsigned long long time;
     float current_value;
   
   public:
     calculate_time_c(void){time = 0;};
     
-    unsigned long get_time(void) {return time;};
+    unsigned long long get_time(void) {return time;};
 
     void *get_integer_value(token_c *token) {
       std::string str = "";
@@ -213,7 +247,7 @@
       if (symbol->hours)
         symbol->hours->accept(*this);
       symbol->days->accept(*this);
-      time += (unsigned long)(current_value * 24 * 3600 * SECOND);
+      time += (unsigned long long)(current_value * 24 * 3600 * SECOND);
       return NULL;
     }
     
@@ -222,7 +256,7 @@
       if (symbol->minutes)
         symbol->minutes->accept(*this);
       symbol->hours->accept(*this);
-      time += (unsigned long)(current_value * 3600 * SECOND);
+      time += (unsigned long long)(current_value * 3600 * SECOND);
       return NULL;
     }
     
@@ -231,7 +265,7 @@
       if (symbol->seconds)
         symbol->seconds->accept(*this);
       symbol->minutes->accept(*this);
-      time += (unsigned long)(current_value * 60 * SECOND);
+      time += (unsigned long long)(current_value * 60 * SECOND);
       return NULL;
     }
     
@@ -240,14 +274,14 @@
       if (symbol->milliseconds)
         symbol->milliseconds->accept(*this);
       symbol->seconds->accept(*this);
-      time += (unsigned long)(current_value * SECOND);
+      time += (unsigned long long)(current_value * SECOND);
       return NULL;
     }
     
     /* SYM_REF2(milliseconds_c, milliseconds, unused) */
     void *visit(milliseconds_c *symbol) {
       symbol->milliseconds->accept(*this);
-      time += (unsigned long)(current_value * MILLISECOND);
+      time += (unsigned long long)(current_value * MILLISECOND);
       return NULL;
     }
 };
@@ -259,37 +293,52 @@
 
 class calculate_common_ticktime_c: public iterator_visitor_c {
   private:
-    unsigned long common_ticktime;
+    unsigned long long common_ticktime;
+    unsigned long long least_common_ticktime;
     
   public:
-    calculate_common_ticktime_c(void){common_ticktime = 0;}
-    
-    unsigned long euclide(unsigned long a, unsigned long b) {
-      unsigned long c = a % b;
+    calculate_common_ticktime_c(void){
+      common_ticktime = 0;
+      least_common_ticktime = 0;
+    }
+    
+    unsigned long long euclide(unsigned long long a, unsigned long long b) {
+      unsigned long long c = a % b;
       if (c == 0)
         return b;
       else
         return euclide(b, c);
     }
     
-    void update_ticktime(unsigned long time) {
+    void update_ticktime(unsigned long long time) {
       if (common_ticktime == 0)
         common_ticktime = time;
       else if (time > common_ticktime)
         common_ticktime = euclide(time, common_ticktime);
       else
         common_ticktime = euclide(common_ticktime, time);
-    }
-
-    unsigned long get_ticktime(void) {
+      if (least_common_ticktime == 0)
+        least_common_ticktime = time;
+      else
+        least_common_ticktime = (least_common_ticktime * time) / common_ticktime;
+    }
+
+    unsigned long long get_common_ticktime(void) {
       return common_ticktime;
     }
 
+    unsigned long get_greatest_tick_count(void) {
+      unsigned long long least_common_tick = least_common_ticktime / common_ticktime;
+      if (least_common_tick >> 32)
+        ERROR;
+      return (unsigned long)(~(((unsigned long)-1) % (unsigned long)least_common_tick) + 1);
+    }
+
 /*  TASK task_name task_initialization */
 //SYM_REF2(task_configuration_c, task_name, task_initialization)  
     void *visit(task_initialization_c *symbol) {
       calculate_time_c calculate_time;
-      unsigned long time = 0;
+      unsigned long long time = 0;
       if (symbol->interval_data_source != NULL) {
         symbol->interval_data_source->accept(calculate_time);
         time = calculate_time.get_time();
@@ -305,15 +354,16 @@
 /***********************************************************************/
 /***********************************************************************/
 
-/* A helper class that knows how to generate code for both the IL and ST languages... */
+/* A helper class that knows how to generate code for the SFC, IL and ST languages... */
 class generate_c_SFC_IL_ST_c: public null_visitor_c {
   private:
     stage4out_c *s4o_ptr;
     symbol_c *scope;
+    symbol_c *fbname;
     const char *variable_prefix;
 
   public:
-    generate_c_SFC_IL_ST_c(stage4out_c *s4o_ptr, symbol_c *scope, const char *variable_prefix = NULL);
+    generate_c_SFC_IL_ST_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL);
     /*********************************************/
     /* B.1.6  Sequential function chart elements */
     /*********************************************/
@@ -351,27 +401,28 @@
 
 #include "generate_c_sfc.cc"
 
-generate_c_SFC_IL_ST_c::generate_c_SFC_IL_ST_c(stage4out_c *s4o_ptr, symbol_c *scope, const char *variable_prefix) {
+generate_c_SFC_IL_ST_c::generate_c_SFC_IL_ST_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix) {
   if (NULL == scope) ERROR;
   this->s4o_ptr = s4o_ptr;
   this->scope = scope;
+  this->fbname = name;
   this->variable_prefix = variable_prefix;
 }
 
 void *generate_c_SFC_IL_ST_c::visit(sequential_function_chart_c * symbol) {
-  generate_c_sfc_c generate_c_sfc(s4o_ptr, scope, variable_prefix);
+  generate_c_sfc_c generate_c_sfc(s4o_ptr, fbname, scope, variable_prefix);
   generate_c_sfc.generate(symbol);
   return NULL;
 }
 
 void *generate_c_SFC_IL_ST_c::visit(instruction_list_c *symbol) {
-  generate_c_il_c generate_c_il(s4o_ptr, scope, variable_prefix);
+  generate_c_il_c generate_c_il(s4o_ptr, fbname, scope, variable_prefix);
   generate_c_il.generate(symbol);
   return NULL;
 }
 
 void *generate_c_SFC_IL_ST_c::visit(statement_list_c *symbol) {
-  generate_c_st_c generate_c_st(s4o_ptr, scope, variable_prefix);
+  generate_c_st_c generate_c_st(s4o_ptr, fbname, scope, variable_prefix);
   generate_c_st.generate(symbol);
   return NULL;
 }
@@ -552,7 +603,7 @@
   s4o.print(s4o.indent_spaces + "}\n");
 
   /* (C) Function body */
-  generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol);
+  generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->derived_function_name, symbol);
   symbol->function_body->accept(generate_c_code);
   
   vardecl = new generate_c_vardecl_c(&s4o,
@@ -588,6 +639,7 @@
   generate_c_vardecl_c *vardecl;
   generate_c_sfcdecl_c *sfcdecl;
   generate_c_typedecl_c *typedecl;
+  generate_c_inlinefcall_c *inlinedecl;
   TRACE("function_block_declaration_c");
 
   /* (A) Function Block data structure declaration... */
@@ -622,11 +674,11 @@
   delete vardecl;
   
   /* (A.4) Generate private internal variables for SFC */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o_incl, generate_c_sfcdecl_c::sfcdecl_sd);
-  sfcdecl->print(symbol->fblock_body);
+  sfcdecl = new generate_c_sfcdecl_c(&s4o_incl, symbol);
+  sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::sfcdecl_sd);
   delete sfcdecl;
   s4o_incl.print("\n");
-  
+
   /* (A.5) Function Block data structure type name. */
   s4o_incl.indent_left();
   s4o_incl.print("} ");
@@ -634,6 +686,11 @@
   s4o_incl.print(";\n\n");
   delete typedecl;
 
+  /* (A.6) Function Block inline function declaration for function invocation */
+  inlinedecl = new generate_c_inlinefcall_c(&s4o, symbol->fblock_name, symbol, FB_FUNCTION_PARAM"->");
+  inlinedecl->print(symbol->fblock_body);
+  delete inlinedecl;
+
   /* (B) Constructor */
   /* (B.1) Constructor name... */
   s4o.print(s4o.indent_spaces + "void ");
@@ -645,7 +702,7 @@
   symbol->fblock_name->accept(*this);
   s4o.print(" *");
   s4o.print(FB_FUNCTION_PARAM);
-  s4o.print(") {\n");
+  s4o.print(", BOOL retain) {\n");
   s4o.indent_right();
 
   /* (B.2) Member initializations... */
@@ -663,25 +720,23 @@
   vardecl->print(symbol->var_declarations, NULL, FB_FUNCTION_PARAM"->");
   delete vardecl;
   s4o.print("\n");
+
+  sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol, FB_FUNCTION_PARAM"->");
+
   /* (B.3) Generate private internal variables for SFC */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::sfcinit_sd);
-  sfcdecl->print(symbol->fblock_body, FB_FUNCTION_PARAM"->");
-  delete sfcdecl;
+  sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::sfcinit_sd);
+
   s4o.indent_left();
   s4o.print(s4o.indent_spaces + "}\n\n");
 
   
   /* (C) Function with FB body */
   /* (C.1) Step definitions */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::stepdef_sd);
-  sfcdecl->print(symbol->fblock_body);
-  delete sfcdecl;
+  sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::stepdef_sd);
   
   /* (C.2) Action definitions */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::actiondef_sd);
-  sfcdecl->print(symbol->fblock_body);
-  delete sfcdecl;
-  
+  sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::actiondef_sd);
+
   /* (C.3) Function declaration */
   s4o.print("// Code part\n");
   /* function interface */
@@ -698,20 +753,26 @@
 
   s4o.print(s4o.indent_spaces + "// Control execution\n");
   s4o.print(s4o.indent_spaces + "if (!");
+  s4o.print(GET_VAR);
+  s4o.print("(");
   s4o.print(FB_FUNCTION_PARAM);
-  s4o.print("->EN) {\n");
+  s4o.print("->EN)) {\n");
   s4o.indent_right();
   s4o.print(s4o.indent_spaces);
+  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");
   s4o.print(s4o.indent_spaces + "else {\n");
   s4o.indent_right();
   s4o.print(s4o.indent_spaces);
+  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");
 
@@ -726,7 +787,7 @@
   s4o.print("\n");
 
   /* (C.5) Function code */
-  generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol, FB_FUNCTION_PARAM"->");
+  generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->fblock_name, symbol, FB_FUNCTION_PARAM"->");
   symbol->fblock_body->accept(generate_c_code);
   s4o.indent_left();
   s4o.print(s4o.indent_spaces + "} // ");
@@ -735,13 +796,11 @@
   s4o.print(s4o.indent_spaces + "() \n\n");
 
   /* (C.6) Step undefinitions */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::stepundef_sd);
-  sfcdecl->print(symbol->fblock_body);
-  delete sfcdecl;
-  
+  sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::stepundef_sd);
+
   /* (C.7) Action undefinitions */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::actionundef_sd);
-  sfcdecl->print(symbol->fblock_body);
+  sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::actionundef_sd);
+
   delete sfcdecl;
 
   s4o.indent_left();
@@ -769,6 +828,7 @@
   generate_c_vardecl_c *vardecl;
   generate_c_sfcdecl_c *sfcdecl;
   generate_c_typedecl_c *typedecl;
+  generate_c_inlinefcall_c *inlinedecl;
   TRACE("program_declaration_c");
 
   /* (A) Program data structure declaration... */
@@ -800,10 +860,12 @@
                 generate_c_vardecl_c::external_vt);
   vardecl->print(symbol->var_declarations);
   delete vardecl;
+
   /* (A.4) Generate private internal variables for SFC */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o_incl, generate_c_sfcdecl_c::sfcdecl_sd);
-  sfcdecl->print(symbol->function_block_body);
+  sfcdecl = new generate_c_sfcdecl_c(&s4o_incl, symbol);
+  sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::sfcdecl_sd);
   delete sfcdecl;
+  s4o_incl.print("\n");
   
   /* (A.5) Program data structure type name. */
   s4o_incl.indent_left();
@@ -812,6 +874,11 @@
   s4o_incl.print(";\n\n");
   delete typedecl;
 
+  /* (A.6) Function Block inline function declaration for function invocation */
+  inlinedecl = new generate_c_inlinefcall_c(&s4o, symbol->program_type_name, symbol, FB_FUNCTION_PARAM"->");
+  inlinedecl->print(symbol->function_block_body);
+  delete inlinedecl;
+
   /* (B) Constructor */
   /* (B.1) Constructor name... */
   s4o.print(s4o.indent_spaces + "void ");
@@ -823,7 +890,7 @@
   symbol->program_type_name->accept(*this);
   s4o.print(" *");
   s4o.print(FB_FUNCTION_PARAM);
-  s4o.print(") {\n");
+  s4o.print(", BOOL retain) {\n");
   s4o.indent_right();
 
   /* (B.2) Member initializations... */
@@ -839,24 +906,21 @@
   vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
   delete vardecl;
   s4o.print("\n");
+
+  sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol, FB_FUNCTION_PARAM"->");
+
   /* (B.3) Generate private internal variables for SFC */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::sfcinit_sd);
-  sfcdecl->print(symbol->function_block_body,FB_FUNCTION_PARAM"->");
-  delete sfcdecl;
+  sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::sfcinit_sd);
 
   s4o.indent_left();
   s4o.print(s4o.indent_spaces + "}\n\n");
 
   /* (C) Function with PROGRAM body */
   /* (C.1) Step definitions */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::stepdef_sd);
-  sfcdecl->print(symbol->function_block_body);
-  delete sfcdecl;
+  sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::stepdef_sd);
   
   /* (C.2) Action definitions */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::actiondef_sd);
-  sfcdecl->print(symbol->function_block_body);
-  delete sfcdecl;
+  sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::actiondef_sd);
 
   /* (C.3) Function declaration */
   s4o.print("// Code part\n");
@@ -883,7 +947,7 @@
   s4o.print("\n");
 
   /* (C.5) Function code */
-  generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol, FB_FUNCTION_PARAM"->");
+  generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->program_type_name, symbol, FB_FUNCTION_PARAM"->");
   symbol->function_block_body->accept(generate_c_code);
   s4o.indent_left();
   s4o.print(s4o.indent_spaces + "} // ");
@@ -892,15 +956,13 @@
   s4o.print(s4o.indent_spaces + "() \n\n");
 
   /* (C.6) Step undefinitions */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::stepundef_sd);
-  sfcdecl->print(symbol->function_block_body);
+  sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::stepundef_sd);
+  
+  /* (C.7) Action undefinitions */
+  sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::actionundef_sd);
+  
   delete sfcdecl;
-  
-  /* (C.7) Action undefinitions */
-  sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::actionundef_sd);
-  sfcdecl->print(symbol->function_block_body);
-  delete sfcdecl;
-  
+
   s4o.indent_left();
   s4o.print("\n\n\n\n");
 
@@ -962,6 +1024,8 @@
   s4o.print("#include \"iec_std_lib.h\"\n\n");
   s4o.print("#include \"accessor.h\"\n\n"); 
   
+  s4o.print("#include \"accessor.h\"\n\n");
+
   /* (A) configuration declaration... */
   /* (A.1) configuration name in comment */
   s4o.print("// CONFIGURATION ");
@@ -987,6 +1051,8 @@
   s4o.print(FB_INIT_SUFFIX);
   s4o.print("(void) {\n");
   s4o.indent_right();
+  s4o.print(s4o.indent_spaces);
+  s4o.print("BOOL retain = 0;\n");
   
   /* (B.3) Global variables initializations... */
   s4o.print(s4o.indent_spaces);
@@ -1014,7 +1080,7 @@
   /* (C.2) Run function name... */
   s4o.print(s4o.indent_spaces + "void config");
   s4o.print(FB_RUN_SUFFIX);
-  s4o.print("(int tick) {\n");
+  s4o.print("(unsigned long tick) {\n");
   s4o.indent_right();
 
   /* (C.3) Resources initializations... */
@@ -1038,7 +1104,7 @@
     }
     else {
       s4o.print(FB_RUN_SUFFIX);
-      s4o.print("(int tick);\n");
+      s4o.print("(unsigned long tick);\n");
     }
   }
   if (wanted_declaretype == initdeclare_dt || wanted_declaretype == rundeclare_dt) {
@@ -1065,7 +1131,7 @@
     }
     else {
       s4o.print(FB_RUN_SUFFIX);
-      s4o.print("(int tick);\n");
+      s4o.print("(unsigned long tick);\n");
     }
   }
   if (wanted_declaretype == initdeclare_dt || wanted_declaretype == rundeclare_dt) {
@@ -1139,6 +1205,50 @@
 
     assigntype_t wanted_assigntype;
 
+    /* the qualifier of variables that need to be processed... */
+    static const unsigned int none_vq        = 0x0000;
+    static const unsigned int constant_vq    = 0x0001;  // CONSTANT
+    static const unsigned int retain_vq      = 0x0002;  // RETAIN
+    static const unsigned int non_retain_vq  = 0x0004;  // NON_RETAIN
+
+    /* variable used to store the qualifier of program currently being processed... */
+    unsigned int current_varqualifier;
+
+    void *print_retain(void) {
+	  s4o.print(",");
+      switch (current_varqualifier) {
+		case retain_vq:
+          s4o.print("1");
+          break;
+        case non_retain_vq:
+          s4o.print("0");
+          break;
+		default:
+		  s4o.print("retain");
+		  break;
+      }
+      return NULL;
+    }
+
+    /******************************************/
+    /* B 1.4.3 - Declaration & Initialisation */
+    /******************************************/
+
+    void *visit(constant_option_c *symbol) {
+      current_varqualifier = constant_vq;
+      return NULL;
+    }
+
+    void *visit(retain_option_c *symbol) {
+      current_varqualifier = retain_vq;
+      return NULL;
+    }
+
+    void *visit(non_retain_option_c *symbol) {
+      current_varqualifier = non_retain_vq;
+      return NULL;
+    }
+
 /********************************/
 /* B 1.7 Configuration elements */
 /********************************/
@@ -1182,8 +1292,10 @@
       current_resource_name->accept(*this);
       s4o.print("\n\n");
       
-      s4o.print("extern int common_ticktime__;\n\n");
-       
+      s4o.print("extern unsigned long long common_ticktime__;\n\n");
+
+      s4o.print("#include \"accessor.h\"\n\n");
+
       /* (A.2) Global variables... */
       if (current_global_vars != NULL) {
         vardecl = new generate_c_vardecl_c(&s4o,
@@ -1216,13 +1328,16 @@
       s4o.print(FB_INIT_SUFFIX);
       s4o.print("(void) {\n");
       s4o.indent_right();
+      s4o.print(s4o.indent_spaces);
+      s4o.print("BOOL retain = 0;\n");
       
       /* (B.2) Global variables initialisations... */
       if (current_global_vars != NULL) {
         s4o.print(s4o.indent_spaces);
         vardecl = new generate_c_vardecl_c(&s4o,
                                            generate_c_vardecl_c::constructorinit_vf,
-                                           generate_c_vardecl_c::global_vt);
+                                           generate_c_vardecl_c::global_vt,
+                                           current_resource_name);
         vardecl->print(current_global_vars);
         delete vardecl;
       }
@@ -1244,7 +1359,7 @@
       s4o.print("void ");
       current_resource_name->accept(*this);
       s4o.print(FB_RUN_SUFFIX);
-      s4o.print("(int tick) {\n");
+      s4o.print("(unsigned long tick) {\n");
       s4o.indent_right();
       
       wanted_declaretype = run_dt;
@@ -1285,11 +1400,14 @@
           s4o.print("\n");
           break;
         case init_dt:
+          if (symbol->retain_option != NULL)
+        	symbol->retain_option->accept(*this);
           s4o.print(s4o.indent_spaces);
           symbol->program_type_name->accept(*this);
           s4o.print(FB_INIT_SUFFIX);
           s4o.print("(&");
           symbol->program_name->accept(*this);
+          print_retain();
           s4o.print(");\n");
           break;
         case run_dt:
@@ -1372,31 +1490,37 @@
             s4o.print(FB_INIT_SUFFIX);
             s4o.print("(&");
             current_task_name->accept(*this);
-            s4o.print("_R_TRIG);\n");
+            s4o.print("_R_TRIG, retain);\n");
           }
           break;
         case run_dt:
           if (symbol->single_data_source != NULL) {
             symbol_c *config_var_decl = NULL;
             symbol_c *res_var_decl = NULL;
+            unsigned int vartype;
             symbol_c *current_var_reference = ((global_var_reference_c *)(symbol->single_data_source))->global_var_name;
             res_var_decl = search_resource_instance->get_decl(current_var_reference);
             if (res_var_decl == NULL) {
               config_var_decl = search_config_instance->get_decl(current_var_reference);
               if (config_var_decl == NULL)
                 ERROR;
+              vartype = search_config_instance->get_vartype();
               s4o.print(s4o.indent_spaces + "{extern ");
               config_var_decl->accept(*this);
               s4o.print(" *");
               symbol->single_data_source->accept(*this);
               s4o.print("; ");
             }
-            else
+            else {
+              vartype = search_resource_instance->get_vartype();
               s4o.print(s4o.indent_spaces);
+            }
+            s4o.print(SET_VAR);
+            s4o.print("(");
             current_task_name->accept(*this);
-            s4o.print("_R_TRIG.CLK = *");
+            s4o.print("_R_TRIG.CLK, *__GET_GLOBAL_");
             symbol->single_data_source->accept(*this);
-            s4o.print(";");
+            s4o.print("());");
             if (config_var_decl != NULL)
               s4o.print("}");
             s4o.print("\n");
@@ -1408,8 +1532,10 @@
             s4o.print(s4o.indent_spaces);
             current_task_name->accept(*this);
             s4o.print(" = ");
+            s4o.print(GET_VAR);
+            s4o.print("(");
             current_task_name->accept(*this);
-            s4o.print("_R_TRIG.Q");
+            s4o.print("_R_TRIG.Q)");
           }
           else {
             s4o.print(s4o.indent_spaces);
@@ -1533,7 +1659,7 @@
     const char *current_name;
     const char *current_builddir;
 
-    unsigned long common_ticktime;
+    unsigned long long common_ticktime;
 
   public:
     generate_c_c(stage4out_c *s4o_ptr, const char *builddir): 
@@ -1553,7 +1679,7 @@
 /* B 0 - Programming Model */
 /***************************/
     void *visit(library_c *symbol) {
-      pous_incl_s4o.print("#ifndef __POUS_H\n#define __POUS_H\n\n");
+      pous_incl_s4o.print("#ifndef __POUS_H\n#define __POUS_H\n\n#include \"accessor.h\"\n\n");
       for(int i = 0; i < symbol->n; i++) {
         symbol->elements[i]->accept(*this);
       }
@@ -1631,16 +1757,23 @@
       
       calculate_common_ticktime_c calculate_common_ticktime;
       symbol->accept(calculate_common_ticktime);
-      common_ticktime = calculate_common_ticktime.get_ticktime();
+      common_ticktime = calculate_common_ticktime.get_common_ticktime();
+      if (common_ticktime == 0) {
+        fprintf(stderr, "\nYou must at least define a periodic task to set cycle period!");
+        ERROR;
+      }
       
       symbol->configuration_name->accept(*this);
       stage4out_c config_s4o(current_builddir, current_name, "c");
       generate_c_config_c generate_c_config(&config_s4o);
       symbol->accept(generate_c_config);
         
-      config_s4o.print("int common_ticktime__ = ");
-      config_s4o.print_integer((int)(common_ticktime / 1000000));
-      config_s4o.print("; /*ms*/\n");
+      config_s4o.print("unsigned long long common_ticktime__ = ");
+      config_s4o.print_long_long_integer(common_ticktime);
+      config_s4o.print("; /*ns*/\n");
+      config_s4o.print("unsigned long greatest_tick_count__ = ");
+      config_s4o.print_long_integer(calculate_common_ticktime.get_greatest_tick_count());
+      config_s4o.print("; /*tick*/\n");
       
       symbol->resource_declarations->accept(*this);