# HG changeset patch # User mjsousa # Date 1404565828 -3600 # Node ID 38dca2e264b65777dc0dcb611f19c0a7c19c2b3e # Parent 6a3964be6a2992f580c0429e23b367815e44eb31# Parent 39086e324665fa818168f527dbd99d014cd4b8de merge diff -r 39086e324665 -r 38dca2e264b6 README.build --- 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 diff -r 39086e324665 -r 38dca2e264b6 lib/iec_std_lib.h --- 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) { diff -r 39086e324665 -r 38dca2e264b6 lib/iec_types.h --- 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. */ diff -r 39086e324665 -r 38dca2e264b6 lib/iec_types_all.h --- 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 diff -r 39086e324665 -r 38dca2e264b6 stage3/fill_candidate_datatypes.hh --- 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); /********************************/ diff -r 39086e324665 -r 38dca2e264b6 stage3/narrow_candidate_datatypes.cc --- 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; diff -r 39086e324665 -r 38dca2e264b6 stage3/narrow_candidate_datatypes.hh --- 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); /********************************/ diff -r 39086e324665 -r 38dca2e264b6 stage3/print_datatypes_error.cc --- 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); diff -r 39086e324665 -r 38dca2e264b6 stage3/print_datatypes_error.hh --- 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 */ /********************************/ diff -r 39086e324665 -r 38dca2e264b6 stage4/generate_c/generate_c.cc --- 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! */ diff -r 39086e324665 -r 38dca2e264b6 stage4/generate_c/generate_c_sfc.cc --- 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[]", 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(); diff -r 39086e324665 -r 38dca2e264b6 stage4/generate_c/generate_c_sfcdecl.cc --- 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"); diff -r 39086e324665 -r 38dca2e264b6 stage4/generate_c/generate_c_st.cc --- 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_ 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); } diff -r 39086e324665 -r 38dca2e264b6 stage4/generate_c/generate_var_list.cc --- 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; }