merge
authormjsousa
Sat, 05 Jul 2014 14:10:28 +0100
changeset 902 38dca2e264b6
parent 901 6a3964be6a29 (diff)
parent 894 39086e324665 (current diff)
child 903 f712705bef65
merge
stage4/generate_c/generate_c.cc
--- a/README.build	Wed May 28 11:32:09 2014 +0200
+++ b/README.build	Sat Jul 05 14:10:28 2014 +0100
@@ -4,6 +4,7 @@
 
 1) Compiling under Linux
 ------------------------
+$ autoreconf -i
 $ ./configure
 $ make
 
--- a/lib/iec_std_lib.h	Wed May 28 11:32:09 2014 +0200
+++ b/lib/iec_std_lib.h	Sat Jul 05 14:10:28 2014 +0100
@@ -180,11 +180,36 @@
 /**********************************************/
 /* Time conversion to/from timespec functions */
 /**********************************************/
-
+/* NOTE: The following function was turned into a macro, so it could be used to initialize the initial value of TIME variables.
+ *       Since each macro parameter is evaluated several times, the macro may result in multiple function invocations if an expression
+ *       containing a function invocation is passed as a parameter. However, currently matiec only uses this conversion macro with 
+ *       constant literals, so it is safe to change it into a macro.
+ */
+/* NOTE: I (Mario - msousa@fe.up.pt) believe that the following function contains a bug when handling negative times.
+ *       The equivalent macro has this bug fixed.
+ *       e.g.;
+ *          T#3.8s
+ *       using the function, will result in a timespec of 3.8s !!!: 
+ *          tv_sec  =  4               <-----  1 *  3.8           is rounded up when converting a double to an int!
+ *          tv_nsec = -200 000 000     <-----  1 * (3.8 - 4)*1e9
+ * 
+ *         -T#3.8s
+ *       using the function, will result in a timespec of -11.8s !!!: 
+ *          tv_sec  = -4                 <-----  -1 *  3.8 is rounded down when converting a double to an int!
+ *          tv_nsec = -7 800 000 000     <-----  -1 * (3.8 - -4)*1e9
+ */
+/* NOTE: Due to the fact that the C compiler may round a tv_sec number away from zero, 
+ *       the following macro may result in a timespec that is not normalized, i.e. with a tv_sec > 0, and a tv_nsec < 0 !!!!
+ *       This is due to the rounding that C compiler applies when converting a (long double) to a (long int).
+ *       To produce normalized timespec's we need to use floor(), but we cannot call any library functions since we want this macro to be 
+ *       useable as a variable initializer.
+ *       VAR x : TIME = T#3.5h; END_VAR --->  IEC_TIME x = __time_to_timespec(1, 0, 0, 0, 3.5, 0);
+ */
+/*
 static inline IEC_TIMESPEC __time_to_timespec(int sign, double mseconds, double seconds, double minutes, double hours, double days) {
   IEC_TIMESPEC ts;
 
-  /* sign is 1 for positive values, -1 for negative time... */
+  // sign is 1 for positive values, -1 for negative time...
   long double total_sec = ((days*24 + hours)*60 + minutes)*60 + seconds + mseconds/1e3;
   if (sign >= 0) sign = 1; else sign = -1;
   ts.tv_sec = sign * (long int)total_sec;
@@ -192,8 +217,29 @@
 
   return ts;
 }
-
-
+*/
+/* NOTE: Unfortunately older versions of ANSI C (e.g. C99) do not allow explicit identification of elements in initializers
+ *         e.g.  {tv_sec = 1, tv_nsec = 300}
+ *       They are therefore commented out. This however means that any change to the definition of IEC_TIMESPEC may require this
+ *       macro to be updated too!
+ */
+#define ld long double
+#define __time_to_timespec(sign,mseconds,seconds,minutes,hours,days) \
+          ((IEC_TIMESPEC){\
+              /*tv_sec  =*/ ((long int)   (((sign>=0)?1:-1)*((((ld)days*24 + (ld)hours)*60 + (ld)minutes)*60 + (ld)seconds + (ld)mseconds/1e3))), \
+              /*tv_nsec =*/ ((long int)(( \
+                            ((long double)(((sign>=0)?1:-1)*((((ld)days*24 + (ld)hours)*60 + (ld)minutes)*60 + (ld)seconds + (ld)mseconds/1e3))) - \
+                            ((long int)   (((sign>=0)?1:-1)*((((ld)days*24 + (ld)hours)*60 + (ld)minutes)*60 + (ld)seconds + (ld)mseconds/1e3)))   \
+                            )*1e9))\
+        })
+#undef ld
+
+
+
+
+/* NOTE: The following function was turned into a macro, so it could be used to initialize the initial value of TOD (TIME_OF_DAY) variables */
+/* NOTE: many (but not all) of the same comments made regarding __time_to_timespec() are also valid here, so go and read those comments too!
+/*
 static inline IEC_TIMESPEC __tod_to_timespec(double seconds, double minutes, double hours) {
   IEC_TIMESPEC ts;
 
@@ -203,6 +249,18 @@
 
   return ts;
 }
+*/
+#define ld long double
+#define __tod_to_timespec(seconds,minutes,hours) \
+          ((IEC_TIMESPEC){\
+              /*tv_sec  =*/ ((long int)   ((((ld)hours)*60 + (ld)minutes)*60 + (ld)seconds)), \
+              /*tv_nsec =*/ ((long int)(( \
+                            ((long double)((((ld)hours)*60 + (ld)minutes)*60 + (ld)seconds)) - \
+                            ((long int)   ((((ld)hours)*60 + (ld)minutes)*60 + (ld)seconds))   \
+                            )*1e9))\
+        })
+#undef ld
+
 
 #define EPOCH_YEAR 1970
 #define SECONDS_PER_MINUTE 60
@@ -221,10 +279,10 @@
 typedef struct {
 	int tm_sec;			/* Seconds.	[0-60] (1 leap second) */
 	int tm_min;			/* Minutes.	[0-59] */
-	int tm_hour;		/* Hours.	[0-23] */
+	int tm_hour;			/* Hours.	[0-23] */
 	int tm_day;			/* Day.		[1-31] */
 	int tm_mon;			/* Month.	[0-11] */
-	int tm_year;		/* Year	*/
+	int tm_year;			/* Year	*/
 } tm;
 
 static inline tm convert_seconds_to_date_and_time(long int seconds) {
--- a/lib/iec_types.h	Wed May 28 11:32:09 2014 +0200
+++ b/lib/iec_types.h	Sat Jul 05 14:10:28 2014 +0100
@@ -29,6 +29,11 @@
 typedef float    IEC_REAL;
 typedef double   IEC_LREAL;
 
+/* WARNING: When editing the definition of IEC_TIMESPEC, take note that 
+ *          if the order of the two elements 'tv_sec' and 'tv_nsec' is changed, then the macros 
+ *          __time_to_timespec() and __tod_to_timespec() will need to be changed accordingly.
+ *          (these macros may be found in iec_std_lib.h)
+ */
 typedef struct {
     long int tv_sec;            /* Seconds.  */
     long int tv_nsec;           /* Nanoseconds.  */
--- a/lib/iec_types_all.h	Wed May 28 11:32:09 2014 +0200
+++ b/lib/iec_types_all.h	Sat Jul 05 14:10:28 2014 +0100
@@ -126,11 +126,12 @@
 __ANY(__DECLARE_IEC_TYPE)
 
 typedef struct {
-  __IEC_BOOL_t state;     // current step state. 0 : inative, 1: active
-  BOOL prev_state;  // previous step state. 0 : inative, 1: active
-  TIME elapsed_time;  // time since step is active
+  __IEC_BOOL_t X;  // state;  --> current step state. 0 : inative, 1: active.   We name it 'X' as it may be accessed from IEC 61131.3 code using stepname.X syntax!!
+  BOOL prev_state; // previous step state. 0 : inative, 1: active
+  __IEC_TIME_t T;  // elapsed_time;  --> time since step is active.   We name it 'T' as it may be accessed from IEC 61131.3 code using stepname.T syntax!!
 } STEP;
 
+
 typedef struct {
   BOOL stored;  // action storing state. 0 : not stored, 1: stored
   __IEC_BOOL_t state; // current action state. 0 : inative, 1: active
--- a/stage3/fill_candidate_datatypes.hh	Wed May 28 11:32:09 2014 +0200
+++ b/stage3/fill_candidate_datatypes.hh	Sat Jul 05 14:10:28 2014 +0100
@@ -242,7 +242,6 @@
     /********************************************/
     /* B 1.6 Sequential function chart elements */
     /********************************************/
-
     void *visit(transition_condition_c *symbol);
 
     /********************************/
--- a/stage3/narrow_candidate_datatypes.cc	Wed May 28 11:32:09 2014 +0200
+++ b/stage3/narrow_candidate_datatypes.cc	Sat Jul 05 14:10:28 2014 +0100
@@ -817,17 +817,16 @@
 /********************************************/
 /* B 1.6 Sequential function chart elements */
 /********************************************/
-
 void *narrow_candidate_datatypes_c::visit(transition_condition_c *symbol) {
-	if (symbol->candidate_datatypes.size() != 1)
-		return NULL;
-	symbol->datatype = symbol->candidate_datatypes[0];
+	// We can safely ask for a BOOL type, as even if the result is a SAFEBOOL, in that case it will aslo include BOOL as a possible datatype.
+	set_datatype(&get_datatype_info_c::bool_type_name /* datatype*/, symbol /* symbol */);
+
 	if (symbol->transition_condition_il != NULL) {
-		symbol->transition_condition_il->datatype = symbol->datatype;
+		set_datatype(symbol->datatype, symbol->transition_condition_il);
 		symbol->transition_condition_il->accept(*this);
 	}
 	if (symbol->transition_condition_st != NULL) {
-		symbol->transition_condition_st->datatype = symbol->datatype;
+		set_datatype(symbol->datatype, symbol->transition_condition_st);
 		symbol->transition_condition_st->accept(*this);
 	}
 	return NULL;
--- a/stage3/narrow_candidate_datatypes.hh	Wed May 28 11:32:09 2014 +0200
+++ b/stage3/narrow_candidate_datatypes.hh	Sat Jul 05 14:10:28 2014 +0100
@@ -222,7 +222,6 @@
     /********************************************/
     /* B 1.6 Sequential function chart elements */
     /********************************************/
-
     void *visit(transition_condition_c *symbol);
 
     /********************************/
--- a/stage3/print_datatypes_error.cc	Wed May 28 11:32:09 2014 +0200
+++ b/stage3/print_datatypes_error.cc	Sat Jul 05 14:10:28 2014 +0100
@@ -689,6 +689,18 @@
 }
 
 
+/********************************************/
+/* B 1.6 Sequential function chart elements */
+/********************************************/
+void *print_datatypes_error_c::visit(transition_condition_c *symbol) {
+	if (symbol->transition_condition_il != NULL)   symbol->transition_condition_il->accept(*this);
+	if (symbol->transition_condition_st != NULL)   symbol->transition_condition_st->accept(*this);
+
+	if (!get_datatype_info_c::is_type_valid(symbol->datatype))
+		STAGE3_ERROR(0, symbol, symbol, "Transition condition has invalid data type (should be BOOL).");
+	return NULL;
+}
+
 
 /********************************/
 /* B 1.7 Configuration elements */
@@ -1163,7 +1175,7 @@
 	symbol->expression->accept(*this);
 	if ((!get_datatype_info_c::is_type_valid(symbol->expression->datatype)) &&
 	    (symbol->expression->candidate_datatypes.size() > 0)) {
-		STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'IF' condition.");
+		STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'IF' condition (should be BOOL).");
 	}
 	if (NULL != symbol->statement_list)
 		symbol->statement_list->accept(*this);
@@ -1178,7 +1190,7 @@
 	symbol->expression->accept(*this);
 	if ((!get_datatype_info_c::is_type_valid(symbol->expression->datatype)) &&
 	    (symbol->expression->candidate_datatypes.size() > 0)) {
-		STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'ELSIF' condition.");
+		STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'ELSIF' condition (should be BOOL).");
 	}
 	if (NULL != symbol->statement_list)
 		symbol->statement_list->accept(*this);
--- a/stage3/print_datatypes_error.hh	Wed May 28 11:32:09 2014 +0200
+++ b/stage3/print_datatypes_error.hh	Sat Jul 05 14:10:28 2014 +0100
@@ -203,6 +203,11 @@
     /**********************/
     void *visit(program_declaration_c *symbol);
 
+    /********************************************/
+    /* B 1.6 Sequential function chart elements */
+    /********************************************/
+    void *visit(transition_condition_c *symbol);
+
     /********************************/
     /* B 1.7 Configuration elements */
     /********************************/
--- a/stage4/generate_c/generate_c.cc	Wed May 28 11:32:09 2014 +0200
+++ b/stage4/generate_c/generate_c.cc	Sat Jul 05 14:10:28 2014 +0100
@@ -386,131 +386,6 @@
 /***********************************************************************/
 /***********************************************************************/
 /***********************************************************************/
-/* 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!               */
--- a/stage4/generate_c/generate_c_sfc.cc	Wed May 28 11:32:09 2014 +0200
+++ b/stage4/generate_c/generate_c_sfc.cc	Sat Jul 05 14:10:28 2014 +0100
@@ -110,10 +110,8 @@
     void print_step_argument(symbol_c *step_name, const char* argument, bool setter=false) {
       print_variable_prefix();
       if (setter) s4o.print(",");
-      s4o.print("__step_list[");
-      s4o.print(SFC_STEP_ACTION_PREFIX);
-      step_name->accept(*this);
-      s4o.print("].");
+      step_name->accept(*this);  // in the generated C code, the 'step_name' will have been previously #define'd as equiv to '__step_list[<step_number>]", so now we simply print out the name!
+      s4o.print(".");
       s4o.print(argument);
     }
 
@@ -135,7 +133,7 @@
       s4o.print(s4o.indent_spaces);
       s4o.print(SET_VAR);
       s4o.print("(");
-      print_step_argument(step_name, "state", true);
+      print_step_argument(step_name, "X", true);
       s4o.print(",,0);\n");
     }
     
@@ -143,9 +141,9 @@
       s4o.print(s4o.indent_spaces);
       s4o.print(SET_VAR);
       s4o.print("(");
-      print_step_argument(step_name, "state", true);
+      print_step_argument(step_name, "X", true);
       s4o.print(",,1);\n" + s4o.indent_spaces);
-      print_step_argument(step_name, "elapsed_time");
+      print_step_argument(step_name, "T.value");
       s4o.print(" = __time_to_timespec(1, 0, 0, 0, 0, 0);\n");
     }
     
@@ -166,21 +164,21 @@
             s4o.print(s4o.indent_spaces + "char activated = ");
             s4o.print(GET_VAR);
             s4o.print("(");
-            print_step_argument(current_step, "state");
+            print_step_argument(current_step, "X");
             s4o.print(") && !");
             print_step_argument(current_step, "prev_state");
             s4o.print(";\n");
             s4o.print(s4o.indent_spaces + "char desactivated = !");
             s4o.print(GET_VAR);
             s4o.print("(");
-            print_step_argument(current_step, "state");
+            print_step_argument(current_step, "X");
             s4o.print(") && ");
             print_step_argument(current_step, "prev_state");
             s4o.print(";\n");
             s4o.print(s4o.indent_spaces + "char active = ");
             s4o.print(GET_VAR);
             s4o.print("(");
-            print_step_argument(current_step, "state");
+            print_step_argument(current_step, "X");
             s4o.print(");\n");
             symbol->action_association_list->accept(*this);
             s4o.indent_left();
@@ -207,21 +205,21 @@
             s4o.print(s4o.indent_spaces + "activated = ");
             s4o.print(GET_VAR);
             s4o.print("(");
-            print_step_argument(current_step, "state");
+            print_step_argument(current_step, "X");
             s4o.print(") && !");
             print_step_argument(current_step, "prev_state");
             s4o.print(";\n");
             s4o.print(s4o.indent_spaces + "desactivated = !");
             s4o.print(GET_VAR);
             s4o.print("(");
-            print_step_argument(current_step, "state");
+            print_step_argument(current_step, "X");
             s4o.print(") && ");
             print_step_argument(current_step, "prev_state");
             s4o.print(";\n");
             s4o.print(s4o.indent_spaces + "active = ");
             s4o.print(GET_VAR);
             s4o.print("(");
-            print_step_argument(current_step, "state");
+            print_step_argument(current_step, "X");
             s4o.print(");\n");
             symbol->action_association_list->accept(*this);
             s4o.indent_left();
@@ -437,7 +435,7 @@
           case transitiontest_sg:
             s4o.print(GET_VAR);
             s4o.print("(");
-            print_step_argument(symbol->step_name, "state");
+            print_step_argument(symbol->step_name, "X");
             s4o.print(")");
             break;
           case stepset_sg:
@@ -462,7 +460,7 @@
           for(int i = 0; i < symbol->n; i++) {
             s4o.print(GET_VAR);
             s4o.print("(");
-            print_step_argument(symbol->elements[i], "state");
+            print_step_argument(symbol->elements[i], "X");
             s4o.print(")");
             if (i < symbol->n - 1) {
               s4o.print(" && ");
@@ -507,7 +505,7 @@
             s4o.print(s4o.indent_spaces + "if (");
             s4o.print(GET_VAR);
             s4o.print("(");
-            print_step_argument(current_step, "state");
+            print_step_argument(current_step, "X");
             s4o.print(")) {\n");
             s4o.indent_right();
             s4o.print(s4o.indent_spaces);
@@ -545,7 +543,7 @@
             }
             else if (strcmp(qualifier, "D") == 0 || strcmp(qualifier, "L") == 0) {
               s4o.print("active && __time_cmp(");
-              print_step_argument(current_step, "elapsed_time");
+              print_step_argument(current_step, "T.value");
               s4o.print(", ");
               symbol->action_time->accept(*this);
               if (strcmp(qualifier, "D") == 0) {
@@ -744,20 +742,20 @@
       s4o.print(GET_VAR);
       s4o.print("(");
       print_variable_prefix();
-      s4o.print("__step_list[i].state);\n");
+      s4o.print("__step_list[i].X);\n");
       s4o.print(s4o.indent_spaces + "if (");
       s4o.print(GET_VAR);
       s4o.print("(");
       print_variable_prefix();
-      s4o.print("__step_list[i].state)) {\n");
+      s4o.print("__step_list[i].X)) {\n");
       s4o.indent_right();
       s4o.print(s4o.indent_spaces);
       print_variable_prefix();
 //      s4o.print("__step_list[i].elapsed_time = __time_add(__BOOL_LITERAL(TRUE), NULL, ");
 //      s4o.print("__step_list[i].elapsed_time = ADD_TIME(__BOOL_LITERAL(TRUE), NULL, ");
-      s4o.print("__step_list[i].elapsed_time = __time_add(");
-      print_variable_prefix();
-      s4o.print("__step_list[i].elapsed_time, elapsed_time);\n");
+      s4o.print("__step_list[i].T.value = __time_add(");
+      print_variable_prefix();
+      s4o.print("__step_list[i].T.value, elapsed_time);\n");
       s4o.indent_left();
       s4o.print(s4o.indent_spaces + "}\n");
       s4o.indent_left();
--- a/stage4/generate_c/generate_c_sfcdecl.cc	Wed May 28 11:32:09 2014 +0200
+++ b/stage4/generate_c/generate_c_sfcdecl.cc	Sat Jul 05 14:10:28 2014 +0100
@@ -252,11 +252,17 @@
           print_variable_prefix();
           s4o.print(",__step_list[");
           s4o.print(step_number);
-          s4o.print("].state,,1);\n");
+          s4o.print("].X,,1);\n");
           step_number++;
           break;
         case stepdef_sd:
           s4o.print("#define ");
+          symbol->step_name->accept(*this);
+          s4o.print(" __step_list[");
+          s4o.print(step_number);
+          s4o.print("]\n");
+
+          s4o.print("#define ");
           s4o.print(SFC_STEP_ACTION_PREFIX);
           symbol->step_name->accept(*this);
           s4o.print(" ");
@@ -266,6 +272,10 @@
           break;
         case stepundef_sd:
           s4o.print("#undef ");
+          symbol->step_name->accept(*this);
+          s4o.print("\n");
+
+          s4o.print("#undef ");
           s4o.print(SFC_STEP_ACTION_PREFIX);
           symbol->step_name->accept(*this);
           s4o.print("\n");
@@ -289,6 +299,12 @@
           break;
         case stepdef_sd:
           s4o.print("#define ");
+          symbol->step_name->accept(*this);
+          s4o.print(" __step_list[");
+          s4o.print(step_number);
+          s4o.print("]\n");
+
+          s4o.print("#define ");
           s4o.print(SFC_STEP_ACTION_PREFIX);
           symbol->step_name->accept(*this);
           s4o.print(" ");
@@ -298,6 +314,10 @@
           break;
         case stepundef_sd:
           s4o.print("#undef ");
+          symbol->step_name->accept(*this);
+          s4o.print("\n");
+
+          s4o.print("#undef ");
           s4o.print(SFC_STEP_ACTION_PREFIX);
           symbol->step_name->accept(*this);
           s4o.print("\n");
--- a/stage4/generate_c/generate_c_st.cc	Wed May 28 11:32:09 2014 +0200
+++ b/stage4/generate_c/generate_c_st.cc	Sat Jul 05 14:10:28 2014 +0100
@@ -211,8 +211,7 @@
     symbol->accept(*this);
     s4o.print(",");
     s4o.print(",");    
-  }
-  else {
+  } else {
     print_variable_prefix();
     s4o.print(",");    
     wanted_variablegeneration = complextype_base_vg;
@@ -334,7 +333,19 @@
   switch (wanted_variablegeneration) {
     case complextype_base_vg:
       symbol->record_variable->accept(*this);
-      if ( get_datatype_info_c::is_function_block(symbol->record_variable->datatype)) {
+      /* NOTE: The following test includes a special case for SFC Steps. They are currently mapped onto a C data structure
+       *        that does not follow the standard IEC_<typename> pattern used for user defined structure datatypes 
+       *        (i.e. it does not include the 'values' and 'flag' structure 
+       *        elements that are tested by __GET_VAR and __SET_VAR acessor macros defined in acessor.h). However, the
+       *        STEP.T and STEP.X elements of this step structure are of the IEC_BOOL and IEC_TIME datatypes, and are 
+       *        actually structures that do have the 'value' and 'flags' elements. So, it is safe to say that any  variable
+       *        that is a STEPname is not of a complex type, as its .T and .X elements are and can later be safely accessed
+       *        using the __SET_VAR and __GET_VAR macros.
+       * 
+       *        For the above reason, a STEP must be handled as a FB, i.e. it does NOT contain the 'flags' and 'value' elements!
+       */
+      if (   get_datatype_info_c::is_function_block(symbol->record_variable->datatype)
+          || get_datatype_info_c::is_sfc_step      (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)))
@@ -346,7 +357,9 @@
       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!
+      // the following condition MUST be a negation of the above condition used in the 'case complextype_base_vg:'
+      if (!(   get_datatype_info_c::is_function_block(symbol->record_variable->datatype)     // if the record variable is not a FB... 
+            || get_datatype_info_c::is_sfc_step      (symbol->record_variable->datatype))) { // ...nor an SFC step name, then it will certainly be a structure!
         s4o.print(".");
         symbol->field_selector->accept(*this);
       }
--- a/stage4/generate_c/generate_var_list.cc	Wed May 28 11:32:09 2014 +0200
+++ b/stage4/generate_c/generate_var_list.cc	Sat Jul 05 14:10:28 2014 +0100
@@ -857,7 +857,7 @@
       print_symbol_list();
       s4o.print("__step_list[");
       print_step_number();
-      s4o.print("].state;BOOL;\n");
+      s4o.print("].X;BOOL;\n");
       step_number++;
       return NULL;
     }
@@ -873,7 +873,7 @@
       print_symbol_list();
       s4o.print("__step_list[");
       print_step_number();
-      s4o.print("].state;BOOL;\n");
+      s4o.print("].X;BOOL;\n");
       step_number++;
       return NULL;
     }