author | mjsousa |
Sat, 18 Mar 2017 22:02:14 +0000 | |
changeset 1035 | 0a58b2720976 |
parent 1034 | f802b5494d56 (diff) |
parent 997 | 7518955c875a (current diff) |
child 1036 | 1000db86d0af |
--- a/README.build Thu Mar 12 16:36:33 2015 +0100 +++ b/README.build Sat Mar 18 22:02:14 2017 +0000 @@ -12,6 +12,8 @@ 2) Cross-Compiling under Linux, for Windows ------------------------------------------- $ ./configure --host=i586-pc-mingw32 +(or, to use static linking, which does not require installing any mingw dll's on windows) +$ ./configure --host=i586-pc-mingw32 LDFLAGS="-static" $ make
--- a/absyntax/absyntax.def Thu Mar 12 16:36:33 2015 +0100 +++ b/absyntax/absyntax.def Sat Mar 18 22:02:14 2017 +0000 @@ -267,6 +267,7 @@ SYM_REF0(lword_type_name_c) SYM_REF0(string_type_name_c) SYM_REF0(wstring_type_name_c) +SYM_REF0(void_type_name_c) /* a non-standard extension! */ /*****************************************************************/ /* Keywords defined in "Safety Software Technical Specification" */
--- a/absyntax/absyntax.hh Thu Mar 12 16:36:33 2015 +0100 +++ b/absyntax/absyntax.hh Sat Mar 18 22:02:14 2017 +0000 @@ -148,6 +148,10 @@ /* comparison operator */ bool operator==(const const_value_c cv) {return ((_int64==cv._int64) && (_uint64==cv._uint64) && (_real64==cv._real64) && (_bool==cv._bool));} + + /* return true if at least one of the const values (int, real, ...) is a valid const value */ + bool is_const(void) + {return (_int64.is_valid() || _uint64.is_valid() || _real64.is_valid() || _bool.is_valid());} };
--- a/absyntax_utils/get_datatype_info.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/absyntax_utils/get_datatype_info.cc Sat Mar 18 22:02:14 2017 +0000 @@ -127,6 +127,8 @@ void *visit(safestring_type_name_c *symbol) {return (void *)symbol;}; void *visit(safewstring_type_name_c *symbol) {return (void *)symbol;}; + void *visit(void_type_name_c *symbol) {return (void *)symbol;}; + /********************************/ /* B 1.3.3 - Derived data types */ /********************************/ @@ -260,6 +262,8 @@ void *visit(safestring_type_name_c *symbol) {return (void *)"SAFESTRING"; }; void *visit(safewstring_type_name_c *symbol) {return (void *)"SAFEWSTRING"; }; + void *visit(void_type_name_c *symbol) {return (void *)"VOID"; }; + /********************************/ /* B.1.3.2 - Generic data types */ /********************************/ @@ -1352,6 +1356,21 @@ + +bool get_datatype_info_c::is_VOID(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(void_type_name_c)) {return true;} + return false; +} + + + + + + + + + /* Can't we do away with this?? */ bool get_datatype_info_c::is_ANY_REAL_literal(symbol_c *type_symbol) { if (type_symbol == NULL) {return true;} /* Please make sure things will work correctly before changing this to false!! */
--- a/absyntax_utils/get_datatype_info.hh Thu Mar 12 16:36:33 2015 +0100 +++ b/absyntax_utils/get_datatype_info.hh Sat Mar 18 22:02:14 2017 +0000 @@ -165,6 +165,8 @@ static bool is_ANY_SAFESTRING (symbol_c *type_symbol); static bool is_ANY_STRING_compatible (symbol_c *type_symbol); + // A non-standard extension --> data type 'VOID' (used for functions that do not return any data) + static bool is_VOID (symbol_c *type_symbol);
--- a/absyntax_utils/search_base_type.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/absyntax_utils/search_base_type.cc Sat Mar 18 22:02:14 2017 +0000 @@ -184,6 +184,8 @@ void *search_base_type_c::visit(string_type_name_c *symbol) {return (void *)symbol;} void *search_base_type_c::visit(wstring_type_name_c *symbol) {return (void *)symbol;} +/* A non standard datatype! */ +void *search_base_type_c::visit(void_type_name_c *symbol) {return (void *)symbol;} /******************************************************/ /* Extensions to the base standard as defined in */
--- a/absyntax_utils/search_base_type.hh Thu Mar 12 16:36:33 2015 +0100 +++ b/absyntax_utils/search_base_type.hh Sat Mar 18 22:02:14 2017 +0000 @@ -141,6 +141,7 @@ void *visit(lword_type_name_c *symbol); void *visit(string_type_name_c *symbol); void *visit(wstring_type_name_c *symbol); + void *visit(void_type_name_c *symbol); /* A non standard datatype! */ /******************************************************/ /* Extensions to the base standard as defined in */
--- a/absyntax_utils/search_var_instance_decl.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/absyntax_utils/search_var_instance_decl.cc Sat Mar 18 22:02:14 2017 +0000 @@ -214,6 +214,12 @@ return NULL; } +/* EN : BOOL */ +void *search_var_instance_decl_c::visit(en_param_declaration_c *symbol) { + if (compare_identifiers(symbol->name, search_name) == 0) + return symbol->type_decl; + return NULL; +} /* VAR [CONSTANT] var_init_decl_list END_VAR */ /* option -> may be NULL ! */
--- a/absyntax_utils/search_var_instance_decl.hh Thu Mar 12 16:36:33 2015 +0100 +++ b/absyntax_utils/search_var_instance_decl.hh Sat Mar 18 22:02:14 2017 +0000 @@ -171,6 +171,8 @@ void *visit(input_output_declarations_c *symbol); /* ENO : BOOL */ void *visit(eno_param_declaration_c *symbol); + /* EN : BOOL */ + void *visit(en_param_declaration_c *symbol); /* VAR [CONSTANT] var_init_decl_list END_VAR */ /* option -> may be NULL ! */ /* helper symbol for input_declarations */
--- a/configure.ac Thu Mar 12 16:36:33 2015 +0100 +++ b/configure.ac Sat Mar 18 22:02:14 2017 +0000 @@ -42,6 +42,10 @@ (exit 1); exit 1; fi +if test "x$LEX" == "x:"; then + AC_MSG_ERROR("flex/lex is missing") +fi + # Checks for header files. AC_CHECK_HEADERS([float.h limits.h stdint.h stdlib.h string.h strings.h sys/timeb.h unistd.h])
--- a/lib/C/accessor.h Thu Mar 12 16:36:33 2015 +0100 +++ b/lib/C/accessor.h Sat Mar 18 22:02:14 2017 +0000 @@ -125,7 +125,7 @@ #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();\ + {extern IEC_BYTE __IS_GLOBAL_##name##_FORCED(void);\ 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)\
--- a/lib/C/iec_std_FB.h Thu Mar 12 16:36:33 2015 +0100 +++ b/lib/C/iec_std_FB.h Sat Mar 18 22:02:14 2017 +0000 @@ -6,15 +6,26 @@ /* NOTE: The code in this file was generated by iec2c (i.e. matiec C compiler), using as source * the *.txt files in the 'lib' directory. - * The only 'manual' change was to the function prototypes, that were all changed to become 'static'. - * e.g.: static void R_TRIG_init__(...) - * ^^^^^^ + * The only 'manual' change was: + * - to merge the generated .h and .c files into this single file + * - to remove the forward declarations of the functions + * - to change the function prototypes to become 'static'. + * e.g.: static void R_TRIG_init__(...) + * ^^^^^^ * * NOTE: If the structure of the C code generated by iec2c (matiec) should change, then this C 'library' * file will need to be recompiled. * The correct way of going about this would be to have this file be automatically generated during * the build process (i.e. after compiling matiec), but we will leave this for later if it ever * becomes necessary. + * + * WARNING: There are 2 versions of this file: + * - file: iec_std_FB.h + * Version to be used when the EN and ENO parameters are implicitly generated + * for all functions and function blocks + * - file: iec_std_FB_no_ENENO.h + * Version to be used when the EN and ENO parameters are NOT implicitly generated + * for all functions and function blocks */ #ifndef _IEC_STD_FB_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/C/iec_std_FB_no_ENENO.h Sat Mar 18 22:02:14 2017 +0000 @@ -0,0 +1,1548 @@ + + +/**** + * IEC 61131-3 standard function block library + */ + +/* NOTE: The code in this file was generated by iec2c (i.e. matiec C compiler), using as source + * the *.txt files in the 'lib' directory. + * The only 'manual' change was: + * - to merge the generated .h and .c files into this single file + * - to remove the forward declarations of the functions + * - to change the function prototypes to become 'static'. + * e.g.: static void R_TRIG_init__(...) + * ^^^^^^ + * + * NOTE: If the structure of the C code generated by iec2c (matiec) should change, then this C 'library' + * file will need to be recompiled. + * The correct way of going about this would be to have this file be automatically generated during + * the build process (i.e. after compiling matiec), but we will leave this for later if it ever + * becomes necessary. + * + * WARNING: There are 2 versions of this file: + * - file: iec_std_FB.h + * Version to be used when the EN and ENO parameters are implicitly generated + * for all functions and function blocks + * - file: iec_std_FB_no_ENENO.h + * Version to be used when the EN and ENO parameters are NOT implicitly generated + * for all functions and function blocks + */ + +#ifndef _IEC_STD_FB_H +#define _IEC_STD_FB_H + + +#include "accessor.h" + + +// FUNCTION_BLOCK R_TRIG +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CLK) + __DECLARE_VAR(BOOL,Q) + + // FB private variables - TEMP, private and located variables + __DECLARE_VAR(BOOL,M) + +} R_TRIG; + +// FUNCTION_BLOCK F_TRIG +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CLK) + __DECLARE_VAR(BOOL,Q) + + // FB private variables - TEMP, private and located variables + __DECLARE_VAR(BOOL,M) + +} F_TRIG; + +// FUNCTION_BLOCK SR +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,S1) + __DECLARE_VAR(BOOL,R) + __DECLARE_VAR(BOOL,Q1) + + // FB private variables - TEMP, private and located variables + +} SR; + +// FUNCTION_BLOCK RS +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,S) + __DECLARE_VAR(BOOL,R1) + __DECLARE_VAR(BOOL,Q1) + + // FB private variables - TEMP, private and located variables + +} RS; + +// FUNCTION_BLOCK CTU +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CU) + __DECLARE_VAR(BOOL,R) + __DECLARE_VAR(INT,PV) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(INT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CU_T; + +} CTU; + +// FUNCTION_BLOCK CTU_DINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CU) + __DECLARE_VAR(BOOL,R) + __DECLARE_VAR(DINT,PV) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(DINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CU_T; + +} CTU_DINT; + +// FUNCTION_BLOCK CTU_LINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CU) + __DECLARE_VAR(BOOL,R) + __DECLARE_VAR(LINT,PV) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(LINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CU_T; + +} CTU_LINT; + +// FUNCTION_BLOCK CTU_UDINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CU) + __DECLARE_VAR(BOOL,R) + __DECLARE_VAR(UDINT,PV) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(UDINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CU_T; + +} CTU_UDINT; + +// FUNCTION_BLOCK CTU_ULINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CU) + __DECLARE_VAR(BOOL,R) + __DECLARE_VAR(ULINT,PV) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(ULINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CU_T; + +} CTU_ULINT; + +// FUNCTION_BLOCK CTD +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CD) + __DECLARE_VAR(BOOL,LD) + __DECLARE_VAR(INT,PV) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(INT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CD_T; + +} CTD; + +// FUNCTION_BLOCK CTD_DINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CD) + __DECLARE_VAR(BOOL,LD) + __DECLARE_VAR(DINT,PV) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(DINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CD_T; + +} CTD_DINT; + +// FUNCTION_BLOCK CTD_LINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CD) + __DECLARE_VAR(BOOL,LD) + __DECLARE_VAR(LINT,PV) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(LINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CD_T; + +} CTD_LINT; + +// FUNCTION_BLOCK CTD_UDINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CD) + __DECLARE_VAR(BOOL,LD) + __DECLARE_VAR(UDINT,PV) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(UDINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CD_T; + +} CTD_UDINT; + +// FUNCTION_BLOCK CTD_ULINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CD) + __DECLARE_VAR(BOOL,LD) + __DECLARE_VAR(ULINT,PV) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(ULINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CD_T; + +} CTD_ULINT; + +// FUNCTION_BLOCK CTUD +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CU) + __DECLARE_VAR(BOOL,CD) + __DECLARE_VAR(BOOL,R) + __DECLARE_VAR(BOOL,LD) + __DECLARE_VAR(INT,PV) + __DECLARE_VAR(BOOL,QU) + __DECLARE_VAR(BOOL,QD) + __DECLARE_VAR(INT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CD_T; + R_TRIG CU_T; + +} CTUD; + +// FUNCTION_BLOCK CTUD_DINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CU) + __DECLARE_VAR(BOOL,CD) + __DECLARE_VAR(BOOL,R) + __DECLARE_VAR(BOOL,LD) + __DECLARE_VAR(DINT,PV) + __DECLARE_VAR(BOOL,QU) + __DECLARE_VAR(BOOL,QD) + __DECLARE_VAR(DINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CD_T; + R_TRIG CU_T; + +} CTUD_DINT; + +// FUNCTION_BLOCK CTUD_LINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CU) + __DECLARE_VAR(BOOL,CD) + __DECLARE_VAR(BOOL,R) + __DECLARE_VAR(BOOL,LD) + __DECLARE_VAR(LINT,PV) + __DECLARE_VAR(BOOL,QU) + __DECLARE_VAR(BOOL,QD) + __DECLARE_VAR(LINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CD_T; + R_TRIG CU_T; + +} CTUD_LINT; + +// FUNCTION_BLOCK CTUD_UDINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CU) + __DECLARE_VAR(BOOL,CD) + __DECLARE_VAR(BOOL,R) + __DECLARE_VAR(BOOL,LD) + __DECLARE_VAR(UDINT,PV) + __DECLARE_VAR(BOOL,QU) + __DECLARE_VAR(BOOL,QD) + __DECLARE_VAR(UDINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CD_T; + R_TRIG CU_T; + +} CTUD_UDINT; + +// FUNCTION_BLOCK CTUD_ULINT +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CU) + __DECLARE_VAR(BOOL,CD) + __DECLARE_VAR(BOOL,R) + __DECLARE_VAR(BOOL,LD) + __DECLARE_VAR(ULINT,PV) + __DECLARE_VAR(BOOL,QU) + __DECLARE_VAR(BOOL,QD) + __DECLARE_VAR(ULINT,CV) + + // FB private variables - TEMP, private and located variables + R_TRIG CD_T; + R_TRIG CU_T; + +} CTUD_ULINT; + +// FUNCTION_BLOCK TP +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,IN) + __DECLARE_VAR(TIME,PT) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(TIME,ET) + + // FB private variables - TEMP, private and located variables + __DECLARE_VAR(SINT,STATE) + __DECLARE_VAR(BOOL,PREV_IN) + __DECLARE_VAR(TIME,CURRENT_TIME) + __DECLARE_VAR(TIME,START_TIME) + +} TP; + +// FUNCTION_BLOCK TON +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,IN) + __DECLARE_VAR(TIME,PT) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(TIME,ET) + + // FB private variables - TEMP, private and located variables + __DECLARE_VAR(SINT,STATE) + __DECLARE_VAR(BOOL,PREV_IN) + __DECLARE_VAR(TIME,CURRENT_TIME) + __DECLARE_VAR(TIME,START_TIME) + +} TON; + +// FUNCTION_BLOCK TOF +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,IN) + __DECLARE_VAR(TIME,PT) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(TIME,ET) + + // FB private variables - TEMP, private and located variables + __DECLARE_VAR(SINT,STATE) + __DECLARE_VAR(BOOL,PREV_IN) + __DECLARE_VAR(TIME,CURRENT_TIME) + __DECLARE_VAR(TIME,START_TIME) + +} TOF; + +// FUNCTION_BLOCK DERIVATIVE +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,RUN) + __DECLARE_VAR(REAL,XIN) + __DECLARE_VAR(TIME,CYCLE) + __DECLARE_VAR(REAL,XOUT) + + // FB private variables - TEMP, private and located variables + __DECLARE_VAR(REAL,X1) + __DECLARE_VAR(REAL,X2) + __DECLARE_VAR(REAL,X3) + +} DERIVATIVE; + +// FUNCTION_BLOCK HYSTERESIS +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(REAL,XIN1) + __DECLARE_VAR(REAL,XIN2) + __DECLARE_VAR(REAL,EPS) + __DECLARE_VAR(BOOL,Q) + + // FB private variables - TEMP, private and located variables + +} HYSTERESIS; + +// FUNCTION_BLOCK INTEGRAL +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,RUN) + __DECLARE_VAR(BOOL,R1) + __DECLARE_VAR(REAL,XIN) + __DECLARE_VAR(REAL,X0) + __DECLARE_VAR(TIME,CYCLE) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(REAL,XOUT) + + // FB private variables - TEMP, private and located variables + +} INTEGRAL; + +// FUNCTION_BLOCK PID +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,AUTO) + __DECLARE_VAR(REAL,PV) + __DECLARE_VAR(REAL,SP) + __DECLARE_VAR(REAL,X0) + __DECLARE_VAR(REAL,KP) + __DECLARE_VAR(REAL,TR) + __DECLARE_VAR(REAL,TD) + __DECLARE_VAR(TIME,CYCLE) + __DECLARE_VAR(REAL,XOUT) + + // FB private variables - TEMP, private and located variables + __DECLARE_VAR(REAL,ERROR) + INTEGRAL ITERM; + DERIVATIVE DTERM; + +} PID; + +// FUNCTION_BLOCK RAMP +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,RUN) + __DECLARE_VAR(REAL,X0) + __DECLARE_VAR(REAL,X1) + __DECLARE_VAR(TIME,TR) + __DECLARE_VAR(TIME,CYCLE) + __DECLARE_VAR(BOOL,BUSY) + __DECLARE_VAR(REAL,XOUT) + + // FB private variables - TEMP, private and located variables + __DECLARE_VAR(REAL,XI) + __DECLARE_VAR(TIME,T) + +} RAMP; + +// FUNCTION_BLOCK RTC +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,IN) + __DECLARE_VAR(DT,PDT) + __DECLARE_VAR(BOOL,Q) + __DECLARE_VAR(DT,CDT) + + // FB private variables - TEMP, private and located variables + __DECLARE_VAR(BOOL,PREV_IN) + __DECLARE_VAR(TIME,OFFSET) + __DECLARE_VAR(DT,CURRENT_TIME) + +} RTC; + +// FUNCTION_BLOCK SEMA +// Data part +typedef struct { + // FB Interface - IN, OUT, IN_OUT variables + __DECLARE_VAR(BOOL,CLAIM) + __DECLARE_VAR(BOOL,RELEASE) + __DECLARE_VAR(BOOL,BUSY) + + // FB private variables - TEMP, private and located variables + __DECLARE_VAR(BOOL,Q_INTERNAL) + +} SEMA; + + + + +static void R_TRIG_init__(R_TRIG *data__, BOOL retain) { + __INIT_VAR(data__->CLK,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->M,__BOOL_LITERAL(FALSE),1) +} + +// Code part +static void R_TRIG_body__(R_TRIG *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->,Q,,(__GET_VAR(data__->CLK,) && !(__GET_VAR(data__->M,)))); +__SET_VAR(data__->,M,,__GET_VAR(data__->CLK,)); + +goto __end; + +__end: + return; +} // R_TRIG_body__() + + + + + +static void F_TRIG_init__(F_TRIG *data__, BOOL retain) { + __INIT_VAR(data__->CLK,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->M,__BOOL_LITERAL(FALSE),1) +} + +// Code part +static void F_TRIG_body__(F_TRIG *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->,Q,,(!(__GET_VAR(data__->CLK,)) && !(__GET_VAR(data__->M,)))); +__SET_VAR(data__->,M,,!(__GET_VAR(data__->CLK,))); + +goto __end; + +__end: + return; +} // F_TRIG_body__() + + + + + +static void SR_init__(SR *data__, BOOL retain) { + __INIT_VAR(data__->S1,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->Q1,__BOOL_LITERAL(FALSE),retain) +} + +// Code part +static void SR_body__(SR *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->,Q1,,(__GET_VAR(data__->S1,) || (!(__GET_VAR(data__->R,)) && __GET_VAR(data__->Q1,)))); + +goto __end; + +__end: + return; +} // SR_body__() + + + + + +static void RS_init__(RS *data__, BOOL retain) { + __INIT_VAR(data__->S,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R1,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->Q1,__BOOL_LITERAL(FALSE),retain) +} + +// Code part +static void RS_body__(RS *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->,Q1,,(!(__GET_VAR(data__->R1,)) && (__GET_VAR(data__->S,) || __GET_VAR(data__->Q1,)))); + +goto __end; + +__end: + return; +} // RS_body__() + + + + + +static void CTU_init__(CTU *data__, BOOL retain) { + __INIT_VAR(data__->CU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CU_T,retain); +} + +// Code part +static void CTU_body__(CTU *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CU_T.,CLK,,__GET_VAR(data__->CU,)); +R_TRIG_body__(&data__->CU_T); +if (__GET_VAR(data__->R,)) { + __SET_VAR(data__->,CV,,0); +} else if ((__GET_VAR(data__->CU_T.Q,) && (__GET_VAR(data__->CV,) < __GET_VAR(data__->PV,)))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) + 1)); +}; +__SET_VAR(data__->,Q,,(__GET_VAR(data__->CV,) >= __GET_VAR(data__->PV,))); + +goto __end; + +__end: + return; +} // CTU_body__() + + + + + +static void CTU_DINT_init__(CTU_DINT *data__, BOOL retain) { + __INIT_VAR(data__->CU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CU_T,retain); +} + +// Code part +static void CTU_DINT_body__(CTU_DINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CU_T.,CLK,,__GET_VAR(data__->CU,)); +R_TRIG_body__(&data__->CU_T); +if (__GET_VAR(data__->R,)) { + __SET_VAR(data__->,CV,,0); +} else if ((__GET_VAR(data__->CU_T.Q,) && (__GET_VAR(data__->CV,) < __GET_VAR(data__->PV,)))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) + 1)); +}; +__SET_VAR(data__->,Q,,(__GET_VAR(data__->CV,) >= __GET_VAR(data__->PV,))); + +goto __end; + +__end: + return; +} // CTU_DINT_body__() + + + + + +static void CTU_LINT_init__(CTU_LINT *data__, BOOL retain) { + __INIT_VAR(data__->CU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CU_T,retain); +} + +// Code part +static void CTU_LINT_body__(CTU_LINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CU_T.,CLK,,__GET_VAR(data__->CU,)); +R_TRIG_body__(&data__->CU_T); +if (__GET_VAR(data__->R,)) { + __SET_VAR(data__->,CV,,0); +} else if ((__GET_VAR(data__->CU_T.Q,) && (__GET_VAR(data__->CV,) < __GET_VAR(data__->PV,)))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) + 1)); +}; +__SET_VAR(data__->,Q,,(__GET_VAR(data__->CV,) >= __GET_VAR(data__->PV,))); + +goto __end; + +__end: + return; +} // CTU_LINT_body__() + + + + + +static void CTU_UDINT_init__(CTU_UDINT *data__, BOOL retain) { + __INIT_VAR(data__->CU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CU_T,retain); +} + +// Code part +static void CTU_UDINT_body__(CTU_UDINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CU_T.,CLK,,__GET_VAR(data__->CU,)); +R_TRIG_body__(&data__->CU_T); +if (__GET_VAR(data__->R,)) { + __SET_VAR(data__->,CV,,0); +} else if ((__GET_VAR(data__->CU_T.Q,) && (__GET_VAR(data__->CV,) < __GET_VAR(data__->PV,)))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) + 1)); +}; +__SET_VAR(data__->,Q,,(__GET_VAR(data__->CV,) >= __GET_VAR(data__->PV,))); + +goto __end; + +__end: + return; +} // CTU_UDINT_body__() + + + + + +static void CTU_ULINT_init__(CTU_ULINT *data__, BOOL retain) { + __INIT_VAR(data__->CU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CU_T,retain); +} + +// Code part +static void CTU_ULINT_body__(CTU_ULINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CU_T.,CLK,,__GET_VAR(data__->CU,)); +R_TRIG_body__(&data__->CU_T); +if (__GET_VAR(data__->R,)) { + __SET_VAR(data__->,CV,,0); +} else if ((__GET_VAR(data__->CU_T.Q,) && (__GET_VAR(data__->CV,) < __GET_VAR(data__->PV,)))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) + 1)); +}; +__SET_VAR(data__->,Q,,(__GET_VAR(data__->CV,) >= __GET_VAR(data__->PV,))); + +goto __end; + +__end: + return; +} // CTU_ULINT_body__() + + + + + +static void CTD_init__(CTD *data__, BOOL retain) { + __INIT_VAR(data__->CD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->LD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CD_T,retain); +} + +// Code part +static void CTD_body__(CTD *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CD_T.,CLK,,__GET_VAR(data__->CD,)); +R_TRIG_body__(&data__->CD_T); +if (__GET_VAR(data__->LD,)) { + __SET_VAR(data__->,CV,,__GET_VAR(data__->PV,)); +} else if ((__GET_VAR(data__->CD_T.Q,) && (__GET_VAR(data__->CV,) > 0))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) - 1)); +}; +__SET_VAR(data__->,Q,,(__GET_VAR(data__->CV,) <= 0)); + +goto __end; + +__end: + return; +} // CTD_body__() + + + + + +static void CTD_DINT_init__(CTD_DINT *data__, BOOL retain) { + __INIT_VAR(data__->CD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->LD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CD_T,retain); +} + +// Code part +static void CTD_DINT_body__(CTD_DINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CD_T.,CLK,,__GET_VAR(data__->CD,)); +R_TRIG_body__(&data__->CD_T); +if (__GET_VAR(data__->LD,)) { + __SET_VAR(data__->,CV,,__GET_VAR(data__->PV,)); +} else if ((__GET_VAR(data__->CD_T.Q,) && (__GET_VAR(data__->CV,) > 0))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) - 1)); +}; +__SET_VAR(data__->,Q,,(__GET_VAR(data__->CV,) <= 0)); + +goto __end; + +__end: + return; +} // CTD_DINT_body__() + + + + + +static void CTD_LINT_init__(CTD_LINT *data__, BOOL retain) { + __INIT_VAR(data__->CD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->LD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CD_T,retain); +} + +// Code part +static void CTD_LINT_body__(CTD_LINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CD_T.,CLK,,__GET_VAR(data__->CD,)); +R_TRIG_body__(&data__->CD_T); +if (__GET_VAR(data__->LD,)) { + __SET_VAR(data__->,CV,,__GET_VAR(data__->PV,)); +} else if ((__GET_VAR(data__->CD_T.Q,) && (__GET_VAR(data__->CV,) > 0))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) - 1)); +}; +__SET_VAR(data__->,Q,,(__GET_VAR(data__->CV,) <= 0)); + +goto __end; + +__end: + return; +} // CTD_LINT_body__() + + + + + +static void CTD_UDINT_init__(CTD_UDINT *data__, BOOL retain) { + __INIT_VAR(data__->CD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->LD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CD_T,retain); +} + +// Code part +static void CTD_UDINT_body__(CTD_UDINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CD_T.,CLK,,__GET_VAR(data__->CD,)); +R_TRIG_body__(&data__->CD_T); +if (__GET_VAR(data__->LD,)) { + __SET_VAR(data__->,CV,,__GET_VAR(data__->PV,)); +} else if ((__GET_VAR(data__->CD_T.Q,) && (__GET_VAR(data__->CV,) > 0))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) - 1)); +}; +__SET_VAR(data__->,Q,,(__GET_VAR(data__->CV,) <= 0)); + +goto __end; + +__end: + return; +} // CTD_UDINT_body__() + + + + + +static void CTD_ULINT_init__(CTD_ULINT *data__, BOOL retain) { + __INIT_VAR(data__->CD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->LD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CD_T,retain); +} + +// Code part +static void CTD_ULINT_body__(CTD_ULINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CD_T.,CLK,,__GET_VAR(data__->CD,)); +R_TRIG_body__(&data__->CD_T); +if (__GET_VAR(data__->LD,)) { + __SET_VAR(data__->,CV,,__GET_VAR(data__->PV,)); +} else if ((__GET_VAR(data__->CD_T.Q,) && (__GET_VAR(data__->CV,) > 0))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) - 1)); +}; +__SET_VAR(data__->,Q,,(__GET_VAR(data__->CV,) <= 0)); + +goto __end; + +__end: + return; +} // CTD_ULINT_body__() + + + + + +static void CTUD_init__(CTUD *data__, BOOL retain) { + __INIT_VAR(data__->CU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->LD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->QU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->QD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CD_T,retain); + R_TRIG_init__(&data__->CU_T,retain); +} + +// Code part +static void CTUD_body__(CTUD *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CD_T.,CLK,,__GET_VAR(data__->CD,)); +R_TRIG_body__(&data__->CD_T); +__SET_VAR(data__->CU_T.,CLK,,__GET_VAR(data__->CU,)); +R_TRIG_body__(&data__->CU_T); +if (__GET_VAR(data__->R,)) { + __SET_VAR(data__->,CV,,0); +} else if (__GET_VAR(data__->LD,)) { + __SET_VAR(data__->,CV,,__GET_VAR(data__->PV,)); +} else { + if (!((__GET_VAR(data__->CU_T.Q,) && __GET_VAR(data__->CD_T.Q,)))) { + if ((__GET_VAR(data__->CU_T.Q,) && (__GET_VAR(data__->CV,) < __GET_VAR(data__->PV,)))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) + 1)); + } else if ((__GET_VAR(data__->CD_T.Q,) && (__GET_VAR(data__->CV,) > 0))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) - 1)); + }; + }; +}; +__SET_VAR(data__->,QU,,(__GET_VAR(data__->CV,) >= __GET_VAR(data__->PV,))); +__SET_VAR(data__->,QD,,(__GET_VAR(data__->CV,) <= 0)); + +goto __end; + +__end: + return; +} // CTUD_body__() + + + + + +static void CTUD_DINT_init__(CTUD_DINT *data__, BOOL retain) { + __INIT_VAR(data__->CU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->LD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->QU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->QD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CD_T,retain); + R_TRIG_init__(&data__->CU_T,retain); +} + +// Code part +static void CTUD_DINT_body__(CTUD_DINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CD_T.,CLK,,__GET_VAR(data__->CD,)); +R_TRIG_body__(&data__->CD_T); +__SET_VAR(data__->CU_T.,CLK,,__GET_VAR(data__->CU,)); +R_TRIG_body__(&data__->CU_T); +if (__GET_VAR(data__->R,)) { + __SET_VAR(data__->,CV,,0); +} else if (__GET_VAR(data__->LD,)) { + __SET_VAR(data__->,CV,,__GET_VAR(data__->PV,)); +} else { + if (!((__GET_VAR(data__->CU_T.Q,) && __GET_VAR(data__->CD_T.Q,)))) { + if ((__GET_VAR(data__->CU_T.Q,) && (__GET_VAR(data__->CV,) < __GET_VAR(data__->PV,)))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) + 1)); + } else if ((__GET_VAR(data__->CD_T.Q,) && (__GET_VAR(data__->CV,) > 0))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) - 1)); + }; + }; +}; +__SET_VAR(data__->,QU,,(__GET_VAR(data__->CV,) >= __GET_VAR(data__->PV,))); +__SET_VAR(data__->,QD,,(__GET_VAR(data__->CV,) <= 0)); + +goto __end; + +__end: + return; +} // CTUD_DINT_body__() + + + + + +static void CTUD_LINT_init__(CTUD_LINT *data__, BOOL retain) { + __INIT_VAR(data__->CU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->LD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->QU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->QD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CD_T,retain); + R_TRIG_init__(&data__->CU_T,retain); +} + +// Code part +static void CTUD_LINT_body__(CTUD_LINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CD_T.,CLK,,__GET_VAR(data__->CD,)); +R_TRIG_body__(&data__->CD_T); +__SET_VAR(data__->CU_T.,CLK,,__GET_VAR(data__->CU,)); +R_TRIG_body__(&data__->CU_T); +if (__GET_VAR(data__->R,)) { + __SET_VAR(data__->,CV,,0); +} else if (__GET_VAR(data__->LD,)) { + __SET_VAR(data__->,CV,,__GET_VAR(data__->PV,)); +} else { + if (!((__GET_VAR(data__->CU_T.Q,) && __GET_VAR(data__->CD_T.Q,)))) { + if ((__GET_VAR(data__->CU_T.Q,) && (__GET_VAR(data__->CV,) < __GET_VAR(data__->PV,)))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) + 1)); + } else if ((__GET_VAR(data__->CD_T.Q,) && (__GET_VAR(data__->CV,) > 0))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) - 1)); + }; + }; +}; +__SET_VAR(data__->,QU,,(__GET_VAR(data__->CV,) >= __GET_VAR(data__->PV,))); +__SET_VAR(data__->,QD,,(__GET_VAR(data__->CV,) <= 0)); + +goto __end; + +__end: + return; +} // CTUD_LINT_body__() + + + + + +static void CTUD_UDINT_init__(CTUD_UDINT *data__, BOOL retain) { + __INIT_VAR(data__->CU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->LD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->QU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->QD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CD_T,retain); + R_TRIG_init__(&data__->CU_T,retain); +} + +// Code part +static void CTUD_UDINT_body__(CTUD_UDINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CD_T.,CLK,,__GET_VAR(data__->CD,)); +R_TRIG_body__(&data__->CD_T); +__SET_VAR(data__->CU_T.,CLK,,__GET_VAR(data__->CU,)); +R_TRIG_body__(&data__->CU_T); +if (__GET_VAR(data__->R,)) { + __SET_VAR(data__->,CV,,0); +} else if (__GET_VAR(data__->LD,)) { + __SET_VAR(data__->,CV,,__GET_VAR(data__->PV,)); +} else { + if (!((__GET_VAR(data__->CU_T.Q,) && __GET_VAR(data__->CD_T.Q,)))) { + if ((__GET_VAR(data__->CU_T.Q,) && (__GET_VAR(data__->CV,) < __GET_VAR(data__->PV,)))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) + 1)); + } else if ((__GET_VAR(data__->CD_T.Q,) && (__GET_VAR(data__->CV,) > 0))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) - 1)); + }; + }; +}; +__SET_VAR(data__->,QU,,(__GET_VAR(data__->CV,) >= __GET_VAR(data__->PV,))); +__SET_VAR(data__->,QD,,(__GET_VAR(data__->CV,) <= 0)); + +goto __end; + +__end: + return; +} // CTUD_UDINT_body__() + + + + + +static void CTUD_ULINT_init__(CTUD_ULINT *data__, BOOL retain) { + __INIT_VAR(data__->CU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->LD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->QU,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->QD,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CV,0,retain) + R_TRIG_init__(&data__->CD_T,retain); + R_TRIG_init__(&data__->CU_T,retain); +} + +// Code part +static void CTUD_ULINT_body__(CTUD_ULINT *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->CD_T.,CLK,,__GET_VAR(data__->CD,)); +R_TRIG_body__(&data__->CD_T); +__SET_VAR(data__->CU_T.,CLK,,__GET_VAR(data__->CU,)); +R_TRIG_body__(&data__->CU_T); +if (__GET_VAR(data__->R,)) { + __SET_VAR(data__->,CV,,0); +} else if (__GET_VAR(data__->LD,)) { + __SET_VAR(data__->,CV,,__GET_VAR(data__->PV,)); +} else { + if (!((__GET_VAR(data__->CU_T.Q,) && __GET_VAR(data__->CD_T.Q,)))) { + if ((__GET_VAR(data__->CU_T.Q,) && (__GET_VAR(data__->CV,) < __GET_VAR(data__->PV,)))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) + 1)); + } else if ((__GET_VAR(data__->CD_T.Q,) && (__GET_VAR(data__->CV,) > 0))) { + __SET_VAR(data__->,CV,,(__GET_VAR(data__->CV,) - 1)); + }; + }; +}; +__SET_VAR(data__->,QU,,(__GET_VAR(data__->CV,) >= __GET_VAR(data__->PV,))); +__SET_VAR(data__->,QD,,(__GET_VAR(data__->CV,) <= 0)); + +goto __end; + +__end: + return; +} // CTUD_ULINT_body__() + + + + + +static void TP_init__(TP *data__, BOOL retain) { + __INIT_VAR(data__->IN,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PT,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->ET,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->STATE,0,retain) + __INIT_VAR(data__->PREV_IN,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CURRENT_TIME,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->START_TIME,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) +} + +// Code part +static void TP_body__(TP *data__) { +// Initialise TEMP variables + +#define GetFbVar(var,...) __GET_VAR(data__->var,__VA_ARGS__) +#define SetFbVar(var,val,...) __SET_VAR(data__->,var,__VA_ARGS__,val) +__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME) +#undef GetFbVar +#undef SetFbVar +; +if ((((__GET_VAR(data__->STATE,) == 0) && !(__GET_VAR(data__->PREV_IN,))) && __GET_VAR(data__->IN,))) { + __SET_VAR(data__->,STATE,,1); + __SET_VAR(data__->,Q,,__BOOL_LITERAL(TRUE)); + __SET_VAR(data__->,START_TIME,,__GET_VAR(data__->CURRENT_TIME,)); +} else if ((__GET_VAR(data__->STATE,) == 1)) { + if (LE_TIME(2, __time_add(__GET_VAR(data__->START_TIME,), __GET_VAR(data__->PT,)), __GET_VAR(data__->CURRENT_TIME,))) { + __SET_VAR(data__->,STATE,,2); + __SET_VAR(data__->,Q,,__BOOL_LITERAL(FALSE)); + __SET_VAR(data__->,ET,,__GET_VAR(data__->PT,)); + } else { + __SET_VAR(data__->,ET,,__time_sub(__GET_VAR(data__->CURRENT_TIME,), __GET_VAR(data__->START_TIME,))); + }; +}; +if (((__GET_VAR(data__->STATE,) == 2) && !(__GET_VAR(data__->IN,)))) { + __SET_VAR(data__->,ET,,__time_to_timespec(1, 0, 0, 0, 0, 0)); + __SET_VAR(data__->,STATE,,0); +}; +__SET_VAR(data__->,PREV_IN,,__GET_VAR(data__->IN,)); + +goto __end; + +__end: + return; +} // TP_body__() + + + + + +static void TON_init__(TON *data__, BOOL retain) { + __INIT_VAR(data__->IN,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PT,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->ET,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->STATE,0,retain) + __INIT_VAR(data__->PREV_IN,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CURRENT_TIME,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->START_TIME,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) +} + +// Code part +static void TON_body__(TON *data__) { +// Initialise TEMP variables + +#define GetFbVar(var,...) __GET_VAR(data__->var,__VA_ARGS__) +#define SetFbVar(var,val,...) __SET_VAR(data__->,var,__VA_ARGS__,val) +__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME) +#undef GetFbVar +#undef SetFbVar +; +if ((((__GET_VAR(data__->STATE,) == 0) && !(__GET_VAR(data__->PREV_IN,))) && __GET_VAR(data__->IN,))) { + __SET_VAR(data__->,STATE,,1); + __SET_VAR(data__->,Q,,__BOOL_LITERAL(FALSE)); + __SET_VAR(data__->,START_TIME,,__GET_VAR(data__->CURRENT_TIME,)); +} else { + if (!(__GET_VAR(data__->IN,))) { + __SET_VAR(data__->,ET,,__time_to_timespec(1, 0, 0, 0, 0, 0)); + __SET_VAR(data__->,Q,,__BOOL_LITERAL(FALSE)); + __SET_VAR(data__->,STATE,,0); + } else if ((__GET_VAR(data__->STATE,) == 1)) { + if (LE_TIME(2, __time_add(__GET_VAR(data__->START_TIME,), __GET_VAR(data__->PT,)), __GET_VAR(data__->CURRENT_TIME,))) { + __SET_VAR(data__->,STATE,,2); + __SET_VAR(data__->,Q,,__BOOL_LITERAL(TRUE)); + __SET_VAR(data__->,ET,,__GET_VAR(data__->PT,)); + } else { + __SET_VAR(data__->,ET,,__time_sub(__GET_VAR(data__->CURRENT_TIME,), __GET_VAR(data__->START_TIME,))); + }; + }; +}; +__SET_VAR(data__->,PREV_IN,,__GET_VAR(data__->IN,)); + +goto __end; + +__end: + return; +} // TON_body__() + + + + + +static void TOF_init__(TOF *data__, BOOL retain) { + __INIT_VAR(data__->IN,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PT,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->ET,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->STATE,0,retain) + __INIT_VAR(data__->PREV_IN,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CURRENT_TIME,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->START_TIME,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) +} + +// Code part +static void TOF_body__(TOF *data__) { +// Initialise TEMP variables + +#define GetFbVar(var,...) __GET_VAR(data__->var,__VA_ARGS__) +#define SetFbVar(var,val,...) __SET_VAR(data__->,var,__VA_ARGS__,val) +__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME) +#undef GetFbVar +#undef SetFbVar +; +if ((((__GET_VAR(data__->STATE,) == 0) && __GET_VAR(data__->PREV_IN,)) && !(__GET_VAR(data__->IN,)))) { + __SET_VAR(data__->,STATE,,1); + __SET_VAR(data__->,START_TIME,,__GET_VAR(data__->CURRENT_TIME,)); +} else { + if (__GET_VAR(data__->IN,)) { + __SET_VAR(data__->,ET,,__time_to_timespec(1, 0, 0, 0, 0, 0)); + __SET_VAR(data__->,STATE,,0); + } else if ((__GET_VAR(data__->STATE,) == 1)) { + if (LE_TIME(2, __time_add(__GET_VAR(data__->START_TIME,), __GET_VAR(data__->PT,)), __GET_VAR(data__->CURRENT_TIME,))) { + __SET_VAR(data__->,STATE,,2); + __SET_VAR(data__->,ET,,__GET_VAR(data__->PT,)); + } else { + __SET_VAR(data__->,ET,,__time_sub(__GET_VAR(data__->CURRENT_TIME,), __GET_VAR(data__->START_TIME,))); + }; + }; +}; +__SET_VAR(data__->,Q,,(__GET_VAR(data__->IN,) || (__GET_VAR(data__->STATE,) == 1))); +__SET_VAR(data__->,PREV_IN,,__GET_VAR(data__->IN,)); + +goto __end; + +__end: + return; +} // TOF_body__() + + + + + +static void DERIVATIVE_init__(DERIVATIVE *data__, BOOL retain) { + __INIT_VAR(data__->RUN,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->XIN,0,retain) + __INIT_VAR(data__->CYCLE,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->XOUT,0,retain) + __INIT_VAR(data__->X1,0,retain) + __INIT_VAR(data__->X2,0,retain) + __INIT_VAR(data__->X3,0,retain) +} + +// Code part +static void DERIVATIVE_body__(DERIVATIVE *data__) { +// Initialise TEMP variables + +if (__GET_VAR(data__->RUN,)) { + __SET_VAR(data__->,XOUT,,((((3.0 * (__GET_VAR(data__->XIN,) - __GET_VAR(data__->X3,))) + __GET_VAR(data__->X1,)) - __GET_VAR(data__->X2,)) / (10.0 * TIME_TO_REAL((TIME)__GET_VAR(data__->CYCLE,))))); + __SET_VAR(data__->,X3,,__GET_VAR(data__->X2,)); + __SET_VAR(data__->,X2,,__GET_VAR(data__->X1,)); + __SET_VAR(data__->,X1,,__GET_VAR(data__->XIN,)); +} else { + __SET_VAR(data__->,XOUT,,0.0); + __SET_VAR(data__->,X1,,__GET_VAR(data__->XIN,)); + __SET_VAR(data__->,X2,,__GET_VAR(data__->XIN,)); + __SET_VAR(data__->,X3,,__GET_VAR(data__->XIN,)); +}; + +goto __end; + +__end: + return; +} // DERIVATIVE_body__() + + + + + +static void HYSTERESIS_init__(HYSTERESIS *data__, BOOL retain) { + __INIT_VAR(data__->XIN1,0,retain) + __INIT_VAR(data__->XIN2,0,retain) + __INIT_VAR(data__->EPS,0,retain) + __INIT_VAR(data__->Q,0,retain) +} + +// Code part +static void HYSTERESIS_body__(HYSTERESIS *data__) { +// Initialise TEMP variables + +if (__GET_VAR(data__->Q,)) { + if ((__GET_VAR(data__->XIN1,) < (__GET_VAR(data__->XIN2,) - __GET_VAR(data__->EPS,)))) { + __SET_VAR(data__->,Q,,0); + }; +} else if ((__GET_VAR(data__->XIN1,) > (__GET_VAR(data__->XIN2,) + __GET_VAR(data__->EPS,)))) { + __SET_VAR(data__->,Q,,1); +}; + +goto __end; + +__end: + return; +} // HYSTERESIS_body__() + + + + + +static void INTEGRAL_init__(INTEGRAL *data__, BOOL retain) { + __INIT_VAR(data__->RUN,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->R1,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->XIN,0,retain) + __INIT_VAR(data__->X0,0,retain) + __INIT_VAR(data__->CYCLE,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->XOUT,0,retain) +} + +// Code part +static void INTEGRAL_body__(INTEGRAL *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->,Q,,!(__GET_VAR(data__->R1,))); +if (__GET_VAR(data__->R1,)) { + __SET_VAR(data__->,XOUT,,__GET_VAR(data__->X0,)); +} else if (__GET_VAR(data__->RUN,)) { + __SET_VAR(data__->,XOUT,,(__GET_VAR(data__->XOUT,) + (__GET_VAR(data__->XIN,) * TIME_TO_REAL((TIME)__GET_VAR(data__->CYCLE,))))); +}; + +goto __end; + +__end: + return; +} // INTEGRAL_body__() + + + + + +static void PID_init__(PID *data__, BOOL retain) { + __INIT_VAR(data__->AUTO,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PV,0,retain) + __INIT_VAR(data__->SP,0,retain) + __INIT_VAR(data__->X0,0,retain) + __INIT_VAR(data__->KP,0,retain) + __INIT_VAR(data__->TR,0,retain) + __INIT_VAR(data__->TD,0,retain) + __INIT_VAR(data__->CYCLE,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->XOUT,0,retain) + __INIT_VAR(data__->ERROR,0,retain) + INTEGRAL_init__(&data__->ITERM,retain); + DERIVATIVE_init__(&data__->DTERM,retain); +} + +// Code part +static void PID_body__(PID *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->,ERROR,,(__GET_VAR(data__->PV,) - __GET_VAR(data__->SP,))); +__SET_VAR(data__->ITERM.,RUN,,__GET_VAR(data__->AUTO,)); +__SET_VAR(data__->ITERM.,R1,,!(__GET_VAR(data__->AUTO,))); +__SET_VAR(data__->ITERM.,XIN,,__GET_VAR(data__->ERROR,)); +__SET_VAR(data__->ITERM.,X0,,(__GET_VAR(data__->TR,) * (__GET_VAR(data__->X0,) - __GET_VAR(data__->ERROR,)))); +__SET_VAR(data__->ITERM.,CYCLE,,__GET_VAR(data__->CYCLE,)); +INTEGRAL_body__(&data__->ITERM); +__SET_VAR(data__->DTERM.,RUN,,__GET_VAR(data__->AUTO,)); +__SET_VAR(data__->DTERM.,XIN,,__GET_VAR(data__->ERROR,)); +__SET_VAR(data__->DTERM.,CYCLE,,__GET_VAR(data__->CYCLE,)); +DERIVATIVE_body__(&data__->DTERM); +__SET_VAR(data__->,XOUT,,(__GET_VAR(data__->KP,) * ((__GET_VAR(data__->ERROR,) + (__GET_VAR(data__->ITERM.XOUT,) / __GET_VAR(data__->TR,))) + (__GET_VAR(data__->DTERM.XOUT,) * __GET_VAR(data__->TD,))))); + +goto __end; + +__end: + return; +} // PID_body__() + + + + + +static void RAMP_init__(RAMP *data__, BOOL retain) { + __INIT_VAR(data__->RUN,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->X0,0,retain) + __INIT_VAR(data__->X1,0,retain) + __INIT_VAR(data__->TR,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->CYCLE,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->BUSY,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->XOUT,0.0,retain) + __INIT_VAR(data__->XI,0,retain) + __INIT_VAR(data__->T,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) +} + +// Code part +static void RAMP_body__(RAMP *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->,BUSY,,__GET_VAR(data__->RUN,)); +if (__GET_VAR(data__->RUN,)) { + if (GE_TIME(2, __GET_VAR(data__->T,), __GET_VAR(data__->TR,))) { + __SET_VAR(data__->,BUSY,,0); + __SET_VAR(data__->,XOUT,,__GET_VAR(data__->X1,)); + } else { + __SET_VAR(data__->,XOUT,,(__GET_VAR(data__->XI,) + (((__GET_VAR(data__->X1,) - __GET_VAR(data__->XI,)) * TIME_TO_REAL((TIME)__GET_VAR(data__->T,))) / TIME_TO_REAL((TIME)__GET_VAR(data__->TR,))))); + __SET_VAR(data__->,T,,__time_add(__GET_VAR(data__->T,), __GET_VAR(data__->CYCLE,))); + }; +} else { + __SET_VAR(data__->,XOUT,,__GET_VAR(data__->X0,)); + __SET_VAR(data__->,XI,,__GET_VAR(data__->X0,)); + __SET_VAR(data__->,T,,__time_to_timespec(1, 0, 0, 0, 0, 0)); +}; + +goto __end; + +__end: + return; +} // RAMP_body__() + + + + + +static void RTC_init__(RTC *data__, BOOL retain) { + __INIT_VAR(data__->IN,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->PDT,__dt_to_timespec(0, 0, 0, 1, 1, 1970),retain) + __INIT_VAR(data__->Q,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->CDT,__dt_to_timespec(0, 0, 0, 1, 1, 1970),retain) + __INIT_VAR(data__->PREV_IN,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->OFFSET,__time_to_timespec(1, 0, 0, 0, 0, 0),retain) + __INIT_VAR(data__->CURRENT_TIME,__dt_to_timespec(0, 0, 0, 1, 1, 1970),retain) +} + +// Code part +static void RTC_body__(RTC *data__) { +// Initialise TEMP variables + +#define GetFbVar(var,...) __GET_VAR(data__->var,__VA_ARGS__) +#define SetFbVar(var,val,...) __SET_VAR(data__->,var,__VA_ARGS__,val) +__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME) +#undef GetFbVar +#undef SetFbVar +; +if (__GET_VAR(data__->IN,)) { + if (!(__GET_VAR(data__->PREV_IN,))) { + __SET_VAR(data__->,OFFSET,,__time_sub(__GET_VAR(data__->PDT,), __GET_VAR(data__->CURRENT_TIME,))); + }; + __SET_VAR(data__->,CDT,,__time_add(__GET_VAR(data__->CURRENT_TIME,), __GET_VAR(data__->OFFSET,))); +} else { + __SET_VAR(data__->,CDT,,__GET_VAR(data__->CURRENT_TIME,)); +}; +__SET_VAR(data__->,Q,,__GET_VAR(data__->IN,)); +__SET_VAR(data__->,PREV_IN,,__GET_VAR(data__->IN,)); + +goto __end; + +__end: + return; +} // RTC_body__() + + + + + +static void SEMA_init__(SEMA *data__, BOOL retain) { + __INIT_VAR(data__->CLAIM,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->RELEASE,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->BUSY,__BOOL_LITERAL(FALSE),retain) + __INIT_VAR(data__->Q_INTERNAL,__BOOL_LITERAL(FALSE),retain) +} + +// Code part +static void SEMA_body__(SEMA *data__) { +// Initialise TEMP variables + +__SET_VAR(data__->,Q_INTERNAL,,(__GET_VAR(data__->CLAIM,) || (__GET_VAR(data__->Q_INTERNAL,) && !(__GET_VAR(data__->RELEASE,))))); +__SET_VAR(data__->,BUSY,,__GET_VAR(data__->Q_INTERNAL,)); + +goto __end; + +__end: + return; +} // SEMA_body__() + + + + + + + + + + + + + + +#endif //_IEC_STD_FB_H \ No newline at end of file
--- a/lib/C/iec_std_functions.h Thu Mar 12 16:36:33 2015 +0100 +++ b/lib/C/iec_std_functions.h Sat Mar 18 22:02:14 2017 +0000 @@ -82,28 +82,40 @@ /********************/ /* EN/ENO PARAMS */ /********************/ - -#define EN_ENO_PARAMS BOOL EN, BOOL *ENO -#define EN_ENO EN, ENO - -#define TEST_EN(TYPENAME)\ - if (!EN) {\ - if (ENO != NULL)\ - *ENO = __BOOL_LITERAL(FALSE);\ - return __INIT_##TYPENAME;\ - }\ - else if (ENO != NULL)\ - *ENO = __BOOL_LITERAL(TRUE); - -#define TEST_EN_COND(TYPENAME, COND)\ - if (!EN || (COND)) {\ - if (ENO != NULL)\ - *ENO = __BOOL_LITERAL(FALSE);\ - return __INIT_##TYPENAME;\ - }\ - else if (ENO != NULL)\ - *ENO = __BOOL_LITERAL(TRUE); - +#ifdef DISABLE_EN_ENO_PARAMETERS + + /* Do _not_ generate the EN and ENO parameters! */ + #define EN_ENO_PARAMS + #define EN_ENO + + #define TEST_EN(TYPENAME) + #define TEST_EN_COND(TYPENAME, COND) + +#else + + /* _Do_ generate the EN and ENO parameters! */ + #define EN_ENO_PARAMS BOOL EN, BOOL *ENO, + #define EN_ENO EN, ENO, + + #define TEST_EN(TYPENAME)\ + if (!EN) {\ + if (ENO != NULL)\ + *ENO = __BOOL_LITERAL(FALSE);\ + return __INIT_##TYPENAME;\ + }\ + else if (ENO != NULL)\ + *ENO = __BOOL_LITERAL(TRUE); + + #define TEST_EN_COND(TYPENAME, COND)\ + if (!EN || (COND)) {\ + if (ENO != NULL)\ + *ENO = __BOOL_LITERAL(FALSE);\ + return __INIT_##TYPENAME;\ + }\ + else if (ENO != NULL)\ + *ENO = __BOOL_LITERAL(TRUE); + +#endif /*****************************************/ @@ -113,14 +125,14 @@ /*****************************************/ #define __convert_type(from_TYPENAME,to_TYPENAME, oper) \ -static inline to_TYPENAME from_TYPENAME##_TO_##to_TYPENAME(EN_ENO_PARAMS, from_TYPENAME op){\ +static inline to_TYPENAME from_TYPENAME##_TO_##to_TYPENAME(EN_ENO_PARAMS from_TYPENAME op){\ TEST_EN(to_TYPENAME)\ return (to_TYPENAME)oper(op);\ } /******** [ANY_NUM | ANY_NBIT]_TO_BOOL ************/ #define __convert_num_to_bool(TYPENAME) \ -static inline BOOL TYPENAME##_TO_BOOL(EN_ENO_PARAMS, TYPENAME op){\ +static inline BOOL TYPENAME##_TO_BOOL(EN_ENO_PARAMS TYPENAME op){\ TEST_EN(BOOL)\ return op == 0 ? 0 : 1;\ } @@ -129,7 +141,7 @@ /******** [TIME | ANY_DATE]_TO_BOOL ************/ #define __convert_time_to_bool(TYPENAME) \ -static inline BOOL TYPENAME##_TO_BOOL(EN_ENO_PARAMS, TYPENAME op){\ +static inline BOOL TYPENAME##_TO_BOOL(EN_ENO_PARAMS TYPENAME op){\ TEST_EN(BOOL)\ return op.tv_sec == 0 && op.tv_nsec == 0 ? 0 : 1;\ } @@ -211,13 +223,13 @@ /******** [ANY_DATE]_TO_[ANY_DATE | TIME] ************/ /* Not supported: DT_TO_TIME */ __convert_type(DT, DATE, __date_and_time_to_date) -static inline DATE DATE_AND_TIME_TO_DATE(EN_ENO_PARAMS, DT op){ - return DT_TO_DATE(EN_ENO, op); +static inline DATE DATE_AND_TIME_TO_DATE(EN_ENO_PARAMS DT op){ + return DT_TO_DATE(EN_ENO op); } __convert_type(DT, DT, __move_DT) __convert_type(DT, TOD, __date_and_time_to_time_of_day) -static inline DATE DATE_AND_TIME_TO_TIME_OF_DAY(EN_ENO_PARAMS, DT op){ - return DT_TO_TOD(EN_ENO, op); +static inline DATE DATE_AND_TIME_TO_TIME_OF_DAY(EN_ENO_PARAMS DT op){ + return DT_TO_TOD(EN_ENO op); } /* Not supported: DATE_TO_TIME */ __convert_type(DATE, DATE, __move_DATE) @@ -296,7 +308,7 @@ /******** TRUNC ************/ #define __iec_(to_TYPENAME,from_TYPENAME) \ -static inline to_TYPENAME TRUNC__##to_TYPENAME##__##from_TYPENAME(EN_ENO_PARAMS, from_TYPENAME op){\ +static inline to_TYPENAME TRUNC__##to_TYPENAME##__##from_TYPENAME(EN_ENO_PARAMS from_TYPENAME op){\ TEST_EN(to_TYPENAME)\ return (to_TYPENAME)__move_##to_TYPENAME(op);\ } @@ -306,12 +318,12 @@ /******** _TO_BCD ************/ #define __iec_(to_TYPENAME,from_TYPENAME) \ -static inline to_TYPENAME from_TYPENAME##_TO_BCD_##to_TYPENAME(EN_ENO_PARAMS, from_TYPENAME op){\ +static inline to_TYPENAME from_TYPENAME##_TO_BCD_##to_TYPENAME(EN_ENO_PARAMS from_TYPENAME op){\ TEST_EN(to_TYPENAME)\ return (to_TYPENAME)__uint_to_bcd(op);\ }\ -static inline to_TYPENAME from_TYPENAME##_TO_BCD__##to_TYPENAME##__##from_TYPENAME(EN_ENO_PARAMS, from_TYPENAME op){\ - return from_TYPENAME##_TO_BCD_##to_TYPENAME(EN_ENO, op);\ +static inline to_TYPENAME from_TYPENAME##_TO_BCD__##to_TYPENAME##__##from_TYPENAME(EN_ENO_PARAMS from_TYPENAME op){\ + return from_TYPENAME##_TO_BCD_##to_TYPENAME(EN_ENO op);\ } __ANY_UINT(__to_anynbit_) #undef __iec_ @@ -319,12 +331,12 @@ /******** BCD_TO_ ************/ #define __iec_(to_TYPENAME,from_TYPENAME) \ -static inline to_TYPENAME from_TYPENAME##_BCD_TO_##to_TYPENAME(EN_ENO_PARAMS, from_TYPENAME op){\ +static inline to_TYPENAME from_TYPENAME##_BCD_TO_##to_TYPENAME(EN_ENO_PARAMS from_TYPENAME op){\ TEST_EN_COND(to_TYPENAME, __test_bcd(op))\ return (to_TYPENAME)__bcd_to_uint(op);\ }\ -static inline to_TYPENAME BCD_TO_##to_TYPENAME##__##to_TYPENAME##__##from_TYPENAME(EN_ENO_PARAMS, from_TYPENAME op){\ - return from_TYPENAME##_BCD_TO_##to_TYPENAME(EN_ENO, op);\ +static inline to_TYPENAME BCD_TO_##to_TYPENAME##__##to_TYPENAME##__##from_TYPENAME(EN_ENO_PARAMS from_TYPENAME op){\ + return from_TYPENAME##_BCD_TO_##to_TYPENAME(EN_ENO op);\ } __ANY_NBIT(__to_anyuint_) #undef __iec_ @@ -362,13 +374,13 @@ #define __numeric(fname,TYPENAME, FUNC) \ /* explicitly typed function */\ -static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, TYPENAME op){\ +static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS TYPENAME op){\ TEST_EN(TYPENAME)\ return FUNC(op);\ }\ /* overloaded function */\ -static inline TYPENAME fname##_##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op) {\ - return fname##TYPENAME(EN_ENO, op);\ +static inline TYPENAME fname##_##TYPENAME##__##TYPENAME(EN_ENO_PARAMS TYPENAME op) {\ + return fname##TYPENAME(EN_ENO op);\ } /******************************************************************/ @@ -380,26 +392,26 @@ /**************/ #define __abs_signed(TYPENAME) \ /* explicitly typed function */\ -static inline TYPENAME ABS_##TYPENAME(EN_ENO_PARAMS, TYPENAME op){\ +static inline TYPENAME ABS_##TYPENAME(EN_ENO_PARAMS TYPENAME op){\ TEST_EN(TYPENAME)\ if (op < 0)\ return -op;\ return op;\ }\ /* overloaded function */\ -static inline TYPENAME ABS__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op) {\ - return ABS_##TYPENAME(EN_ENO, op);\ +static inline TYPENAME ABS__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS TYPENAME op) {\ + return ABS_##TYPENAME(EN_ENO op);\ } #define __abs_unsigned(TYPENAME) \ /* explicitly typed function */\ -static inline TYPENAME ABS_##TYPENAME(EN_ENO_PARAMS, TYPENAME op){\ +static inline TYPENAME ABS_##TYPENAME(EN_ENO_PARAMS TYPENAME op){\ TEST_EN(TYPENAME)\ return op;\ }\ /* overloaded function */\ -static inline TYPENAME ABS__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op) {\ - return ABS_##TYPENAME(EN_ENO, op);\ +static inline TYPENAME ABS__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS TYPENAME op) {\ + return ABS_##TYPENAME(EN_ENO op);\ } __ANY_REAL(__abs_signed) @@ -480,7 +492,7 @@ /*****************************************************/ #define __arith_expand(fname,TYPENAME, OP)\ -static inline TYPENAME fname(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\ +static inline TYPENAME fname(EN_ENO_PARAMS UINT param_count, TYPENAME op1, ...){\ va_list ap;\ UINT i;\ TEST_EN(TYPENAME)\ @@ -497,13 +509,13 @@ #define __arith_static(fname,TYPENAME, OP)\ /* explicitly typed function */\ -static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\ +static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS TYPENAME op1, TYPENAME op2){\ TEST_EN(TYPENAME)\ return op1 OP op2;\ }\ /* overloaded function */\ -static inline TYPENAME fname##_##TYPENAME##__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\ - return fname##TYPENAME(EN_ENO, op1, op2);\ +static inline TYPENAME fname##_##TYPENAME##__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS TYPENAME op1, TYPENAME op2){\ + return fname##TYPENAME(EN_ENO op1, op2);\ } /**************/ @@ -536,13 +548,13 @@ /**************/ #define __div(TYPENAME)\ /* The explicitly typed standard functions */\ -static inline TYPENAME DIV_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\ +static inline TYPENAME DIV_##TYPENAME(EN_ENO_PARAMS TYPENAME op1, TYPENAME op2){\ TEST_EN_COND(TYPENAME, op2 == 0)\ return op1 / op2;\ }\ /* The overloaded standard functions */\ -static inline TYPENAME DIV__##TYPENAME##__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\ - return DIV_##TYPENAME(EN_ENO, op1, op2);\ +static inline TYPENAME DIV__##TYPENAME##__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS TYPENAME op1, TYPENAME op2){\ + return DIV_##TYPENAME(EN_ENO op1, op2);\ } __ANY_NUM(__div) @@ -552,14 +564,14 @@ /**************/ #define __mod(TYPENAME)\ /* The explicitly typed standard functions */\ -static inline TYPENAME MOD_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\ +static inline TYPENAME MOD_##TYPENAME(EN_ENO_PARAMS TYPENAME op1, TYPENAME op2){\ TEST_EN(TYPENAME)\ if (op2 == 0) return 0;\ return op1 % op2;\ }\ /* The overloaded standard functions */\ -static inline TYPENAME MOD__##TYPENAME##__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\ - return MOD_##TYPENAME(EN_ENO, op1, op2);\ +static inline TYPENAME MOD__##TYPENAME##__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS TYPENAME op1, TYPENAME op2){\ + return MOD_##TYPENAME(EN_ENO op1, op2);\ } __ANY_INT(__mod) @@ -569,9 +581,9 @@ /* overloaded function */ #define __iec_(in1_TYPENAME,in2_TYPENAME) \ static inline in1_TYPENAME EXPT__##in1_TYPENAME##__##in1_TYPENAME##__##in2_TYPENAME\ - (EN_ENO_PARAMS, in1_TYPENAME IN1, in2_TYPENAME IN2){\ + (EN_ENO_PARAMS in1_TYPENAME IN1, in2_TYPENAME IN2){\ TEST_EN(in1_TYPENAME)\ - return pow(IN1, IN2);\ + return __expt(IN1, IN2);\ } #define __in1_anyreal_(in2_TYPENAME) __ANY_REAL_1(__iec_,in2_TYPENAME) __ANY_NUM(__in1_anyreal_) @@ -584,7 +596,7 @@ /***************/ /* The explicitly typed standard functions */ #define __iec_(TYPENAME)\ -static inline TYPENAME MOVE_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1){\ +static inline TYPENAME MOVE_##TYPENAME(EN_ENO_PARAMS TYPENAME op1){\ TEST_EN(TYPENAME)\ return op1;\ } @@ -593,7 +605,7 @@ /* Overloaded function */ #define __iec_(TYPENAME)\ -static inline TYPENAME MOVE__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op1){\ +static inline TYPENAME MOVE__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS TYPENAME op1){\ TEST_EN(TYPENAME)\ return op1;\ } @@ -621,7 +633,7 @@ #define __in1_anynbit_(in2_TYPENAME) __ANY_NBIT_1(__iec_,in2_TYPENAME) #define __shift_(fname, in1_TYPENAME, in2_TYPENAME, OP)\ -static inline in1_TYPENAME fname(EN_ENO_PARAMS, in1_TYPENAME IN, in2_TYPENAME N) {\ +static inline in1_TYPENAME fname(EN_ENO_PARAMS in1_TYPENAME IN, in2_TYPENAME N) {\ TEST_EN(in1_TYPENAME)\ return IN OP N;\ } @@ -631,7 +643,7 @@ /**************/ #define __iec_(TYPENAME) \ /* Overloaded function */\ -static inline BOOL SHL__BOOL__##TYPENAME(EN_ENO_PARAMS, BOOL IN, TYPENAME N) { \ +static inline BOOL SHL__BOOL__##TYPENAME(EN_ENO_PARAMS BOOL IN, TYPENAME N) { \ TEST_EN(BOOL);\ return (N==0)? IN : __INIT_BOOL; /* shifting by N>1 will always introduce a 0 */\ } @@ -650,7 +662,7 @@ /**************/ #define __iec_(TYPENAME) \ /* Overloaded function */\ -static inline BOOL SHR__BOOL__##TYPENAME(EN_ENO_PARAMS, BOOL IN, TYPENAME N) { \ +static inline BOOL SHR__BOOL__##TYPENAME(EN_ENO_PARAMS BOOL IN, TYPENAME N) { \ TEST_EN(BOOL);\ return (N==0)? IN : __INIT_BOOL; /* shifting by N>1 will always introduce a 0 */\ } @@ -669,7 +681,7 @@ /**************/ #define __iec_(TYPENAME) \ /* Overloaded function */\ -static inline BOOL ROR__BOOL__##TYPENAME(EN_ENO_PARAMS, BOOL IN, TYPENAME N) { \ +static inline BOOL ROR__BOOL__##TYPENAME(EN_ENO_PARAMS BOOL IN, TYPENAME N) { \ TEST_EN(BOOL);\ return IN; /* rotating a single bit by any value N will not change that bit! */\ } @@ -678,7 +690,7 @@ #define __iec_(in1_TYPENAME,in2_TYPENAME) \ -static inline in1_TYPENAME ROR__##in1_TYPENAME##__##in1_TYPENAME##__##in2_TYPENAME(EN_ENO_PARAMS, in1_TYPENAME IN, in2_TYPENAME N){\ +static inline in1_TYPENAME ROR__##in1_TYPENAME##__##in1_TYPENAME##__##in2_TYPENAME(EN_ENO_PARAMS in1_TYPENAME IN, in2_TYPENAME N){\ TEST_EN(in1_TYPENAME)\ N %= 8*sizeof(in1_TYPENAME);\ return (IN >> N) | (IN << (8*sizeof(in1_TYPENAME)-N));\ @@ -692,7 +704,7 @@ /**************/ #define __iec_(TYPENAME) \ /* Overloaded function */\ -static inline BOOL ROL__BOOL__##TYPENAME(EN_ENO_PARAMS, BOOL IN, TYPENAME N) { \ +static inline BOOL ROL__BOOL__##TYPENAME(EN_ENO_PARAMS BOOL IN, TYPENAME N) { \ TEST_EN(BOOL);\ return IN; /* rotating a single bit by any value N will not change that bit! */\ } @@ -701,7 +713,7 @@ #define __iec_(in1_TYPENAME,in2_TYPENAME) \ -static inline in1_TYPENAME ROL__##in1_TYPENAME##__##in1_TYPENAME##__##in2_TYPENAME(EN_ENO_PARAMS, in1_TYPENAME IN, in2_TYPENAME N){\ +static inline in1_TYPENAME ROL__##in1_TYPENAME##__##in1_TYPENAME##__##in2_TYPENAME(EN_ENO_PARAMS in1_TYPENAME IN, in2_TYPENAME N){\ TEST_EN(in1_TYPENAME)\ N %= 8*sizeof(in1_TYPENAME);\ return (IN << N) | (IN >> (8*sizeof(in1_TYPENAME)-N));\ @@ -743,7 +755,7 @@ /* XOR */ /**************/ #define __xorbool_expand(fname) \ -static inline BOOL fname(EN_ENO_PARAMS, UINT param_count, BOOL op1, ...){ \ +static inline BOOL fname(EN_ENO_PARAMS UINT param_count, BOOL op1, ...){ \ va_list ap; \ UINT i; \ TEST_EN(BOOL) \ @@ -773,20 +785,20 @@ /* NOT */ /**************/ /* The explicitly typed standard functions */ -static inline BOOL NOT_BOOL(EN_ENO_PARAMS, BOOL op1){ +static inline BOOL NOT_BOOL(EN_ENO_PARAMS BOOL op1){ TEST_EN(BOOL) return !op1; } /* Overloaded function */ -static inline BOOL NOT__BOOL__BOOL(EN_ENO_PARAMS, BOOL op1){ +static inline BOOL NOT__BOOL__BOOL(EN_ENO_PARAMS BOOL op1){ TEST_EN(BOOL) return !op1; } /* The explicitly typed standard functions */ #define __iec_(TYPENAME)\ -static inline TYPENAME NOT_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1){\ +static inline TYPENAME NOT_##TYPENAME(EN_ENO_PARAMS TYPENAME op1){\ TEST_EN(TYPENAME)\ return ~op1;\ } @@ -795,7 +807,7 @@ /* Overloaded function */ #define __iec_(TYPENAME)\ -static inline TYPENAME NOT__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op1){\ +static inline TYPENAME NOT__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS TYPENAME op1){\ TEST_EN(TYPENAME)\ return ~op1;\ } @@ -824,7 +836,7 @@ /* The explicitly typed standard functions */ #define __iec_(TYPENAME)\ -static inline TYPENAME SEL_##TYPENAME(EN_ENO_PARAMS, BOOL G, TYPENAME op0, TYPENAME op1){\ +static inline TYPENAME SEL_##TYPENAME(EN_ENO_PARAMS BOOL G, TYPENAME op0, TYPENAME op1){\ TEST_EN(TYPENAME)\ return G ? op1 : op0;\ } @@ -833,7 +845,7 @@ /* Overloaded function */ #define __iec_(TYPENAME)\ -static inline TYPENAME SEL__##TYPENAME##__BOOL__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, BOOL G, TYPENAME op0, TYPENAME op1){\ +static inline TYPENAME SEL__##TYPENAME##__BOOL__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS BOOL G, TYPENAME op0, TYPENAME op1){\ TEST_EN(TYPENAME)\ return G ? op1 : op0;\ } @@ -846,7 +858,7 @@ /**************/ #define __extrem_(fname,TYPENAME, COND) \ -static inline TYPENAME fname(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\ +static inline TYPENAME fname(EN_ENO_PARAMS UINT param_count, TYPENAME op1, ...){\ va_list ap;\ UINT i;\ TEST_EN(TYPENAME)\ @@ -914,12 +926,12 @@ /* Limit for numerical data types */ #define __iec_(TYPENAME)\ /* The explicitly typed standard functions */\ -static inline TYPENAME LIMIT_##TYPENAME(EN_ENO_PARAMS, TYPENAME MN, TYPENAME IN, TYPENAME MX){\ +static inline TYPENAME LIMIT_##TYPENAME(EN_ENO_PARAMS TYPENAME MN, TYPENAME IN, TYPENAME MX){\ TEST_EN(TYPENAME)\ return IN > MN ? IN < MX ? IN : MX : MN;\ }\ /* Overloaded function */\ -static inline TYPENAME LIMIT__##TYPENAME##__##TYPENAME##__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME MN, TYPENAME IN, TYPENAME MX){\ +static inline TYPENAME LIMIT__##TYPENAME##__##TYPENAME##__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS TYPENAME MN, TYPENAME IN, TYPENAME MX){\ TEST_EN(TYPENAME)\ return IN > MN ? IN < MX ? IN : MX : MN;\ } @@ -931,14 +943,14 @@ /* Limit for time data types */ #define __iec_(TYPENAME)\ /* The explicitly typed standard functions */\ -static inline TYPENAME LIMIT_##TYPENAME(EN_ENO_PARAMS, TYPENAME MN, TYPENAME IN, TYPENAME MX){\ +static inline TYPENAME LIMIT_##TYPENAME(EN_ENO_PARAMS TYPENAME MN, TYPENAME IN, TYPENAME MX){\ TEST_EN(TYPENAME)\ return __time_cmp(IN, MN) > 0 ? /* IN>MN ?*/\ __time_cmp(IN, MX) < 0 ? /* IN<MX ?*/\ IN : MX : MN;\ }\ /* Overloaded function */\ -static inline TYPENAME LIMIT__##TYPENAME##__##TYPENAME##__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME MN, TYPENAME IN, TYPENAME MX){\ +static inline TYPENAME LIMIT__##TYPENAME##__##TYPENAME##__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS TYPENAME MN, TYPENAME IN, TYPENAME MX){\ TEST_EN(TYPENAME)\ return __time_cmp(IN, MN) > 0 ? /* IN>MN ?*/\ __time_cmp(IN, MX) < 0 ? /* IN<MX ?*/\ @@ -951,13 +963,13 @@ /* Limit for string data types */ /* The explicitly typed standard functions */ -static inline STRING LIMIT_STRING(EN_ENO_PARAMS, STRING MN, STRING IN, STRING MX){ +static inline STRING LIMIT_STRING(EN_ENO_PARAMS STRING MN, STRING IN, STRING MX){ TEST_EN(STRING) return __STR_CMP(IN, MN) > 0 ? __STR_CMP(IN, MX) < 0 ? IN : MX : MN; } /* Overloaded function */ -static inline STRING LIMIT__STRING__STRING__STRING__STRING(EN_ENO_PARAMS, STRING MN, STRING IN, STRING MX){ +static inline STRING LIMIT__STRING__STRING__STRING__STRING(EN_ENO_PARAMS STRING MN, STRING IN, STRING MX){ TEST_EN(STRING) return __STR_CMP(IN, MN) > 0 ? __STR_CMP(IN, MX) < 0 ? IN : MX : MN; } @@ -972,7 +984,7 @@ /* The explicitly typed standard functions */ #define __in1_anyint_(in2_TYPENAME) __ANY_INT_1(__iec_,in2_TYPENAME) #define __iec_(in1_TYPENAME,in2_TYPENAME) \ -static inline in2_TYPENAME MUX__##in2_TYPENAME##__##in1_TYPENAME##__##in2_TYPENAME(EN_ENO_PARAMS, in1_TYPENAME K, UINT param_count, ...){\ +static inline in2_TYPENAME MUX__##in2_TYPENAME##__##in1_TYPENAME##__##in2_TYPENAME(EN_ENO_PARAMS in1_TYPENAME K, UINT param_count, ...){\ va_list ap;\ UINT i;\ in2_TYPENAME tmp;\ @@ -1005,7 +1017,7 @@ /******************************************/ #define __compare_(fname,TYPENAME, COND) \ -static inline BOOL fname(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\ +static inline BOOL fname(EN_ENO_PARAMS UINT param_count, TYPENAME op1, ...){\ va_list ap;\ UINT i;\ TEST_EN(BOOL)\ @@ -1158,19 +1170,19 @@ /* NE */ /**************/ #define __ne_num(fname, TYPENAME) \ -static inline BOOL fname(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\ +static inline BOOL fname(EN_ENO_PARAMS TYPENAME op1, TYPENAME op2){\ TEST_EN(BOOL)\ return op1 != op2 ? 1 : 0;\ } #define __ne_time(fname, TYPENAME) \ -static inline BOOL fname(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\ +static inline BOOL fname(EN_ENO_PARAMS TYPENAME op1, TYPENAME op2){\ TEST_EN(BOOL)\ return __time_cmp(op1, op2) != 0 ? 1 : 0;\ } #define __ne_string(fname, TYPENAME) \ -static inline BOOL fname(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\ +static inline BOOL fname(EN_ENO_PARAMS TYPENAME op1, TYPENAME op2){\ TEST_EN(BOOL)\ return __STR_CMP(op1, op2) != 0 ? 1 : 0;\ } @@ -1225,7 +1237,7 @@ /* A function, with 1 input paramter, implementing a generic OPERATION */ #define __genoper_1p_(fname,ret_TYPENAME, par_TYPENAME, OPERATION) \ -static inline ret_TYPENAME fname(EN_ENO_PARAMS, par_TYPENAME par1){\ +static inline ret_TYPENAME fname(EN_ENO_PARAMS par_TYPENAME par1){\ TEST_EN(ret_TYPENAME)\ return (ret_TYPENAME)OPERATION(par1);\ } @@ -1240,7 +1252,7 @@ /****************/ #define __left(TYPENAME) \ -static inline STRING LEFT__STRING__STRING__##TYPENAME(EN_ENO_PARAMS, STRING IN, TYPENAME L){\ +static inline STRING LEFT__STRING__STRING__##TYPENAME(EN_ENO_PARAMS STRING IN, TYPENAME L){\ STRING res;\ TEST_EN_COND(STRING, L < 0)\ res = __INIT_STRING;\ @@ -1257,7 +1269,7 @@ /*****************/ #define __right(TYPENAME) \ -static inline STRING RIGHT__STRING__STRING__##TYPENAME(EN_ENO_PARAMS, STRING IN, TYPENAME L){\ +static inline STRING RIGHT__STRING__STRING__##TYPENAME(EN_ENO_PARAMS STRING IN, TYPENAME L){\ STRING res;\ TEST_EN_COND(STRING, L < 0)\ res = __INIT_STRING;\ @@ -1274,7 +1286,7 @@ /***************/ #define __mid(TYPENAME) \ -static inline STRING MID__STRING__STRING__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, STRING IN, TYPENAME L, TYPENAME P){\ +static inline STRING MID__STRING__STRING__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS STRING IN, TYPENAME L, TYPENAME P){\ STRING res;\ TEST_EN_COND(STRING, L < 0 || P < 0)\ res = __INIT_STRING;\ @@ -1293,7 +1305,7 @@ /* CONCAT */ /******************/ -static inline STRING CONCAT(EN_ENO_PARAMS, UINT param_count, ...){ +static inline STRING CONCAT(EN_ENO_PARAMS UINT param_count, ...){ UINT i; STRING res; va_list ap; @@ -1344,7 +1356,7 @@ } #define __iec_(TYPENAME) \ -static inline STRING INSERT__STRING__STRING__STRING__##TYPENAME(EN_ENO_PARAMS, STRING str1, STRING str2, TYPENAME P){\ +static inline STRING INSERT__STRING__STRING__STRING__##TYPENAME(EN_ENO_PARAMS STRING str1, STRING str2, TYPENAME P){\ TEST_EN_COND(STRING, P < 0)\ return (STRING)__insert(str1,str2,(__strlen_t)P);\ } @@ -1375,7 +1387,7 @@ } #define __iec_(TYPENAME) \ -static inline STRING DELETE__STRING__STRING__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, STRING str, TYPENAME L, TYPENAME P){\ +static inline STRING DELETE__STRING__STRING__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS STRING str, TYPENAME L, TYPENAME P){\ TEST_EN_COND(STRING, L < 0 || P < 0)\ return (STRING)__delete(str,(__strlen_t)L,(__strlen_t)P);\ } @@ -1416,7 +1428,7 @@ } #define __iec_(TYPENAME) \ -static inline STRING REPLACE__STRING__STRING__STRING__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, STRING str1, STRING str2, TYPENAME L, TYPENAME P){\ +static inline STRING REPLACE__STRING__STRING__STRING__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS STRING str1, STRING str2, TYPENAME L, TYPENAME P){\ TEST_EN_COND(STRING, L < 0 || P < 0)\ return (STRING)__replace(str1,str2,(__strlen_t)L,(__strlen_t)P);\ } @@ -1444,7 +1456,7 @@ } #define __iec_(TYPENAME) \ -static inline TYPENAME FIND__##TYPENAME##__STRING__STRING(EN_ENO_PARAMS, STRING str1, STRING str2){\ +static inline TYPENAME FIND__##TYPENAME##__STRING__STRING(EN_ENO_PARAMS STRING str1, STRING str2){\ TEST_EN(TYPENAME)\ return (TYPENAME)__pfind(&str1,&str2);\ } @@ -1464,47 +1476,47 @@ /**************************************/ -static inline TIME ADD_TIME(EN_ENO_PARAMS, TIME IN1, TIME IN2){ +static inline TIME ADD_TIME(EN_ENO_PARAMS TIME IN1, TIME IN2){ TEST_EN(TIME) return __time_add(IN1, IN2); } -static inline TOD ADD_TOD_TIME(EN_ENO_PARAMS, TOD IN1, TIME IN2){ +static inline TOD ADD_TOD_TIME(EN_ENO_PARAMS TOD IN1, TIME IN2){ TEST_EN(TOD) return __time_add(IN1, IN2); } -static inline DT ADD_DT_TIME(EN_ENO_PARAMS, DT IN1, TIME IN2){ +static inline DT ADD_DT_TIME(EN_ENO_PARAMS DT IN1, TIME IN2){ TEST_EN(DT) return __time_add(IN1, IN2); } -static inline TIME SUB_TIME(EN_ENO_PARAMS, TIME IN1, TIME IN2){ +static inline TIME SUB_TIME(EN_ENO_PARAMS TIME IN1, TIME IN2){ TEST_EN(TIME) return __time_sub(IN1, IN2); } -static inline TIME SUB_DATE_DATE(EN_ENO_PARAMS, DATE IN1, DATE IN2){ +static inline TIME SUB_DATE_DATE(EN_ENO_PARAMS DATE IN1, DATE IN2){ TEST_EN(TIME) return __time_sub(IN1, IN2); } -static inline TOD SUB_TOD_TIME(EN_ENO_PARAMS, TOD IN1, TIME IN2){ +static inline TOD SUB_TOD_TIME(EN_ENO_PARAMS TOD IN1, TIME IN2){ TEST_EN(TOD) return __time_sub(IN1, IN2); } -static inline TIME SUB_TOD_TOD(EN_ENO_PARAMS, TOD IN1, TOD IN2){ +static inline TIME SUB_TOD_TOD(EN_ENO_PARAMS TOD IN1, TOD IN2){ TEST_EN(TIME) return __time_sub(IN1, IN2); } -static inline DT SUB_DT_TIME(EN_ENO_PARAMS, DT IN1, TIME IN2){ +static inline DT SUB_DT_TIME(EN_ENO_PARAMS DT IN1, TIME IN2){ TEST_EN(DT) return __time_sub(IN1, IN2); } -static inline TIME SUB_DT_DT(EN_ENO_PARAMS, DT IN1, DT IN2){ +static inline TIME SUB_DT_DT(EN_ENO_PARAMS DT IN1, DT IN2){ TEST_EN(TIME) return __time_sub(IN1, IN2); } @@ -1512,7 +1524,7 @@ /*** MULTIME ***/ #define __iec_(TYPENAME)\ -static inline TIME MULTIME__TIME__TIME__##TYPENAME(EN_ENO_PARAMS, TIME IN1, TYPENAME IN2){\ +static inline TIME MULTIME__TIME__TIME__##TYPENAME(EN_ENO_PARAMS TIME IN1, TYPENAME IN2){\ TEST_EN(TIME)\ return __time_mul(IN1, (LREAL)IN2);\ } @@ -1521,7 +1533,7 @@ /*** MUL ***/ #define __iec_(TYPENAME)\ -static inline TIME MUL__TIME__TIME__##TYPENAME(EN_ENO_PARAMS, TIME IN1, TYPENAME IN2){\ +static inline TIME MUL__TIME__TIME__##TYPENAME(EN_ENO_PARAMS TIME IN1, TYPENAME IN2){\ TEST_EN(TIME)\ return __time_mul(IN1, (LREAL)IN2);\ } @@ -1530,7 +1542,7 @@ /*** DIVTIME ***/ #define __iec_(TYPENAME)\ -static inline TIME DIVTIME__TIME__TIME__##TYPENAME(EN_ENO_PARAMS, TIME IN1, TYPENAME IN2){\ +static inline TIME DIVTIME__TIME__TIME__##TYPENAME(EN_ENO_PARAMS TIME IN1, TYPENAME IN2){\ TEST_EN(TIME)\ return __time_div(IN1, (LREAL)IN2);\ } @@ -1539,7 +1551,7 @@ /*** DIV ***/ #define __iec_(TYPENAME)\ -static inline TIME DIV__TIME__TIME__##TYPENAME(EN_ENO_PARAMS, TIME IN1, TYPENAME IN2){\ +static inline TIME DIV__TIME__TIME__##TYPENAME(EN_ENO_PARAMS TIME IN1, TYPENAME IN2){\ TEST_EN(TIME)\ return __time_div(IN1, (LREAL)IN2);\ } @@ -1547,7 +1559,7 @@ #undef __iec_ /*** CONCAT_DATE_TOD ***/ -static inline DT CONCAT_DATE_TOD(EN_ENO_PARAMS, DATE IN1, TOD IN2){ +static inline DT CONCAT_DATE_TOD(EN_ENO_PARAMS DATE IN1, TOD IN2){ TEST_EN(DT) return __time_add(IN1, IN2); }
--- a/lib/C/iec_std_lib.h Thu Mar 12 16:36:33 2015 +0100 +++ b/lib/C/iec_std_lib.h Sat Mar 18 22:02:14 2017 +0000 @@ -162,6 +162,16 @@ /*exit(1);*/ } + +/*******************/ +/* Math Operations */ +/*******************/ + +static inline double __expt(double in1, double in2) { + return pow(in1, in2); +} + + /*******************************/ /* Time normalization function */ /*******************************/ @@ -236,7 +246,7 @@ /* 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! +/* 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; @@ -308,7 +318,7 @@ days += __isleap(dt.tm_year) ? 366 : 365; } dt.tm_mon = 1; - while (days > __mon_yday[__isleap(dt.tm_year)][dt.tm_mon]) { + while (days >= __mon_yday[__isleap(dt.tm_year)][dt.tm_mon]) { dt.tm_mon += 1; } dt.tm_day = days - __mon_yday[__isleap(dt.tm_year)][dt.tm_mon - 1] + 1; @@ -735,8 +745,12 @@ - #include "iec_std_functions.h" -#include "iec_std_FB.h" + +#ifdef DISABLE_EN_ENO_PARAMETERS + #include "iec_std_FB_no_ENENO.h" +#else + #include "iec_std_FB.h" +#endif #endif /* _IEC_STD_LIB_H */
--- a/main.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/main.cc Sat Mar 18 22:02:14 2017 +0000 @@ -116,12 +116,17 @@ printf(" -p : allow use of forward references (a non-standard extension?)\n"); printf(" -l : use a relaxed datatype equivalence model (a non-standard extension?)\n"); printf(" -s : allow use of safe datatypes (SAFEBOOL, etc.) (defined in PLCOpen Safety)\n"); // PLCopen TC5 "Safety Software Technical Specification - Part 1" v1.0 + printf(" -n : allow use of nested comments (an IEC 61131-3 v3 feature)\n"); printf(" -r : allow use of references (REF_TO, REF, ^, NULL) (an IEC 61131-3 v3 feature)\n"); printf(" -R : allow use of REF_TO ANY datatypes (a non-standard extension!)\n"); printf(" as well as REF_TO in ARRAYs and STRUCTs (a non-standard extension!)\n"); printf(" -a : allow use of non-literals in array size limits (a non-standard extension!)\n"); + printf(" -i : allow POUs with no in out and inout parameters (a non-standard extension!)\n"); + printf(" -b : allow functions returning VOID (a non-standard extension!)\n"); + printf(" -e : disable generation of implicit EN and ENO parameters.\n"); printf(" -c : create conversion functions for enumerated data types\n"); printf(" -O : options for output (code generation) stage. Available options for %s are...\n", cmd); + runtime_options.allow_missing_var_in = false; /* disable: allow definition and invocation of POUs with no input, output and in_out parameters! */ stage4_print_options(); printf("\n"); printf("%s - Copyright (C) 2003-2014 \n" @@ -141,14 +146,17 @@ int path_len; /* Default values for the command line options... */ - runtime_options.pre_parsing = false; /* allow use of forward references (run pre-parsing phase before the definitive parsing phase that builds the AST) */ - runtime_options.safe_extensions = false; /* allow use of SAFExxx datatypes */ - runtime_options.full_token_loc = false; /* error messages specify full token location */ - runtime_options.conversion_functions = false; /* Create a conversion function for derived datatype */ - runtime_options.nested_comments = false; /* Allow the use of nested comments. */ - runtime_options.ref_standard_extensions = false; /* Allow the use of REFerences (keywords REF_TO, REF, DREF, ^, NULL). */ - runtime_options.ref_nonstand_extensions = false; /* Allow the use of non-standard extensions to REF_TO datatypes: REF_TO ANY, and REF_TO in struct elements! */ - runtime_options.nonliteral_in_array_size= false; /* Allow the use of constant non-literals when specifying size of arrays (ARRAY [1..max] OF INT) */ + runtime_options.allow_void_datatype = false; /* disable: allow declaration of functions returning VOID */ + runtime_options.allow_missing_var_in = false; /* disable: allow definition and invocation of POUs with no input, output and in_out parameters! */ + runtime_options.disable_implicit_en_eno = false; /* disable: do not generate EN and ENO parameters */ + runtime_options.pre_parsing = false; /* disable: allow use of forward references (run pre-parsing phase before the definitive parsing phase that builds the AST) */ + runtime_options.safe_extensions = false; /* disable: allow use of SAFExxx datatypes */ + runtime_options.full_token_loc = false; /* disable: error messages specify full token location */ + runtime_options.conversion_functions = false; /* disable: create a conversion function for derived datatype */ + runtime_options.nested_comments = false; /* disable: Allow the use of nested comments. */ + runtime_options.ref_standard_extensions = false; /* disable: Allow the use of REFerences (keywords REF_TO, REF, DREF, ^, NULL). */ + runtime_options.ref_nonstand_extensions = false; /* disable: Allow the use of non-standard extensions to REF_TO datatypes: REF_TO ANY, and REF_TO in struct elements! */ + runtime_options.nonliteral_in_array_size= false; /* disable: Allow the use of constant non-literals when specifying size of arrays (ARRAY [1..max] OF INT) */ runtime_options.includedir = NULL; /* Include directory, where included files will be searched for... */ /* Default values for the command line options... */ @@ -157,7 +165,7 @@ /******************************************/ /* Parse command line options... */ /******************************************/ - while ((optres = getopt(argc, argv, ":nhvfplsrRacI:T:O:")) != -1) { + while ((optres = getopt(argc, argv, ":nehvfplsrRabicI:T:O:")) != -1) { switch(optres) { case 'h': printusage(argv[0]); @@ -173,8 +181,11 @@ runtime_options.ref_nonstand_extensions = true; break; case 'r': runtime_options.ref_standard_extensions = true; break; case 'a': runtime_options.nonliteral_in_array_size = true; break; + case 'b': runtime_options.allow_void_datatype = true; break; + case 'i': runtime_options.allow_missing_var_in = true; break; case 'c': runtime_options.conversion_functions = true; break; case 'n': runtime_options.nested_comments = true; break; + case 'e': runtime_options.disable_implicit_en_eno = true; break; case 'I': /* NOTE: To improve the usability under windows: * We delete last char's path if it ends with "\".
--- a/main.hh Thu Mar 12 16:36:33 2015 +0100 +++ b/main.hh Sat Mar 18 22:02:14 2017 +0000 @@ -40,6 +40,9 @@ typedef struct { /* options specific to stage1_2 */ + bool allow_void_datatype; /* Allow declaration of functions returning VOID */ + bool allow_missing_var_in; /* Allow definition and invocation of POUs with no input, output and in_out parameters! */ + bool disable_implicit_en_eno; /* Disable the generation of implicit EN and ENO parameters on functions and Function Blocks */ bool pre_parsing; /* Support forward references (Run a pre-parsing phase before the defintive parsing phase that builds the AST) */ bool safe_extensions; /* support SAFE_* datatypes defined in PLCOpen TC5 "Safety Software Technical Specification - Part 1" v1.0 */ bool full_token_loc; /* error messages specify full token location */
--- a/stage1_2/Makefile.am Thu Mar 12 16:36:33 2015 +0100 +++ b/stage1_2/Makefile.am Sat Mar 18 22:02:14 2017 +0000 @@ -1,7 +1,9 @@ include ../common.mk +## Flags for yacc syntax parser generator (bison) AM_YFLAGS = -d -AM_LFLAGS = -o$(LEX_OUTPUT_ROOT).c +## Flags for lex lexer generator (flex) +AM_LFLAGS = --warn -o$(LEX_OUTPUT_ROOT).c # Make sure this header file is generated first (by bison), as it is included # by other C++ code that will also be compiled.
--- a/stage1_2/iec_bison.yy Thu Mar 12 16:36:33 2015 +0100 +++ b/stage1_2/iec_bison.yy Sat Mar 18 22:02:14 2017 +0000 @@ -198,12 +198,6 @@ */ extern bool allow_extensible_function_parameters; -/* A global flag used to tell the parser whether to include the full variable location when printing out error messages... */ -extern bool full_token_loc; - -/* A global flag used to tell the parser whether to generate conversion function for enumerated data types. */ -extern bool conversion_functions; - /* A global flag used to tell the parser whether to allow use of DREF and '^' operators (defined in IEC 61131-3 v3) */ extern bool allow_ref_dereferencing; @@ -379,6 +373,32 @@ %type <leaf> prev_declared_derived_function_block_name %type <leaf> prev_declared_program_type_name +/* Tokens used to help resolve a reduce/reduce conflict */ +/* The mentioned conflict only arises due to a non-standard feature added to matiec. + * Namely, the permission to call functions returning VOID as an ST statement. + * e.g.: FUNCTION foo: VOID + * VAR_INPUT i: INT; END_VAR; + * ... + * END_FUNCTION + * + * FUNCTION BAR: BOOL + * VAR b: bool; END_VAR + * foo(i:=42); <--- Calling foo outside an expression. Function invocation is considered an ST statement!! + * END_FUNCTION + * + * The above function invocation may also be reduced to a formal IL function invocation, so we get a + * reduce/reduce conflict to st_statement_list/instruction_list (or something equivalent). + * + * We solve this by having flex determine if it is ST or IL invocation (ST ends with a ';' !!). + * At the start of a function/FB/program body, flex will tell bison whether to expect ST or IL code! + * This is why we need the following two tokens! + * + * NOTE: flex was already determing whther it was parsing ST or IL code as it can only send + * EOL tokens when parsing IL. However, did this silently without telling bison about this. + * Now, it does + */ +%token start_ST_body_token +%token start_IL_body_token @@ -656,6 +676,9 @@ %token TIME_OF_DAY %token TOD +/* A non-standard extension! */ +%token VOID + /******************************************************/ /* Symbols defined in */ /* "Safety Software Technical Specification, */ @@ -2573,7 +2596,7 @@ data_type_declaration: TYPE type_declaration_list END_TYPE - {$$ = new data_type_declaration_c($2, locloc(@$)); if (conversion_functions) include_string((create_enumtype_conversion_functions_c::get_declaration($$)).c_str());} + {$$ = new data_type_declaration_c($2, locloc(@$)); if (runtime_options.conversion_functions) include_string((create_enumtype_conversion_functions_c::get_declaration($$)).c_str());} /* ERROR_CHECK_BEGIN */ | TYPE END_TYPE {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no data type declared in data type(s) declaration."); yynerrs++;} @@ -5001,7 +5024,7 @@ /* POST_PARSING and STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ | function_name_declaration ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION {$$ = new function_declaration_c($1, $3, $4, $5, locloc(@$)); - add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ + if (!runtime_options.disable_implicit_en_eno) add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ variable_name_symtable.pop(); direct_variable_symtable.pop(); library_element_symtable.insert($1, prev_declared_derived_function_name_token); @@ -5009,7 +5032,15 @@ /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ | function_name_declaration ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION {$$ = new function_declaration_c($1, $3, $4, $5, locloc(@$)); - add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ + if (!runtime_options.disable_implicit_en_eno) add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ + variable_name_symtable.pop(); + direct_variable_symtable.pop(); + library_element_symtable.insert($1, prev_declared_derived_function_name_token); + } +/* | FUNCTION derived_function_name ':' VOID io_OR_function_var_declarations_list function_body END_FUNCTION */ +| function_name_declaration ':' VOID io_OR_function_var_declarations_list function_body END_FUNCTION + {$$ = new function_declaration_c($1, new void_type_name_c(locloc(@3)), $4, $5, locloc(@$)); + if (!runtime_options.disable_implicit_en_eno) add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ variable_name_symtable.pop(); direct_variable_symtable.pop(); library_element_symtable.insert($1, prev_declared_derived_function_name_token); @@ -5178,8 +5209,8 @@ function_body: - statement_list {$$ = $1;} /* if we leave it for the default action we get a type clash! */ -| instruction_list {$$ = $1;} /* if we leave it for the default action we get a type clash! */ + start_ST_body_token statement_list {$$ = $2;} +| start_IL_body_token instruction_list {$$ = $2;} /* | ladder_diagram | function_block_diagram @@ -5220,7 +5251,7 @@ /* POST_PARSING: The rules expected to be applied after the preparser runs. Will only run if pre-parsing command line option is ON. */ | FUNCTION_BLOCK prev_declared_derived_function_block_name io_OR_other_var_declarations_list function_block_body END_FUNCTION_BLOCK {$$ = new function_block_declaration_c($2, $3, $4, locloc(@$)); - add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ + if (!runtime_options.disable_implicit_en_eno) add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ /* Clear the variable_name_symtable. Since we have finished parsing the function block, * the variable names are now out of scope, so are no longer valid! */ @@ -5231,7 +5262,7 @@ | FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list function_block_body END_FUNCTION_BLOCK {$$ = new function_block_declaration_c($2, $3, $4, locloc(@$)); library_element_symtable.insert($2, prev_declared_derived_function_block_name_token); - add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ + if (!runtime_options.disable_implicit_en_eno) add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ /* Clear the variable_name_symtable. Since we have finished parsing the function block, * the variable names are now out of scope, so are no longer valid! */ @@ -5252,7 +5283,7 @@ {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable(s) declared and body defined in function block declaration."); yynerrs++;} */ | FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list function_block_body END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "no variable(s) declared and body defined in function block declaration."); yynerrs++;} + {$$ = NULL; print_err_msg(locf(@1), locl(@2), "expecting END_FUNCTION_BLOCK before end of file."); yynerrs++;} | FUNCTION_BLOCK error END_FUNCTION_BLOCK {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in function block declaration."); yyerrok;} /* ERROR_CHECK_END */ @@ -5361,9 +5392,21 @@ function_block_body: - statement_list {$$ = $1;} -| instruction_list {$$ = $1;} -| sequential_function_chart {$$ = $1;} + /* NOTE: start_ST_body_token is a dummy token generated by flex when it determines it is starting to parse a POU body in ST + * start_IL_body_token is a dummy token generated by flex when it determines it is starting to parse a POU body in IL + * These tokens help remove a reduce/reduce conflict in bison, between a formal function invocation in IL, and a + * function invocation used as a statement (a non-standard extension added to matiec) + * e.g: FUNCTION_BLOCK foo + * VAR ... END_VAR + * func_returning_void(in1 := 3 + * ); --> only the presence or absence of ';' will determine whether this is a IL or ST + * function invocation. (In standard ST this would be ilegal, in matiec we allow it + * when activated by a command line option) + * END_FUNCTION + */ + start_ST_body_token statement_list {$$ = $2;} +| start_IL_body_token instruction_list {$$ = $2;} +| sequential_function_chart {$$ = $1;} /* | ladder_diagram | function_block_diagram @@ -5803,17 +5846,17 @@ transition_condition: - ':' eol_list simple_instr_list - {$$ = new transition_condition_c($3, NULL, locloc(@$));} + start_IL_body_token ':' eol_list simple_instr_list + {$$ = new transition_condition_c($4, NULL, locloc(@$));} | ASSIGN expression ';' {$$ = new transition_condition_c(NULL, $2, locloc(@$));} /* ERROR_CHECK_BEGIN */ -| eol_list simple_instr_list - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing before IL condition in transition declaration."); yynerrs++;} -| ':' eol_list error +| start_IL_body_token eol_list simple_instr_list + {$$ = NULL; print_err_msg(locl(@2), locf(@3), "':' missing before IL condition in transition declaration."); yynerrs++;} +| start_IL_body_token ':' eol_list error {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no instructions defined in IL condition of transition declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid instructions in IL condition of transition declaration."); yyclearin;} + if (is_current_syntax_token()) {print_err_msg(locl(@3), locf(@4), "no instructions defined in IL condition of transition declaration.");} + else {print_err_msg(locf(@4), locl(@4), "invalid instructions in IL condition of transition declaration."); yyclearin;} yyerrok; } | ASSIGN ';' @@ -7812,11 +7855,16 @@ {$$ = new function_invocation_c($1, $3, NULL, locloc(@$)); if (NULL == dynamic_cast<poutype_identifier_c*>($1)) ERROR;} // $1 should be a poutype_identifier_c | function_name_no_NOT_clashes '(' param_assignment_nonformal_list ')' {$$ = new function_invocation_c($1, NULL, $3, locloc(@$)); if (NULL == dynamic_cast<poutype_identifier_c*>($1)) ERROR;} // $1 should be a poutype_identifier_c +| function_name_no_NOT_clashes '(' ')' + {if (NULL == dynamic_cast<poutype_identifier_c*>($1)) ERROR; // $1 should be a poutype_identifier_c + if (runtime_options.allow_missing_var_in) + {$$ = new function_invocation_c($1, NULL, NULL, locloc(@$));} + else + {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no parameter defined in function invocation of ST expression."); yynerrs++;} + } /* ERROR_CHECK_BEGIN */ | function_name_no_NOT_clashes param_assignment_formal_list ')' {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'(' missing after function name in ST expression."); yynerrs++;} -| function_name_no_NOT_clashes '(' ')' - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no parameter defined in function invocation of ST expression."); yynerrs++;} | function_name_no_NOT_clashes '(' error ')' {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid parameter(s) defined in function invocation of ST expression."); yyerrok;} | function_name_no_NOT_clashes '(' param_assignment_formal_list error @@ -7857,6 +7905,15 @@ | subprogram_control_statement | selection_statement | iteration_statement +| function_invocation + { /* This is a non-standard extension (calling a function outside an ST expression!) */ + /* Only allow this if command line option has been selected... */ + $$ = $1; + if (!runtime_options.allow_void_datatype) { + print_err_msg(locf(@1), locl(@1), "Function invocation in ST code is not allowed outside an expression. To allow this non-standard syntax, activate the apropriate command line option."); + yynerrs++; + } + } ; @@ -8443,10 +8500,6 @@ */ bool allow_extensible_function_parameters = false; -/* A global flag indicating whether to include the full variable location when printing out error messages... */ -bool full_token_loc; -/* A global flag used to tell the parser whether to generate conversion function for enumerated data types. */ -bool conversion_functions = false; /* A global flag used to tell the parser whether to allow use of DREF and '^' operators (defined in IEC 61131-3 v3) */ bool allow_ref_dereferencing; /* A global flag used to tell the parser whether to allow use of REF_TO ANY datatypes (non-standard extension) */ @@ -8522,7 +8575,7 @@ if (first_filename == NULL) first_filename = unknown_file; if ( last_filename == NULL) last_filename = unknown_file; - if (full_token_loc) { + if (runtime_options.full_token_loc) { if (first_filename == last_filename) fprintf(stderr, "%s:%d-%d..%d-%d: error: %s\n", first_filename, first_line, first_column, last_line, last_column, additional_error_msg); else @@ -8708,8 +8761,6 @@ allow_function_overloading = true; allow_extensible_function_parameters = true; - full_token_loc = runtime_options.full_token_loc; - conversion_functions = runtime_options.conversion_functions; allow_ref_dereferencing = runtime_options.ref_standard_extensions; allow_ref_to_any = runtime_options.ref_nonstand_extensions; allow_ref_to_in_derived_datatypes = runtime_options.ref_nonstand_extensions; @@ -8745,8 +8796,6 @@ allow_function_overloading = false; allow_extensible_function_parameters = false; - full_token_loc = runtime_options.full_token_loc; - conversion_functions = runtime_options.conversion_functions; allow_ref_dereferencing = runtime_options.ref_standard_extensions; allow_ref_to_any = runtime_options.ref_nonstand_extensions; allow_ref_to_in_derived_datatypes = runtime_options.ref_nonstand_extensions;
--- a/stage1_2/iec_flex.ll Thu Mar 12 16:36:33 2015 +0100 +++ b/stage1_2/iec_flex.ll Sat Mar 18 22:02:14 2017 +0000 @@ -151,17 +151,6 @@ -/* We will not be using unput() in our flex code... */ -/* NOTE: it seems that this #define is no longer needed, It has been - * replaced by %option nounput. - * Should we simply delete it? - * For now leave it in, in case someone is using an old version of flex. - * In any case, the most harm that can result in a warning message - * when compiling iec.flex.c: - * warning: ‘void yyunput(int, char*)’ defined but not used - */ -#define YY_NO_UNPUT - /* Variable defined by the bison parser. * It must be initialised with the location * of the token being parsed. @@ -237,6 +226,16 @@ void include_file(const char *include_filename); +/* The body_state tries to find a ';' before a END_PROGRAM, END_FUNCTION or END_FUNCTION_BLOCK or END_ACTION + * To do so, it must ignore comments and pragmas. This means that we cannot do this in a signle lex rule. + * However, we must store any text we consume in every rule, so we can push it back into the buffer + * once we have decided if we are parsing ST or IL code. The following functions manage that buffer used by + * the body_state. + */ +void append_bodystate_buffer(const char *yytext); +void unput_bodystate_buffer(void); +int isempty_bodystate_buffer(void); + int GetNextChar(char *b, int maxBuffer); %} @@ -969,20 +968,29 @@ <INITIAL>{file_include_pragma} unput_text(0); yy_push_state(include_beg); /* Pragmas sent to syntax analyser (bison) */ -{disable_code_generation_pragma} return disable_code_generation_pragma_token; -{enable_code_generation_pragma} return enable_code_generation_pragma_token; -<body_state,vardecl_list_state>{disable_code_generation_pragma} return disable_code_generation_pragma_token; -<body_state,vardecl_list_state>{enable_code_generation_pragma} return enable_code_generation_pragma_token; - + /* NOTE: In the vardecl_list_state we only process the pragmas between two consecutive VAR .. END_VAR blocks. + * We do not process any pragmas trailing after the last END_VAR. We leave that to the body_state. + * This is because the pragmas are stored in a statement_list or instruction_list (in bison), + * but these lists must start with the special tokens start_IL_body_token/start_ST_body_token. + * This means that these special tokens must be generated (by the body_state) before processing + * the pragme => we cannot process the trailing pragmas in the vardecl_list_state state. + */ +{disable_code_generation_pragma} return disable_code_generation_pragma_token; +{enable_code_generation_pragma} return enable_code_generation_pragma_token; +<vardecl_list_state>{disable_code_generation_pragma}/(VAR) return disable_code_generation_pragma_token; +<vardecl_list_state>{enable_code_generation_pragma}/(VAR) return enable_code_generation_pragma_token; +<body_state>{disable_code_generation_pragma} append_bodystate_buffer(yytext); /* in body state we do not process any tokens, we simply store them for later processing! */ +<body_state>{enable_code_generation_pragma} append_bodystate_buffer(yytext); /* in body state we do not process any tokens, we simply store them for later processing! */ /* Any other pragma we find, we just pass it up to the syntax parser... */ /* Note that the <body_state> state is exclusive, so we have to include it here too. */ +<body_state>{pragma} append_bodystate_buffer(yytext); /* in body state we do not process any tokens, we simply store them for later processing! */ {pragma} {/* return the pragmma without the enclosing '{' and '}' */ int cut = yytext[1]=='{'?2:1; yytext[strlen(yytext)-cut] = '\0'; yylval.ID=strdup(yytext+cut); return pragma_token; } -<body_state,vardecl_list_state>{pragma} {/* return the pragmma without the enclosing '{' and '}' */ +<vardecl_list_state>{pragma}/(VAR) {/* return the pragmma without the enclosing '{' and '}' */ int cut = yytext[1]=='{'?2:1; yytext[strlen(yytext)-cut] = '\0'; yylval.ID=strdup(yytext+cut); @@ -1070,7 +1078,30 @@ /* INITIAL -> header_state */ <INITIAL>{ - /* NOTE: how about functions that do not declare variables, and go directly to the body_state??? +FUNCTION{st_whitespace} if (get_preparse_state()) BEGIN(get_pou_name_state); else {BEGIN(header_state);/* printf("\nChanging to header_state\n"); */} return FUNCTION; +FUNCTION_BLOCK{st_whitespace} if (get_preparse_state()) BEGIN(get_pou_name_state); else {BEGIN(header_state);/* printf("\nChanging to header_state\n"); */} return FUNCTION_BLOCK; +PROGRAM{st_whitespace} if (get_preparse_state()) BEGIN(get_pou_name_state); else {BEGIN(header_state);/* printf("\nChanging to header_state\n"); */} return PROGRAM; +CONFIGURATION{st_whitespace} if (get_preparse_state()) BEGIN(get_pou_name_state); else {BEGIN(config_state);/* printf("\nChanging to config_state\n"); */} return CONFIGURATION; +} + +<get_pou_name_state>{ +{identifier} BEGIN(ignore_pou_state); yylval.ID=strdup(yytext); return identifier_token; +. BEGIN(ignore_pou_state); unput_text(0); +} + +<ignore_pou_state>{ +END_FUNCTION unput_text(0); BEGIN(INITIAL); +END_FUNCTION_BLOCK unput_text(0); BEGIN(INITIAL); +END_PROGRAM unput_text(0); BEGIN(INITIAL); +END_CONFIGURATION unput_text(0); BEGIN(INITIAL); +.|\n {}/* Ignore text inside POU! (including the '\n' character!)) */ +} + + + /* header_state -> (vardecl_list_state) */ + /* NOTE: This transition assumes that all POUs with code (Function, FB, and Program) will always contain + * at least one VAR_XXX block. + * How about functions that do not declare variables, and go directly to the body_state??? * - According to Section 2.5.1.3 (Function Declaration), item 2 in the list, a FUNCTION * must have at least one input argument, so a correct declaration will have at least * one VAR_INPUT ... VAR_END construct! @@ -1084,44 +1115,22 @@ * All the above means that we needn't worry about PROGRAMs, FUNCTIONs or * FUNCTION_BLOCKs that do not have at least one VAR_END before the body_state. * If the code has an error, and no VAR_END before the body, we will simply - * continue in the <vardecl_state> state, untill the end of the FUNCTION, FUNCTION_BLOCK + * continue in the <vardecl_state> state, until the end of the FUNCTION, FUNCTION_BLOCK * or PROGAM. + * + * WARNING: From 2016-05 (May 2016) onwards, matiec supports a non-standard option in which a Function + * may be declared with no Input, Output or IN_OUT variables. This means that the above + * assumption is no longer valid. + * To make things simpler (i.e. so we do not need to change the transition conditions in the flex state machine), + * when using this non-standard extension matiec requires that Functions must include at least one + * VAR .. END_VAR block. This implies that the above assumption remains valid! + * This limitation of requiring a VAR .. END_VAR block is not really very limiting, as a function + * with no input and output parameters will probably need to do some 'work', and for that it will + * probably need some local variables declared in a VAR .. END_VAR block. + * Note however that in the extreme it might make sense to have a function with no variables whatsoever + * (e.g.: a function that only calls other functions that all return VOID - another non standard extension!). + * For now we do not consider this!! */ - -FUNCTION{st_whitespace} if (get_preparse_state()) BEGIN(get_pou_name_state); else BEGIN(header_state); return FUNCTION; -FUNCTION_BLOCK{st_whitespace} if (get_preparse_state()) BEGIN(get_pou_name_state); else BEGIN(header_state); return FUNCTION_BLOCK; -PROGRAM{st_whitespace} if (get_preparse_state()) BEGIN(get_pou_name_state); else BEGIN(header_state); return PROGRAM; -CONFIGURATION{st_whitespace} if (get_preparse_state()) BEGIN(get_pou_name_state); else BEGIN(config_state); return CONFIGURATION; -} - -<get_pou_name_state>{ -{identifier} BEGIN(ignore_pou_state); yylval.ID=strdup(yytext); return identifier_token; -. BEGIN(ignore_pou_state); unput_text(0); -} - -<ignore_pou_state>{ -END_FUNCTION unput_text(0); BEGIN(INITIAL); -END_FUNCTION_BLOCK unput_text(0); BEGIN(INITIAL); -END_PROGRAM unput_text(0); BEGIN(INITIAL); -END_CONFIGURATION unput_text(0); BEGIN(INITIAL); -.|\n {}/* Ignore text inside POU! (including the '\n' character!)) */ -} - - /* INITIAL -> body_state */ - /* required if the function, program, etc.. has no VAR block! */ - /* We comment it out since the standard does not allow this. */ - /* NOTE: Even if we were to include the following code, it */ - /* would have no effect whatsoever since the above */ - /* rules will take precendence! */ - /* -<INITIAL>{ -FUNCTION BEGIN(body_state); return FUNCTION; -FUNCTION_BLOCK BEGIN(body_state); return FUNCTION_BLOCK; -PROGRAM BEGIN(body_state); return PROGRAM; -} - */ - - /* header_state -> (vardecl_list_state) */ <header_state>{ VAR | /* execute the next rule's action, i.e. fall-through! */ VAR_INPUT | @@ -1131,7 +1140,7 @@ VAR_GLOBAL | VAR_TEMP | VAR_CONFIG | -VAR_ACCESS unput_text(0); BEGIN(vardecl_list_state); +VAR_ACCESS unput_text(0); /* printf("\nChanging to vardecl_list_state\n") */; BEGIN(vardecl_list_state); } @@ -1147,11 +1156,11 @@ VAR_ACCESS | VAR unput_text(0); yy_push_state(vardecl_state); -END_FUNCTION unput_text(0); BEGIN(INITIAL); -END_FUNCTION_BLOCK unput_text(0); BEGIN(INITIAL); -END_PROGRAM unput_text(0); BEGIN(INITIAL); - -. unput_text(0); yy_push_state(body_state); /* anything else, just change to body_state! */ +END_FUNCTION unput_text(0); BEGIN(INITIAL); +END_FUNCTION_BLOCK unput_text(0); BEGIN(INITIAL); +END_PROGRAM unput_text(0); BEGIN(INITIAL); + +. unput_text(0); yy_push_state(body_state); //printf("\nChanging to body_state\n");/* anything else, just change to body_state! */ } @@ -1163,41 +1172,51 @@ /* body_state -> (il_state | st_state | sfc_state) */ <body_state>{ -INITIAL_STEP unput_text(0); BEGIN(sfc_state); - -{qualified_identifier} unput_text(0); BEGIN(st_state); /* will always be followed by '[' for an array access, or ':=' as the left hand of an assignment statement */ -{direct_variable_standard} unput_text(0); BEGIN(st_state); /* will always be followed by ':=' as the left hand of an assignment statement */ - -RETURN unput_text(0); BEGIN(st_state); -IF unput_text(0); BEGIN(st_state); -CASE unput_text(0); BEGIN(st_state); -FOR unput_text(0); BEGIN(st_state); -WHILE unput_text(0); BEGIN(st_state); -EXIT unput_text(0); BEGIN(st_state); -REPEAT unput_text(0); BEGIN(st_state); - - /* ':=' occurs only in transitions, and not Function or FB bodies! */ -:= unput_text(0); BEGIN(st_state); - -{identifier} {int token = get_identifier_token(yytext); - if ((token == prev_declared_fb_name_token) || (token == prev_declared_variable_name_token)) { - /* the code has a call to a function block OR has an assingment with a variable as the lvalue */ - unput_text(0); BEGIN(st_state); - } else - if (token == prev_declared_derived_function_name_token) { - /* the code has a call to a function - must be IL */ - unput_text(0); BEGIN(il_state); - } else { - /* Might be a lable in IL, or a bug in ST/IL code. We jump to IL */ - unput_text(0); BEGIN(il_state); - } - } - -. unput_text(0); BEGIN(il_state); /* Don't know what it could be. This is most likely a bug. Let's just to a random state... */ +{st_whitespace} {/* In body state we do not process any tokens, + * we simply store them for later processing! + * NOTE: all whitespace in the begining + * of body_state must be removed so we can + * detect ':=' in the beginning of TRANSACTION + * conditions preceded by whitespace. + * => only add to bodystate_buffer when not in beginning. + */ + if (!isempty_bodystate_buffer()) + append_bodystate_buffer(yytext); + } + /* 'INITIAL_STEP' always used in beginning of SFCs !! */ +INITIAL_STEP { if (isempty_bodystate_buffer()) {unput_text(0); BEGIN(sfc_state);} + else {append_bodystate_buffer(yytext);} + } + + /* ':=', at the very beginning of a 'body', occurs only in transitions and not Function, FB, or Program bodies! */ +:= { if (isempty_bodystate_buffer()) {unput_text(0); BEGIN(st_state);} /* We do _not_ return a start_ST_body_token here, as bison does not expect it! */ + else {append_bodystate_buffer(yytext);} + } + + /* check if ';' occurs before an END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM, END_ACTION or END_TRANSITION. (If true => we are parsing ST; If false => parsing IL). */ +END_ACTION | /* execute the next rule's action, i.e. fall-through! */ +END_FUNCTION | +END_FUNCTION_BLOCK | +END_TRANSITION | +END_PROGRAM { append_bodystate_buffer(yytext); unput_bodystate_buffer(); BEGIN(il_state); /*printf("returning start_IL_body_token\n");*/ return start_IL_body_token;} +.|\n { append_bodystate_buffer(yytext); + if (strcmp(yytext, ";") == 0) + {unput_bodystate_buffer(); BEGIN(st_state); /*printf("returning start_ST_body_token\n");*/ return start_ST_body_token;} + } + /* The following rules are not really necessary. They just make compilation faster in case the ST Statement List starts with one fot he following... */ +RETURN | /* execute the next rule's action, i.e. fall-through! */ +IF | +CASE | +FOR | +WHILE | +EXIT | +REPEAT { if (isempty_bodystate_buffer()) {unput_text(0); BEGIN(st_state); return start_ST_body_token;} + else {append_bodystate_buffer(yytext);} + } + } /* end of body_state lexical parser */ - /* (il_state | st_state) -> pop to $previous_state (vardecl_list_state or sfc_state) */ <il_state,st_state>{ END_FUNCTION yy_pop_state(); unput_text(0); @@ -1225,8 +1244,12 @@ /* NOTE: pragmas are handled right at the beginning... */ /* The whitespace */ -<INITIAL,header_state,config_state,body_state,vardecl_list_state,vardecl_state,st_state,sfc_state,task_init_state,sfc_qualifier_state>{st_whitespace} /* Eat any whitespace */ +<INITIAL,header_state,config_state,vardecl_list_state,vardecl_state,st_state,sfc_state,task_init_state,sfc_qualifier_state>{st_whitespace} /* Eat any whitespace */ <il_state>{il_whitespace} /* Eat any whitespace */ + /* NOTE: Due to the need of having the following rule have higher priority, + * the following rule was moved to an earlier position in this file. +<body_state>{st_whitespace} {...} + */ /* The comments */ <get_pou_name_state,ignore_pou_state,body_state,vardecl_list_state>{comment_beg} yy_push_state(comment_state); @@ -1265,6 +1288,14 @@ * We solve this by NOT testing for function names here, and * handling this function and keyword clash in bison! */ + /* NOTE: The following code has been commented out as most users do not want matiec + * to allow the use of 'R1', 'IN' ... IL operators as identifiers, + * even though a literal reading of the standard allows this. + * We could add this as a commadnd line option, but it is not yet done. + * For now we just comment out the code, but leave it the commented code + * in so we can re-activate quickly (without having to go through old commits + * in the mercurial repository to figure out the missing code! + */ /* {identifier} {int token = get_identifier_token(yytext); // fprintf(stderr, "flex: analysing identifier '%s'...", yytext); @@ -1378,6 +1409,10 @@ DATE_AND_TIME return DATE_AND_TIME; /* Keyword (Data Type) */ TIME_OF_DAY return TIME_OF_DAY; /* Keyword (Data Type) */ + /* A non-standard extension! */ +VOID {if (runtime_options.allow_void_datatype) {return VOID;} else {REJECT;}} + + /*****************************************************************/ /* Keywords defined in "Safety Software Technical Specification" */ /*****************************************************************/ @@ -1480,28 +1515,49 @@ /***********************/ /* B 1.5.1 - Functions */ /***********************/ -FUNCTION return FUNCTION; /* Keyword */ -END_FUNCTION return END_FUNCTION; /* Keyword */ -VAR return VAR; /* Keyword */ -CONSTANT return CONSTANT; /* Keyword */ + /* Note: The following END_FUNCTION rule includes a BEGIN(INITIAL); command. + * This is necessary in case the input program being parsed has syntax errors that force + * flex's main state machine to never change to the il_state or the st_state + * after changing to the body_state. + * Ths BEGIN(INITIAL) command forces the flex state machine to re-synchronise with + * the input stream even in the presence of buggy code! + */ +FUNCTION return FUNCTION; /* Keyword */ +END_FUNCTION BEGIN(INITIAL); return END_FUNCTION; /* Keyword */ /* see Note above */ +VAR return VAR; /* Keyword */ +CONSTANT return CONSTANT; /* Keyword */ /*****************************/ /* B 1.5.2 - Function Blocks */ /*****************************/ -FUNCTION_BLOCK return FUNCTION_BLOCK; /* Keyword */ -END_FUNCTION_BLOCK return END_FUNCTION_BLOCK; /* Keyword */ -VAR_TEMP return VAR_TEMP; /* Keyword */ -VAR return VAR; /* Keyword */ -NON_RETAIN return NON_RETAIN; /* Keyword */ -END_VAR return END_VAR; /* Keyword */ + /* Note: The following END_FUNCTION_BLOCK rule includes a BEGIN(INITIAL); command. + * This is necessary in case the input program being parsed has syntax errors that force + * flex's main state machine to never change to the il_state or the st_state + * after changing to the body_state. + * Ths BEGIN(INITIAL) command forces the flex state machine to re-synchronise with + * the input stream even in the presence of buggy code! + */ +FUNCTION_BLOCK return FUNCTION_BLOCK; /* Keyword */ +END_FUNCTION_BLOCK BEGIN(INITIAL); return END_FUNCTION_BLOCK; /* Keyword */ /* see Note above */ +VAR_TEMP return VAR_TEMP; /* Keyword */ +VAR return VAR; /* Keyword */ +NON_RETAIN return NON_RETAIN; /* Keyword */ +END_VAR return END_VAR; /* Keyword */ /**********************/ /* B 1.5.3 - Programs */ /**********************/ -PROGRAM return PROGRAM; /* Keyword */ -END_PROGRAM return END_PROGRAM; /* Keyword */ + /* Note: The following END_PROGRAM rule includes a BEGIN(INITIAL); command. + * This is necessary in case the input program being parsed has syntax errors that force + * flex's main state machine to never change to the il_state or the st_state + * after changing to the body_state. + * Ths BEGIN(INITIAL) command forces the flex state machine to re-synchronise with + * the input stream even in the presence of buggy code! + */ +PROGRAM return PROGRAM; /* Keyword */ +END_PROGRAM BEGIN(INITIAL); return END_PROGRAM; /* Keyword */ /* see Note above */ /********************************************/ @@ -1549,21 +1605,28 @@ /********************************/ /* B 1.7 Configuration elements */ /********************************/ -CONFIGURATION return CONFIGURATION; /* Keyword */ -END_CONFIGURATION return END_CONFIGURATION; /* Keyword */ -TASK return TASK; /* Keyword */ -RESOURCE return RESOURCE; /* Keyword */ -ON return ON; /* Keyword */ -END_RESOURCE return END_RESOURCE; /* Keyword */ -VAR_CONFIG return VAR_CONFIG; /* Keyword */ -VAR_ACCESS return VAR_ACCESS; /* Keyword */ -END_VAR return END_VAR; /* Keyword */ -WITH return WITH; /* Keyword */ -PROGRAM return PROGRAM; /* Keyword */ -RETAIN return RETAIN; /* Keyword */ -NON_RETAIN return NON_RETAIN; /* Keyword */ -READ_WRITE return READ_WRITE; /* Keyword */ -READ_ONLY return READ_ONLY; /* Keyword */ + /* Note: The following END_CONFIGURATION rule will never get to be used, as we have + * another identical rule above (closer to the rules handling the transitions + * of the main state machine) that will always execute before this one. + * Note: The following END_CONFIGURATION rule includes a BEGIN(INITIAL); command. + * This is nt strictly necessary, but I place it here so it follwos the same + * pattern used in END_FUNCTION, END_PROGRAM, and END_FUNCTION_BLOCK + */ +CONFIGURATION return CONFIGURATION; /* Keyword */ +END_CONFIGURATION BEGIN(INITIAL); return END_CONFIGURATION; /* Keyword */ /* see 2 Notes above! */ +TASK return TASK; /* Keyword */ +RESOURCE return RESOURCE; /* Keyword */ +ON return ON; /* Keyword */ +END_RESOURCE return END_RESOURCE; /* Keyword */ +VAR_CONFIG return VAR_CONFIG; /* Keyword */ +VAR_ACCESS return VAR_ACCESS; /* Keyword */ +END_VAR return END_VAR; /* Keyword */ +WITH return WITH; /* Keyword */ +PROGRAM return PROGRAM; /* Keyword */ +RETAIN return RETAIN; /* Keyword */ +NON_RETAIN return NON_RETAIN; /* Keyword */ +READ_WRITE return READ_WRITE; /* Keyword */ +READ_ONLY return READ_ONLY; /* Keyword */ /* PRIORITY, SINGLE and INTERVAL are not a keywords, so we only return them when * it is explicitly required and we are not expecting any identifiers @@ -2013,6 +2076,47 @@ +/* The body_state tries to find a ';' before a END_PROGRAM, END_FUNCTION or END_FUNCTION_BLOCK or END_ACTION + * To do so, it must ignore comments and pragmas. This means that we cannot do this in a signle lex rule. + * However, we must store any text we consume in every rule, so we can push it back into the buffer + * once we have decided if we are parsing ST or IL code. The following functions manage that buffer used by + * the body_state. + */ +/* The buffer used by the body_state state */ +char *bodystate_buffer = NULL; + +/* append text to bodystate_buffer */ +void append_bodystate_buffer(const char *text) { + //printf("<<<append_bodystate_buffer>>> %d <%s><%s>\n", bodystate_buffer, text, (NULL != bodystate_buffer)?bodystate_buffer:"NULL"); + long int old_len = 0; + if (NULL != bodystate_buffer) old_len = strlen(bodystate_buffer); + bodystate_buffer = (char *)realloc(bodystate_buffer, old_len + strlen(text) + 1); + if (NULL == bodystate_buffer) ERROR; + strcpy(bodystate_buffer + old_len, text); + //printf("=<%s> %d %d\n", (NULL != bodystate_buffer)?bodystate_buffer:NULL, old_len + strlen(text) + 1, bodystate_buffer); +} + +/* Return all data in bodystate_buffer back to flex, and empty bodystate_buffer. */ +void unput_bodystate_buffer(void) { + if (NULL == bodystate_buffer) ERROR; + //printf("<<<unput_bodystate_buffer>>>\n%s\n", bodystate_buffer); + + for (long int i = strlen(bodystate_buffer)-1; i >= 0; i--) + unput(bodystate_buffer[i]); + + free(bodystate_buffer); + bodystate_buffer = NULL; +} + + +/* Return true if bodystate_buffer is empty */ +int isempty_bodystate_buffer(void) { + return (NULL == bodystate_buffer); +} + + + + /* Called by flex when it reaches the end-of-file */ int yywrap(void) {
--- a/stage3/Makefile.am Thu Mar 12 16:36:33 2015 +0100 +++ b/stage3/Makefile.am Sat Mar 18 22:02:14 2017 +0000 @@ -12,6 +12,7 @@ datatype_functions.cc \ lvalue_check.cc \ array_range_check.cc \ + case_elements_check.cc \ constant_folding.cc \ declaration_check.cc \ enum_declaration_check.cc \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/case_elements_check.cc Sat Mar 18 22:02:14 2017 +0000 @@ -0,0 +1,249 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2015 Mario de Sousa (msousa@fe.up.pt) + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +/* + * An IEC 61131-3 compiler. + * + * Based on the + * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) + * + */ + + +/* + * Case Options Checking: + * - Check whether the options in a case statement are repeated, either directly, or in a range. + * For example: + * case var of + * 1: ... <- OK + * 2: ... <- OK + * 1: ... <- OK (not an error), but produce a warning due to repeated '1'! + * 0..8: ...<- OK (not an error), but produce a warning cue to repeated '1' and '2'! + */ + + +#include "case_elements_check.hh" + + +#define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order) ? (symbol1) : (symbol2)) +#define LAST_(symbol1, symbol2) (((symbol1)->last_order > (symbol2)->last_order) ? (symbol1) : (symbol2)) + +#define STAGE3_ERROR(error_level, symbol1, symbol2, ...) { \ + if (current_display_error_level >= error_level) { \ + fprintf(stderr, "%s:%d-%d..%d-%d: error: ", \ + FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\ + LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column);\ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + error_count++; \ + } \ +} + + +#define STAGE3_WARNING(symbol1, symbol2, ...) { \ + fprintf(stderr, "%s:%d-%d..%d-%d: warning: ", \ + FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\ + LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column);\ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + warning_found = true; \ +} + + +#define GET_CVALUE(dtype, symbol) ((symbol)->const_value._##dtype.get()) +#define VALID_CVALUE(dtype, symbol) ((symbol)->const_value._##dtype.is_valid()) + + + + +case_elements_check_c::case_elements_check_c(symbol_c *ignore) { + warning_found = false; + error_count = 0; + current_display_error_level = 0; +} + + + +case_elements_check_c::~case_elements_check_c(void) { +} + + + +int case_elements_check_c::get_error_count() { + return error_count; +} + + + + +/* compare two integer constants, and determins if s1 < s2 */ +static bool less_than(symbol_c *s1, symbol_c *s2) { + if ( (VALID_CVALUE( int64, s1)) + && (VALID_CVALUE( int64, s2)) + && ( GET_CVALUE( int64, s1) < GET_CVALUE( int64, s2))) + return true; + + if ( (VALID_CVALUE(uint64, s1)) + && (VALID_CVALUE(uint64, s2)) + && ( GET_CVALUE(uint64, s1) < GET_CVALUE(uint64, s2))) + return true; + + if ( (VALID_CVALUE( int64, s1)) + && (VALID_CVALUE(uint64, s2)) + && ( GET_CVALUE( int64, s1) < 0)) + return true; + + return false; +} + + + +void case_elements_check_c::check_subr_subr(symbol_c *s1, symbol_c *s2) { + subrange_c *sub1 = dynamic_cast<subrange_c *>(s1); + subrange_c *sub2 = dynamic_cast<subrange_c *>(s2); + + if ((NULL == sub1) || (NULL == sub2)) return; + symbol_c *l1 = sub1->lower_limit; + symbol_c *u1 = sub1->upper_limit; + symbol_c *l2 = sub2->lower_limit; + symbol_c *u2 = sub2->upper_limit; + + if (less_than(u1, l2)) return; // no overlap! + if (less_than(u2, l1)) return; // no overlap! + + if ( (VALID_CVALUE( int64, l1) || (VALID_CVALUE(uint64, l1))) + && (VALID_CVALUE( int64, l2) || (VALID_CVALUE(uint64, l2))) + && (VALID_CVALUE( int64, u1) || (VALID_CVALUE(uint64, u1))) + && (VALID_CVALUE( int64, u2) || (VALID_CVALUE(uint64, u2)))) + STAGE3_WARNING(s1, s2, "Elements in CASE options have overlapping ranges."); +} + + + + +void case_elements_check_c::check_subr_symb(symbol_c *s1, symbol_c *s2) { + subrange_c *subr = NULL; + symbol_c *symb = NULL; + if ((subr = dynamic_cast<subrange_c *>(s1)) != NULL) {symb = s2;} + if ((subr = dynamic_cast<subrange_c *>(s2)) != NULL) {symb = s1;} + + if ((NULL == subr) || (NULL == symb)) return; + symbol_c *lowl = subr->lower_limit; + symbol_c *uppl = subr->upper_limit; + + if ( (VALID_CVALUE(int64, symb)) + && (VALID_CVALUE(int64, lowl)) + && (VALID_CVALUE(int64, uppl)) + && ( GET_CVALUE(int64, symb) >= GET_CVALUE(int64, lowl)) + && ( GET_CVALUE(int64, symb) <= GET_CVALUE(int64, uppl))) + {STAGE3_WARNING(s1, s2, "Element in CASE option falls within range of another element."); return;} + + if ( (VALID_CVALUE(uint64, symb)) + && (VALID_CVALUE( int64, lowl)) + && (VALID_CVALUE(uint64, uppl)) + && ( GET_CVALUE( int64, lowl) < 0) + && ( GET_CVALUE(uint64, symb) <= GET_CVALUE(uint64, uppl))) + {STAGE3_WARNING(s1, s2, "Element in CASE option falls within range of another element."); return;} + + if ( (VALID_CVALUE(uint64, symb)) + && (VALID_CVALUE(uint64, lowl)) + && (VALID_CVALUE(uint64, uppl)) + && ( GET_CVALUE(uint64, symb) >= GET_CVALUE(uint64, lowl)) + && ( GET_CVALUE(uint64, symb) <= GET_CVALUE(uint64, uppl))) + {STAGE3_WARNING(s1, s2, "Element in CASE option falls within range of another element."); return;} +} + + + + +#include <typeinfo> +void case_elements_check_c::check_symb_symb(symbol_c *s1, symbol_c *s2) { + if ( (dynamic_cast<subrange_c *>(s1) != NULL) + || (dynamic_cast<subrange_c *>(s2) != NULL)) + return; // only run this test if neither s1 nor s2 are subranges! + + if ( (s1->const_value.is_const() && s2->const_value.is_const() && (s1->const_value == s2->const_value)) // if const, then compare const values (using overloaded '==' operator!) + || (compare_identifiers(s1, s2) == 0)) // if token_c, compare tokens! (compare_identifiers() returns 0 when equal tokens!, -1 when either is not token_c) + STAGE3_WARNING(s1, s2, "Duplicate element found in CASE options."); +} + + + + + + + + + +/***************************************/ +/* B.3 - Language ST (Structured Text) */ +/***************************************/ +/********************/ +/* B 3.2 Statements */ +/********************/ +/********************************/ +/* B 3.2.3 Selection Statements */ +/********************************/ +/* CASE expression OF case_element_list ELSE statement_list END_CASE */ +// SYM_REF3(case_statement_c, expression, case_element_list, statement_list) +void *case_elements_check_c::visit(case_statement_c *symbol) { + std::vector<symbol_c *> case_elements_list_local = case_elements_list; // Required when source code contains CASE inside another CASE ! + + case_elements_list.clear(); + symbol->case_element_list->accept(*this); // will fill up the case_elements_list with all the elements in the case! + + // OK, now check whether we have any overlappings... + std::vector<symbol_c *>::iterator s1 = case_elements_list.begin(); + for ( ; s1 != case_elements_list.end(); s1++) { + std::vector<symbol_c *>::iterator s2 = s1; + s2++; // do not compare the value with itself! + for (; s2 != case_elements_list.end(); s2++) { + // Check for overlapping elements + check_subr_subr(*s1, *s2); + check_subr_symb(*s1, *s2); + check_symb_symb(*s2, *s1); + } + } + + case_elements_list = case_elements_list_local; + return NULL; +} + +/* helper symbol for case_statement */ +// SYM_LIST(case_element_list_c) +// void *case_elements_check_c::visit(case_element_list_c *symbol) // not needed! We inherit from iterator_visitor_c + +/* case_list ':' statement_list */ +// SYM_REF2(case_element_c, case_list, statement_list) +// void *case_elements_check_c::visit(case_element_c *symbol) // not needed! We inherit from iterator_visitor_c + + +// SYM_LIST(case_list_c) +void *case_elements_check_c::visit(case_list_c *symbol) { + for (int i = 0; i < symbol->n; i++) + case_elements_list.push_back(symbol->elements[i]); + return NULL; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/case_elements_check.hh Sat Mar 18 22:02:14 2017 +0000 @@ -0,0 +1,85 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2015 Mario de Sousa (msousa@fe.up.pt) + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +/* + * An IEC 61131-3 compiler. + * + * Based on the + * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) + * + */ + + +/* + * Case Options Checking: + * - Check whether the options in a case statement are repeated, either directly, or in a range. + * For example: + * case var of + * 1: ... <- OK + * 2: ... <- OK + * 1: ... <- OK (not an error), but produce a warning! + * 0..8: ...<- OK (not an error), but produce a warning! + */ + +#include "../absyntax_utils/absyntax_utils.hh" + + + +class case_elements_check_c: public iterator_visitor_c { + + private: + bool warning_found; + int error_count; + int current_display_error_level; + + std::vector<symbol_c *> case_elements_list; + void check_subr_subr(symbol_c *s1, symbol_c *s2); + void check_subr_symb(symbol_c *s1, symbol_c *s2); + void check_symb_symb(symbol_c *s1, symbol_c *s2); + + + public: + case_elements_check_c(symbol_c *ignore); + virtual ~case_elements_check_c(void); + int get_error_count(); + + /***************************************/ + /* B.3 - Language ST (Structured Text) */ + /***************************************/ + /********************/ + /* B 3.2 Statements */ + /********************/ + /********************************/ + /* B 3.2.3 Selection Statements */ + /********************************/ + void *visit(case_statement_c *symbol); + void *visit(case_list_c *symbol); +}; /* case_elements_check_c */ + + + + + + +
--- a/stage3/fill_candidate_datatypes.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage3/fill_candidate_datatypes.cc Sat Mar 18 22:02:14 2017 +0000 @@ -1831,7 +1831,8 @@ /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */ // SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;) void *fill_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) { - symbol->il_param_list->accept(*this); + /* non-standard extension allowing functions with no input parameters => il_param_list may be NULL !!! */ + if (NULL != symbol->il_param_list) symbol->il_param_list->accept(*this); generic_function_call_t fcall_param = { /* fcall_param.function_name = */ symbol->function_name, @@ -2170,7 +2171,7 @@ void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) { if (NULL != symbol->formal_param_list) symbol-> formal_param_list->accept(*this); else if (NULL != symbol->nonformal_param_list) symbol->nonformal_param_list->accept(*this); - else ERROR; + // else ERROR; NOTE-> We support the non-standard feature of POUS with no in, out and inout parameters, so this is no longer an internal error! generic_function_call_t fcall_param = { function_name: symbol->function_name,
--- a/stage3/narrow_candidate_datatypes.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage3/narrow_candidate_datatypes.cc Sat Mar 18 22:02:14 2017 +0000 @@ -930,6 +930,20 @@ return NULL; } + +void *narrow_candidate_datatypes_c::visit(action_qualifier_c *symbol) { + if (symbol->action_time) { + for(unsigned int i = 0; i < symbol->action_time->candidate_datatypes.size(); i++) { + if (get_datatype_info_c::is_TIME_compatible(symbol->action_time->candidate_datatypes[i])) + symbol->action_time->datatype = symbol->action_time->candidate_datatypes[i]; + } + symbol->action_time->accept(*this); + } + symbol->action_qualifier->accept(*this); // Not really necessary for now... + return NULL; +} + + /********************************/ /* B 1.7 Configuration elements */ /********************************/
--- a/stage3/narrow_candidate_datatypes.hh Thu Mar 12 16:36:33 2015 +0100 +++ b/stage3/narrow_candidate_datatypes.hh Sat Mar 18 22:02:14 2017 +0000 @@ -249,6 +249,7 @@ /* B 1.6 Sequential function chart elements */ /********************************************/ void *visit(transition_condition_c *symbol); + void *visit(action_qualifier_c *symbol); /********************************/ /* B 1.7 Configuration elements */
--- a/stage3/stage3.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage3/stage3.cc Sat Mar 18 22:02:14 2017 +0000 @@ -41,6 +41,7 @@ #include "print_datatypes_error.hh" #include "lvalue_check.hh" #include "array_range_check.hh" +#include "case_elements_check.hh" #include "constant_folding.hh" #include "declaration_check.hh" #include "enum_declaration_check.hh" @@ -126,6 +127,15 @@ } +/* Case options check assumes that constant folding has been completed! + * so be sure to call constant_folding() before calling this function! + */ +static int case_elements_check(symbol_c *tree_root){ + case_elements_check_c case_elements_check(tree_root); + tree_root->accept(case_elements_check); + return case_elements_check.get_error_count(); +} + /* Removing forward dependencies only makes sense when stage1_2 is run with the pre-parsing option. * This algorithm has no dependencies on other stage 3 algorithms. @@ -154,6 +164,7 @@ error_count += type_safety(tree_root); error_count += lvalue_check(tree_root); error_count += array_range_check(tree_root); + error_count += case_elements_check(tree_root); error_count += remove_forward_dependencies(tree_root, ordered_tree_root); if (error_count > 0) {
--- a/stage4/generate_c/generate_c.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage4/generate_c/generate_c.cc Sat Mar 18 22:02:14 2017 +0000 @@ -859,53 +859,83 @@ /* (B.2) Temporary variable for function's return value */ /* It will have the same name as the function itself! */ - s4o.print(s4o.indent_spaces); - symbol->type_name->accept(print_base); /* return type */ - s4o.print(" "); - symbol->derived_function_name->accept(print_base); - s4o.print(" = "); - { - /* get the default value of this variable's type */ - symbol_c *default_value = type_initial_value_c::get(symbol->type_name); - if (default_value == NULL) ERROR; - initialization_analyzer_c initialization_analyzer(default_value); - switch (initialization_analyzer.get_initialization_type()) { - case initialization_analyzer_c::struct_it: - { - generate_c_structure_initialization_c *structure_initialization = new generate_c_structure_initialization_c(&s4o); - structure_initialization->init_structure_default(symbol->type_name); - structure_initialization->init_structure_values(default_value); - delete structure_initialization; - } - break; - case initialization_analyzer_c::array_it: - { - generate_c_array_initialization_c *array_initialization = new generate_c_array_initialization_c(&s4o); - array_initialization->init_array_size(symbol->type_name); - array_initialization->init_array_values(default_value); - delete array_initialization; - } - break; - default: - default_value->accept(print_base); - break; + /* NOTE: matiec supports a non-standard syntax, in which functions do not return a value + * (declared as returning the special non-standard datatype VOID) + * e.g.: FUNCTION foo: VOID + * ... + * END_FUNCTION + * + * These functions cannot return any value, so they do not need a variable to + * store the return value. + * Note that any attemot to sto a value in the implicit variable + * e.g.: FUNCTION foo: VOID + * ... + * foo := 42; + * END_FUNCTION + * will always return a datatype incompatilibiyt error in stage 3 of matiec, + * so it is safe for stage 4 to assume that this return variable will never be needed + * if the function's return type is VOID. + */ + if (!get_datatype_info_c::is_VOID(symbol->type_name->datatype)) { // only print return variable if return datatype is not VOID + s4o.print(s4o.indent_spaces); + symbol->type_name->accept(print_base); /* return type */ + s4o.print(" "); + symbol->derived_function_name->accept(print_base); + s4o.print(" = "); + { + /* get the default value of this variable's type */ + symbol_c *default_value = type_initial_value_c::get(symbol->type_name); + if (default_value == NULL) ERROR; + initialization_analyzer_c initialization_analyzer(default_value); + switch (initialization_analyzer.get_initialization_type()) { + case initialization_analyzer_c::struct_it: + { + generate_c_structure_initialization_c *structure_initialization = new generate_c_structure_initialization_c(&s4o); + structure_initialization->init_structure_default(symbol->type_name); + structure_initialization->init_structure_values(default_value); + delete structure_initialization; + } + break; + case initialization_analyzer_c::array_it: + { + generate_c_array_initialization_c *array_initialization = new generate_c_array_initialization_c(&s4o); + array_initialization->init_array_size(symbol->type_name); + array_initialization->init_array_values(default_value); + delete array_initialization; + } + break; + default: + default_value->accept(print_base); + break; + } } } s4o.print(";\n\n"); - s4o.print(s4o.indent_spaces + "// Control execution\n"); - s4o.print(s4o.indent_spaces + "if (!EN) {\n"); - s4o.indent_right(); - s4o.print(s4o.indent_spaces + "if (__ENO != NULL) {\n"); - s4o.indent_right(); - s4o.print(s4o.indent_spaces + "*__ENO = __BOOL_LITERAL(FALSE);\n"); - s4o.indent_left(); - s4o.print(s4o.indent_spaces + "}\n"); - s4o.print(s4o.indent_spaces + "return "); - symbol->derived_function_name->accept(print_base); - s4o.print(";\n"); - s4o.indent_left(); - s4o.print(s4o.indent_spaces + "}\n"); + + // Only generate the code that controls the execution of the function's body if the + // function contains a declaration of both the EN and ENO variables + search_var_instance_decl_c search_var(symbol); + identifier_c en_var("EN"); + identifier_c eno_var("ENO"); + if ( (search_var.get_vartype(& en_var) == search_var_instance_decl_c::input_vt) + && (search_var.get_vartype(&eno_var) == search_var_instance_decl_c::output_vt)) { + s4o.print(s4o.indent_spaces + "// Control execution\n"); + s4o.print(s4o.indent_spaces + "if (!EN) {\n"); + s4o.indent_right(); + s4o.print(s4o.indent_spaces + "if (__ENO != NULL) {\n"); + s4o.indent_right(); + s4o.print(s4o.indent_spaces + "*__ENO = __BOOL_LITERAL(FALSE);\n"); + s4o.indent_left(); + s4o.print(s4o.indent_spaces + "}\n"); + if (!get_datatype_info_c::is_VOID(symbol->type_name->datatype)) { // only print return variable if return datatype is not VOID + s4o.print(s4o.indent_spaces + "return "); + symbol->derived_function_name->accept(print_base); + s4o.print(";\n"); + } + s4o.indent_left(); + s4o.print(s4o.indent_spaces + "}\n"); + } /* (C) Function body */ generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->derived_function_name, symbol); @@ -921,9 +951,12 @@ vardecl->print(symbol->var_declarations_list); delete vardecl; - s4o.print(s4o.indent_spaces + "return "); - symbol->derived_function_name->accept(print_base); - s4o.print(";\n"); + if (!get_datatype_info_c::is_VOID(symbol->type_name->datatype)) { // only print 'return <fname>' if return datatype is not VOID + s4o.print(s4o.indent_spaces + "return "); + symbol->derived_function_name->accept(print_base); + s4o.print(";\n"); + } + s4o.indent_left(); s4o.print(s4o.indent_spaces + "}\n\n\n"); @@ -1071,31 +1104,40 @@ } else { s4o.print(" {\n"); s4o.indent_right(); - - 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.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(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.indent_left(); - s4o.print(s4o.indent_spaces + "}\n"); + + // Only generate the code that controls the execution of the function's body if the + // function contains a declaration of both the EN and ENO variables + search_var_instance_decl_c search_var(symbol); + identifier_c en_var("EN"); + identifier_c eno_var("ENO"); + if ( (search_var.get_vartype(& en_var) == search_var_instance_decl_c::input_vt) + && (search_var.get_vartype(&eno_var) == search_var_instance_decl_c::output_vt)) { + + 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.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(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.indent_left(); + s4o.print(s4o.indent_spaces + "}\n"); + } /* (C.4) Initialize TEMP variables */ /* function body */ @@ -1380,6 +1422,15 @@ s4o.print("/* FILE GENERATED BY iec2c */\n"); s4o.print("/* Editing this file is not recommended... */\n"); s4o.print("/*******************************************/\n\n"); + + if (runtime_options.disable_implicit_en_eno) { + // If we are not generating the EN and ENO parameters for functions and FB, + // then make sure we use the standard library version compiled without these parameters too! + s4o.print("#ifndef DISABLE_EN_ENO_PARAMETERS\n"); + s4o.print("#define DISABLE_EN_ENO_PARAMETERS\n"); + s4o.print("#endif\n"); + } + s4o.print("#include \"iec_std_lib.h\"\n\n"); s4o.print("#include \"accessor.h\"\n\n"); s4o.print("#include \"POUS.h\"\n\n"); @@ -1685,6 +1736,15 @@ s4o.print("/* FILE GENERATED BY iec2c */\n"); s4o.print("/* Editing this file is not recommended... */\n"); s4o.print("/*******************************************/\n\n"); + + if (runtime_options.disable_implicit_en_eno) { + // If we are not generating the EN and ENO parameters for functions and FB, + // then make sure we use the standard library version compiled without these parameters too! + s4o.print("#ifndef DISABLE_EN_ENO_PARAMETERS\n"); + s4o.print("#define DISABLE_EN_ENO_PARAMETERS\n"); + s4o.print("#endif\n"); + } + s4o.print("#include \"iec_std_lib.h\"\n\n"); /* (A) resource declaration... */ @@ -2118,7 +2178,17 @@ /* B 0 - Programming Model */ /***************************/ void *visit(library_c *symbol) { - pous_incl_s4o.print("#ifndef __POUS_H\n#define __POUS_H\n\n#include \"accessor.h\"\n#include \"iec_std_lib.h\"\n\n"); + pous_incl_s4o.print("#ifndef __POUS_H\n#define __POUS_H\n\n"); + + if (runtime_options.disable_implicit_en_eno) { + // If we are not generating the EN and ENO parameters for functions and FB, + // then make sure we use the standard library version compiled without these parameters too! + pous_incl_s4o.print("#ifndef DISABLE_EN_ENO_PARAMETERS\n"); + pous_incl_s4o.print("#define DISABLE_EN_ENO_PARAMETERS\n"); + pous_incl_s4o.print("#endif\n"); + } + + pous_incl_s4o.print("#include \"accessor.h\"\n#include \"iec_std_lib.h\"\n\n"); for(int i = 0; i < symbol->n; i++) { symbol->elements[i]->accept(*this); @@ -2258,7 +2328,7 @@ 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("unsigned long greatest_tick_count__ = (unsigned long)"); config_s4o.print_long_integer(calculate_common_ticktime.get_greatest_tick_count()); config_s4o.print("; /*tick*/\n"); }
--- a/stage4/generate_c/generate_c_base.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage4/generate_c/generate_c_base.cc Sat Mar 18 22:02:14 2017 +0000 @@ -249,13 +249,48 @@ return NULL; } + /* Call a standard library function that does a comparison (GT, NE, EQ, LT, ...) + * NOTE: Typically, the function will have the following parameters: + * 1st parameter: EN (enable) + * 2nd parameter: ENO (enable output) + * 3rd parameter: number of operands we will be passing (required because we are calling an extensible standard function!) + * 4th parameter: the left hand side of the comparison expression (in out case, the IL implicit variable) + * 4th parameter: the right hand side of the comparison expression (in out case, current operand) + * + * The 1st and 2nd parameter may not be present, only issue them if NE and ENO are being generated! + * The 3rd parameter must not be generated when the 'NE' function is called (it is not an extensible function!) + * + * NOTE: To implement this correctly, this function should really instantiate a + * function_invocation_c and have the generate_c visitor generate the code automatically for this + * function invocation. However, the code for function invocations is currently duplicated + * for IL and ST. Until this code is not re-formulated into a single piece of general code, for now + * we generate the function call directly here in print_compare_function() + */ void *print_compare_function(const char *function, symbol_c *compare_type, symbol_c *l_exp, symbol_c *r_exp) { - s4o.print(function); - compare_type->accept(*this); - s4o.print("(__BOOL_LITERAL(TRUE), NULL, 2, "); + // Print out the name of the function we will call. + // It will be something like LE_TIME, LE_DATE, GT_DATE, ... + // (in other words, we are calling an overloaded function!) + s4o.print(function); // the GT, LE, ... part + s4o.print("_"); // the '_' part... + compare_type->accept(*this); // the TIME, DATE, ... part. + s4o.print("("); // start of parameters to function call... + // Determine whether this function has the EN parameter + // (we just check the base LE, GT, .. function, as it should have + // the same parameters as the overloaded function!) + function_symtable_t::iterator lower = function_symtable.lower_bound(function); + if (lower == function_symtable.end()) ERROR; // We want to call a function that does not exist!!?? Hmm... + search_var_instance_decl_c search_var(function_symtable.get_value(lower)); + identifier_c en_var("EN"); + identifier_c eno_var("ENO"); + if (search_var.get_vartype(& en_var) == search_var_instance_decl_c::input_vt) + s4o.print("__BOOL_LITERAL(TRUE), "); // function has EN parameter, pass TRUE + if (search_var.get_vartype(&eno_var) == search_var_instance_decl_c::output_vt) + s4o.print("NULL, "); // function has ENO parameter, pass NULL + if (strcmp(function, "NE") != 0) // All comparison library functions are extensible, except for 'NE'!! + s4o.print("2, "); // function is extensible, so must first pass the number of parameters that follow l_exp->accept(*this); s4o.print(", "); r_exp->accept(*this); @@ -623,6 +658,8 @@ void *visit(safestring_type_name_c *symbol) {s4o.print("STRING"); return NULL;} void *visit(safewstring_type_name_c *symbol) {s4o.print("WSTRING"); return NULL;} + void *visit(void_type_name_c *symbol) {s4o.print("void"); return NULL;} + /********************************/ /* B.1.3.2 - Generic data types */ /********************************/
--- a/stage4/generate_c/generate_c_il.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage4/generate_c/generate_c_il.cc Sat Mar 18 22:02:14 2017 +0000 @@ -327,21 +327,8 @@ this->implicit_variable_result.accept(*this); s4o.print(" = "); - s4o.print(operation); - operand->datatype->accept(*this); - /* NOTE: we are calling a standard Function: - * 1st parameter: EN (enable) - * 2nd parameter: ENO (enable output) - * 3rd parameter: number of operands we will be passing (required because we are calling an extensible standard function!) - * 4th parameter: the left hand side of the comparison expression (in out case, the IL implicit variable) - * 4th parameter: the right hand side of the comparison expression (in out case, current operand) - */ - s4o.print("(__BOOL_LITERAL(TRUE), NULL, 2, "); - this->implicit_variable_current.accept(*this); - s4o.print(", "); - operand->accept(*this); - s4o.print(")"); - + // print_compare_function is in generate_c_base_c, which is inherited by generate_c_il_c + print_compare_function(operation, operand->datatype, &(this->implicit_variable_current), operand); return NULL; } @@ -897,8 +884,11 @@ int fdecl_mutiplicity = function_symtable.count(symbol->function_name); if (fdecl_mutiplicity == 0) ERROR; - this->implicit_variable_result.accept(*this); - s4o.print(" = "); + /* when function returns a void, we do not store the value in the default variable! */ + if (!get_datatype_info_c::is_VOID(symbol->datatype)) { + this->implicit_variable_result.accept(*this); + s4o.print(" = "); + } if (function_type_prefix != NULL) { s4o.print("("); @@ -937,6 +927,7 @@ } s4o.print("("); s4o.indent_right(); + s4o.print("\n"+s4o.indent_spaces); int nb_param = 0; PARAM_LIST_ITERATOR() { @@ -991,6 +982,7 @@ } s4o.print(")"); + s4o.indent_left(); CLEAR_PARAM_LIST() @@ -1299,8 +1291,11 @@ /* function being called is NOT overloaded! */ f_decl = NULL; - this->implicit_variable_result.accept(*this); - s4o.print(" = "); + /* when function returns a void, we do not store the value in the default variable! */ + if (!get_datatype_info_c::is_VOID(symbol->datatype)) { + this->implicit_variable_result.accept(*this); + s4o.print(" = "); + } if (function_type_prefix != NULL) { s4o.print("("); @@ -1711,12 +1706,12 @@ void *visit(MOD_operator_c *symbol) {XXX_operator(&(this->implicit_variable_result), " %= ", this->current_operand); return NULL;} -void *visit(GT_operator_c *symbol) {CMP_operator(this->current_operand, "GT_"); return NULL;} -void *visit(GE_operator_c *symbol) {CMP_operator(this->current_operand, "GE_"); return NULL;} -void *visit(EQ_operator_c *symbol) {CMP_operator(this->current_operand, "EQ_"); return NULL;} -void *visit(LT_operator_c *symbol) {CMP_operator(this->current_operand, "LT_"); return NULL;} -void *visit(LE_operator_c *symbol) {CMP_operator(this->current_operand, "LE_"); return NULL;} -void *visit(NE_operator_c *symbol) {CMP_operator(this->current_operand, "NE_"); return NULL;} +void *visit(GT_operator_c *symbol) {CMP_operator(this->current_operand, "GT"); return NULL;} +void *visit(GE_operator_c *symbol) {CMP_operator(this->current_operand, "GE"); return NULL;} +void *visit(EQ_operator_c *symbol) {CMP_operator(this->current_operand, "EQ"); return NULL;} +void *visit(LT_operator_c *symbol) {CMP_operator(this->current_operand, "LT"); return NULL;} +void *visit(LE_operator_c *symbol) {CMP_operator(this->current_operand, "LE"); return NULL;} +void *visit(NE_operator_c *symbol) {CMP_operator(this->current_operand, "NE"); return NULL;} //SYM_REF0(CAL_operator_c)
--- a/stage4/generate_c/generate_c_inlinefcall.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage4/generate_c/generate_c_inlinefcall.cc Sat Mar 18 22:02:14 2017 +0000 @@ -37,22 +37,6 @@ } variablegeneration_t; private: - /* The result of the comparison IL operations (GT, EQ, LT, ...) - * is a boolean variable. - * This class keeps track of the current data type stored in the - * il default variable. This is usually done by keeping a reference - * to the data type of the last operand. Nevertheless, in the case of - * the comparison IL operators, the data type of the result (a boolean) - * is not the data type of the operand. We therefore need an object - * of the boolean data type to keep as a reference of the current - * data type. - * The following object is it... - */ - bool_type_name_c bool_type; - lint_type_name_c lint_type; - lword_type_name_c lword_type; - lreal_type_name_c lreal_type; - /* The name of the IL default variable... */ #define IL_DEFVAR VAR_LEADER "IL_DEFVAR" @@ -120,7 +104,7 @@ } s4o.print(s4o.indent_spaces); - s4o.print("inline "); + s4o.print("static inline "); function_type_prefix->accept(*this); s4o.print(" __"); fbname->accept(*this); @@ -281,21 +265,6 @@ else s4o.print(SET_VAR); s4o.print("(,"); -/* - wanted_variablegeneration = complextype_base_vg; - symbol->accept(*this); - s4o.print(","); - wanted_variablegeneration = expression_vg; - print_check_function(type, value, NULL, true); - if (analyse_variable_c::contains_complex_type(symbol)) { - s4o.print(","); - wanted_variablegeneration = complextype_suffix_vg; - symbol->accept(*this); - } - s4o.print(")"); - wanted_variablegeneration = expression_vg; - return NULL; -*/ wanted_variablegeneration = complextype_base_vg; symbol->accept(*this); s4o.print(","); @@ -311,6 +280,28 @@ return NULL; } + /********************/ + /* 2.1.6 - Pragmas */ + /********************/ + //SYM_REF0(disable_code_generation_pragma_c) + //SYM_REF0(enable_code_generation_pragma_c) + //SYM_TOKEN(pragma_c) + void *visit(pragma_c *symbol) {return NULL;} + + + /*************************/ + /* B.1 - Common elements */ + /*************************/ + /*******************************************/ + /* B 1.1 - Letters, digits and identifiers */ + /*******************************************/ + void *visit(identifier_c *symbol) { + if (generating_inlinefunction) { + return generate_c_base_c::visit(symbol); // let the base class handle it... + } + return NULL; + } + /*********************/ /* B 1.4 - Variables */ /*********************/ @@ -782,7 +773,8 @@ symbol_c *parameter_assignment_list = NULL; if (NULL != symbol-> formal_param_list) parameter_assignment_list = symbol-> formal_param_list; if (NULL != symbol->nonformal_param_list) parameter_assignment_list = symbol->nonformal_param_list; - if (NULL == parameter_assignment_list) ERROR; + // NOTE-> We support the non-standard feature of POUS with no in, out and inout parameters, so this is no longer an internal error! + // if (NULL == parameter_assignment_list) ERROR; function_call_param_iterator_c function_call_param_iterator(symbol);
--- a/stage4/generate_c/generate_c_sfc.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage4/generate_c/generate_c_sfc.cc Sat Mar 18 22:02:14 2017 +0000 @@ -577,7 +577,7 @@ s4o.print(s4o.indent_spaces + "if (active && __time_cmp("); print_step_argument(current_step, "T.value"); s4o.print(", "); - symbol->action_time->accept(*this); + symbol->action_time->accept(*generate_c_st); if (strcmp(qualifier, "L") == 0) s4o.print(") < 0) "); else @@ -618,7 +618,7 @@ s4o.print(" = 1;\n" + s4o.indent_spaces); print_action_argument(current_action, "reset_remaining_time"); s4o.print(" = "); - symbol->action_time->accept(*this); + symbol->action_time->accept(*generate_c_st); s4o.print(";\n"); s4o.indent_left(); s4o.print(s4o.indent_spaces + "}\n"); @@ -632,7 +632,7 @@ s4o.print("\n" + s4o.indent_spaces); print_action_argument(current_action, "set_remaining_time"); s4o.print(" = "); - symbol->action_time->accept(*this); + symbol->action_time->accept(*generate_c_st); s4o.print(";\n"); s4o.indent_left(); s4o.print(s4o.indent_spaces + "}\n"); @@ -720,8 +720,6 @@ /* generate elapsed_time initializations */ s4o.print(s4o.indent_spaces + "// Calculate elapsed_time\n"); s4o.print(s4o.indent_spaces +"current_time = __CURRENT_TIME;\n"); -// s4o.print(s4o.indent_spaces +"elapsed_time = __time_sub(__BOOL_LITERAL(TRUE), NULL, current_time, "); -// s4o.print(s4o.indent_spaces +"elapsed_time = SUB_TIME(__BOOL_LITERAL(TRUE), NULL, current_time, "); s4o.print(s4o.indent_spaces +"elapsed_time = __time_sub(current_time, "); print_variable_prefix(); s4o.print("__lasttick_time);\n"); @@ -768,8 +766,6 @@ 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].T.value = __time_add("); print_variable_prefix(); s4o.print("__step_list[i].T.value, elapsed_time);\n"); @@ -802,8 +798,6 @@ s4o.indent_right(); s4o.print(s4o.indent_spaces); print_variable_prefix(); -// s4o.print("__action_list[i].set_remaining_time = __time_sub(__BOOL_LITERAL(TRUE), NULL, "); -// s4o.print("__action_list[i].set_remaining_time = SUB_TIME(__BOOL_LITERAL(TRUE), NULL, "); s4o.print("__action_list[i].set_remaining_time = __time_sub("); print_variable_prefix(); s4o.print("__action_list[i].set_remaining_time, elapsed_time);\n"); @@ -829,8 +823,6 @@ s4o.indent_right(); s4o.print(s4o.indent_spaces); print_variable_prefix(); -// s4o.print("__action_list[i].reset_remaining_time = __time_sub(__BOOL_LITERAL(TRUE), NULL, "); -// s4o.print("__action_list[i].reset_remaining_time = SUB_TIME(__BOOL_LITERAL(TRUE), NULL, "); s4o.print("__action_list[i].reset_remaining_time = __time_sub("); print_variable_prefix(); s4o.print("__action_list[i].reset_remaining_time, elapsed_time);\n");
--- a/stage4/generate_c/generate_c_sfcdecl.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage4/generate_c/generate_c_sfcdecl.cc Sat Mar 18 22:02:14 2017 +0000 @@ -130,7 +130,7 @@ wanted_sfcdeclaration = sfcinit_sd; /* steps table initialisation */ - s4o.print(s4o.indent_spaces + "static const STEP temp_step = {{0, 0}, 0, {0, 0}};\n"); + s4o.print(s4o.indent_spaces + "static const STEP temp_step = {{0, 0}, 0, {{0, 0}, 0}};\n"); s4o.print(s4o.indent_spaces + "for(i = 0; i < "); print_variable_prefix(); s4o.print("__nb_steps; i++) {\n");
--- a/stage4/generate_c/generate_c_st.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage4/generate_c/generate_c_st.cc Sat Mar 18 22:02:14 2017 +0000 @@ -54,12 +54,6 @@ fparam_output_vg } variablegeneration_t; - typedef enum { - single_cg, - subrange_cg, - none_cg - } casegeneration_t; - private: /* When calling a function block, we must first find it's type, * by searching through the declarations of the variables currently @@ -89,7 +83,6 @@ bool first_subrange_case_list; variablegeneration_t wanted_variablegeneration; - casegeneration_t wanted_casegeneration; public: generate_c_st_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL) @@ -105,7 +98,6 @@ fcall_number = 0; fbname = name; wanted_variablegeneration = expression_vg; - wanted_casegeneration = none_cg; } virtual ~generate_c_st_c(void) { @@ -234,17 +226,7 @@ /* signed_integer DOTDOT signed_integer */ void *visit(subrange_c *symbol) { - switch (wanted_casegeneration) { - case subrange_cg: - s4o.print("__case_expression >= "); - symbol->lower_limit->accept(*this); - s4o.print(" && __case_expression <= "); - symbol->upper_limit->accept(*this); - break; - default: - symbol->lower_limit->accept(*this); - break; - } + symbol->lower_limit->accept(*this); return NULL; } @@ -611,7 +593,7 @@ void *visit(xor_expression_c *symbol) { if (get_datatype_info_c::is_BOOL_compatible(symbol->datatype)) { - s4o.print("("); + s4o.print("(("); symbol->l_exp->accept(*this); s4o.print(" && !"); symbol->r_exp->accept(*this); @@ -619,7 +601,7 @@ symbol->l_exp->accept(*this); s4o.print(" && "); symbol->r_exp->accept(*this); - s4o.print(")"); + s4o.print("))"); return NULL; } if (get_datatype_info_c::is_ANY_nBIT_compatible(symbol->datatype)) @@ -641,7 +623,7 @@ if (get_datatype_info_c::is_TIME_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_DATE_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_STRING_compatible(symbol->l_exp->datatype)) - return print_compare_function("EQ_", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); + return print_compare_function("EQ", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); return print_binary_expression(symbol->l_exp, symbol->r_exp, " == "); } @@ -649,7 +631,7 @@ if (get_datatype_info_c::is_TIME_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_DATE_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_STRING_compatible(symbol->l_exp->datatype)) - return print_compare_function("NE_", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); + return print_compare_function("NE", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); return print_binary_expression(symbol->l_exp, symbol->r_exp, " != "); } @@ -657,7 +639,7 @@ if (get_datatype_info_c::is_TIME_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_DATE_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_STRING_compatible(symbol->l_exp->datatype)) - return print_compare_function("LT_", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); + return print_compare_function("LT", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); return print_binary_expression(symbol->l_exp, symbol->r_exp, " < "); } @@ -665,7 +647,7 @@ if (get_datatype_info_c::is_TIME_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_DATE_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_STRING_compatible(symbol->l_exp->datatype)) - return print_compare_function("GT_", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); + return print_compare_function("GT", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); return print_binary_expression(symbol->l_exp, symbol->r_exp, " > "); } @@ -673,7 +655,7 @@ if (get_datatype_info_c::is_TIME_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_DATE_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_STRING_compatible(symbol->l_exp->datatype)) - return print_compare_function("LE_", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); + return print_compare_function("LE", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); return print_binary_expression(symbol->l_exp, symbol->r_exp, " <= "); } @@ -681,19 +663,11 @@ if (get_datatype_info_c::is_TIME_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_DATE_compatible (symbol->l_exp->datatype) || get_datatype_info_c::is_ANY_STRING_compatible(symbol->l_exp->datatype)) - return print_compare_function("GE_", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); + return print_compare_function("GE", symbol->l_exp->datatype, symbol->l_exp, symbol->r_exp); return print_binary_expression(symbol->l_exp, symbol->r_exp, " >= "); } void *visit(add_expression_c *symbol) { -/* - symbol_c *left_type = symbol->l_exp->datatype; - symbol_c *right_type = symbol->r_exp->datatype; - if ((typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) || - (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) || - (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c))) - return print_binary_function("__time_add", symbol->l_exp, symbol->r_exp); -*/ if (get_datatype_info_c::is_TIME_compatible (symbol->datatype) || get_datatype_info_c::is_ANY_DATE_compatible (symbol->datatype)) return print_binary_function("__time_add", symbol->l_exp, symbol->r_exp); @@ -701,17 +675,6 @@ } void *visit(sub_expression_c *symbol) { -/* - symbol_c *left_type = symbol->l_exp->datatype; - symbol_c *right_type = symbol->r_exp->datatype; - if ((typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) || - (typeid(*left_type) == typeid(date_type_name_c) && typeid(*right_type) == typeid(date_type_name_c)) || - (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) || - (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(tod_type_name_c)) || - (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) || - (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(dt_type_name_c))) - return print_binary_function("__time_sub", symbol->l_exp, symbol->r_exp); -*/ if (get_datatype_info_c::is_TIME_compatible (symbol->datatype) || get_datatype_info_c::is_ANY_DATE_compatible (symbol->datatype)) return print_binary_function("__time_sub", symbol->l_exp, symbol->r_exp); @@ -719,26 +682,12 @@ } void *visit(mul_expression_c *symbol) { -/* - symbol_c *left_type = symbol->l_exp->datatype; - symbol_c *right_type = symbol->r_exp->datatype; - if ((typeid(*left_type) == typeid(time_type_name_c) && get_datatype_info_c::is_ANY_INT_compatible (right_type)) || - (typeid(*left_type) == typeid(time_type_name_c) && get_datatype_info_c::is_ANY_REAL_compatible(right_type))) - return print_binary_function("__time_mul", symbol->l_exp, symbol->r_exp); -*/ if (get_datatype_info_c::is_TIME_compatible (symbol->datatype)) return print_binary_function("__time_mul", symbol->l_exp, symbol->r_exp); return print_binary_expression(symbol->l_exp, symbol->r_exp, " * "); } void *visit(div_expression_c *symbol) { -/* - symbol_c *left_type = symbol->l_exp->datatype; - symbol_c *right_type = symbol->r_exp->datatype; - if ((typeid(*left_type) == typeid(time_type_name_c) && get_datatype_info_c::is_ANY_INT_compatible (right_type)) || - (typeid(*left_type) == typeid(time_type_name_c) && get_datatype_info_c::is_ANY_REAL_compatible(right_type))) - return print_binary_function("__time_div", symbol->l_exp, symbol->r_exp); -*/ if (get_datatype_info_c::is_TIME_compatible (symbol->datatype)) return print_binary_function("__time_div", symbol->l_exp, symbol->r_exp); return print_binary_expression(symbol->l_exp, symbol->r_exp, " / "); @@ -754,13 +703,9 @@ } void *visit(power_expression_c *symbol) { - s4o.print("EXPT__LREAL__LREAL__LREAL((BOOL)__BOOL_LITERAL(TRUE),\n"); - s4o.indent_right(); - s4o.print(s4o.indent_spaces + "NULL,\n"); - s4o.print(s4o.indent_spaces + "(LREAL)("); + s4o.print("__expt((LREAL)("); symbol->l_exp->accept(*this); - s4o.print("),\n"); - s4o.print(s4o.indent_spaces + "(LREAL)("); + s4o.print("), (LREAL)("); symbol->r_exp->accept(*this); s4o.print("))"); return NULL; @@ -781,7 +726,8 @@ symbol_c *parameter_assignment_list = NULL; if (NULL != symbol-> formal_param_list) parameter_assignment_list = symbol-> formal_param_list; if (NULL != symbol->nonformal_param_list) parameter_assignment_list = symbol->nonformal_param_list; - if (NULL == parameter_assignment_list) ERROR; + // NOTE-> We support the non-standard feature of POUS with no in, out and inout parameters, so this is no longer an internal error! + //if (NULL == parameter_assignment_list) ERROR; function_call_param_iterator_c function_call_param_iterator(symbol); @@ -913,6 +859,7 @@ } s4o.print("("); s4o.indent_right(); + s4o.print("\n"+s4o.indent_spaces); int nb_param = 0; PARAM_LIST_ITERATOR() { @@ -1223,100 +1170,62 @@ expression_type->accept(*this); s4o.print(" __case_expression = "); symbol->expression->accept(*this); - s4o.print(";\n" + s4o.indent_spaces + "switch (__case_expression) {\n"); - s4o.indent_right(); - wanted_casegeneration = single_cg; - symbol->case_element_list->accept(*this); - wanted_casegeneration = subrange_cg; - s4o.print(s4o.indent_spaces + "default:\n"); - s4o.indent_right(); - first_subrange_case_list = true; + s4o.print(";\n"); symbol->case_element_list->accept(*this); if (symbol->statement_list != NULL) { - if (!first_subrange_case_list) { - s4o.print(s4o.indent_spaces + "else {\n"); - s4o.indent_right(); - } + s4o.print(s4o.indent_spaces + "else {\n"); + s4o.indent_right(); symbol->statement_list->accept(*this); - if (!first_subrange_case_list) { - s4o.indent_left(); - s4o.print(s4o.indent_spaces + "}\n"); - } - } - s4o.print(s4o.indent_spaces + "break;\n"); + s4o.indent_left(); + s4o.print(s4o.indent_spaces + "}\n"); + } s4o.indent_left(); - wanted_casegeneration = none_cg; + s4o.print(s4o.indent_spaces + "}"); + return NULL; +} + + +/* helper symbol for case_statement */ +void *visit(case_element_list_c *symbol) {return print_list(symbol, s4o.indent_spaces+"if ", s4o.indent_spaces+"else if ");} + +void *visit(case_element_c *symbol) { + symbol->case_list->accept(*this); + s4o.print(" {\n"); + s4o.indent_right(); + symbol->statement_list->accept(*this); s4o.indent_left(); s4o.print(s4o.indent_spaces + "}\n"); - s4o.indent_left(); - s4o.print(s4o.indent_spaces + "}"); - return NULL; -} - -/* helper symbol for case_statement */ -void *visit(case_element_list_c *symbol) {return print_list(symbol);} - -void *visit(case_element_c *symbol) { - case_element_iterator_c *case_element_iterator; - symbol_c* element = NULL; - bool first_element = true; - - switch (wanted_casegeneration) { - case single_cg: - case_element_iterator = new case_element_iterator_c(symbol->case_list, case_element_iterator_c::element_single); - for (element = case_element_iterator->next(); element != NULL; element = case_element_iterator->next()) { - if (first_element) first_element = false; - s4o.print(s4o.indent_spaces + "case "); - element->accept(*this); - s4o.print(":\n"); - } - delete case_element_iterator; - break; - - case subrange_cg: - case_element_iterator = new case_element_iterator_c(symbol->case_list, case_element_iterator_c::element_subrange); - for (element = case_element_iterator->next(); element != NULL; element = case_element_iterator->next()) { - if (first_element) { - if (first_subrange_case_list) { - s4o.print(s4o.indent_spaces + "if ("); - first_subrange_case_list = false; - } - else { - s4o.print(s4o.indent_spaces + "else if ("); - } - first_element = false; - } - else { - s4o.print(" && "); - } - element->accept(*this); - } - delete case_element_iterator; - if (!first_element) { - s4o.print(") {\n"); - } - break; - - default: - break; - } - - if (!first_element) { - s4o.indent_right(); - symbol->statement_list->accept(*this); - switch (wanted_casegeneration) { - case single_cg: - s4o.print(s4o.indent_spaces + "break;\n"); - s4o.indent_left(); - break; - case subrange_cg: - s4o.indent_left(); - s4o.print(s4o.indent_spaces + "}\n"); - break; - default: - break; - } - } + return NULL; +} + + +void *visit(case_list_c *symbol) { + s4o.print("("); + for (int i = 0; i < symbol->n; i++) { + /* if not the first element, then add an '||', a '\n', and add some spaces to get nice alignment */ + /* example of generated C code (codition) for + * case XX of + * 10..20,42,15..99: <---- C code is for this line! + * + * else if ((__case_expression >= 10 && __case_expression <= 20) || + * (__case_expression == 42) || + * (__case_expression >= 15 && __case_expression <= 99)) { + */ + if (0 != i) s4o.print(" ||\n" + s4o.indent_spaces + " "); + s4o.print("("); + subrange_c *subrange = dynamic_cast<subrange_c *>(symbol->elements[i]); + if (NULL == subrange) { + s4o.print("__case_expression == "); + symbol->elements[i]->accept(*this); + } else { + s4o.print("__case_expression >= "); + subrange->lower_limit->accept(*this); + s4o.print(" && __case_expression <= "); + subrange->upper_limit->accept(*this); + } + s4o.print(")"); + } + s4o.print(")"); return NULL; }
--- a/stage4/generate_c/generate_c_vardecl.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage4/generate_c/generate_c_vardecl.cc Sat Mar 18 22:02:14 2017 +0000 @@ -909,10 +909,6 @@ this->current_var_type_symbol = spec_init_sperator_c::get_spec(symbol); this->current_var_init_symbol = spec_init_sperator_c::get_init(symbol); if (NULL == this->current_var_type_symbol) ERROR; - if (NULL == this->current_var_type_symbol->datatype) {debug_c::print(this->current_var_type_symbol); ERROR;} - if (get_datatype_info_c::is_array(this->current_var_type_symbol)) - this->current_var_type_symbol = this->current_var_type_symbol->datatype; - if (NULL == this->current_var_type_symbol) ERROR; if (NULL == this->current_var_init_symbol) { /* We try to find the data type's default value... */ this->current_var_init_symbol = type_initial_value_c::get(this->current_var_type_symbol); @@ -922,6 +918,15 @@ ERROR; */ } + /* When handling arrays we must make sure that we use the base datatype, since arrays use an aliased name in the C code! + * This is done using a stage4 annotation (on the base datatype class) named "generate_c_annotaton__implicit_type_id" + * Note that we do this only _after_ determining the initial value, since in principle the derived array could have + * a default initial different to the base array datatype! + */ + if (NULL == this->current_var_type_symbol->datatype) {debug_c::print(this->current_var_type_symbol); ERROR;} + if (get_datatype_info_c::is_array(this->current_var_type_symbol)) + this->current_var_type_symbol = this->current_var_type_symbol->datatype; + if (NULL == this->current_var_type_symbol) ERROR; } void void_type_init(void) { @@ -1429,8 +1434,7 @@ /* Start off by setting the current_var_type_symbol and * current_var_init_symbol private variables... */ - if (NULL == symbol->array_spec_init->datatype) ERROR; - update_type_init(symbol->array_spec_init->datatype); // we want to print the name of the base datatype, and nt the derived datatype, so we use '->datatype'! + update_type_init(symbol->array_spec_init); /* now to produce the c equivalent... */ if (wanted_varformat == constructorinit_vf) { @@ -1572,8 +1576,7 @@ /* Start off by setting the current_var_type_symbol and * current_var_init_symbol private variables... */ - if (symbol->array_specification->datatype == NULL) {debug_c::print(symbol->array_specification); ERROR;} - update_type_init(symbol->array_specification->datatype); // we want to print the name of the base datatype, and nt the derived datatype, so we use '->datatype'! + update_type_init(symbol->array_specification); /* now to produce the c equivalent... */ if (wanted_varformat == constructorinit_vf) {
--- a/stage4/generate_iec/generate_iec.cc Thu Mar 12 16:36:33 2015 +0100 +++ b/stage4/generate_iec/generate_iec.cc Sat Mar 18 22:02:14 2017 +0000 @@ -392,48 +392,50 @@ /***********************************/ /* B 1.3.1 - Elementary Data Types */ /***********************************/ -void *visit(time_type_name_c *symbol) {s4o.print("TIME"); return NULL;} -void *visit(bool_type_name_c *symbol) {s4o.print("BOOL"); return NULL;} -void *visit(sint_type_name_c *symbol) {s4o.print("SINT"); return NULL;} -void *visit(int_type_name_c *symbol) {s4o.print("INT"); return NULL;} -void *visit(dint_type_name_c *symbol) {s4o.print("DINT"); return NULL;} -void *visit(lint_type_name_c *symbol) {s4o.print("LINT"); return NULL;} -void *visit(usint_type_name_c *symbol) {s4o.print("USINT"); return NULL;} -void *visit(uint_type_name_c *symbol) {s4o.print("UINT"); return NULL;} -void *visit(udint_type_name_c *symbol) {s4o.print("UDINT"); return NULL;} -void *visit(ulint_type_name_c *symbol) {s4o.print("ULINT"); return NULL;} -void *visit(real_type_name_c *symbol) {s4o.print("REAL"); return NULL;} -void *visit(lreal_type_name_c *symbol) {s4o.print("LREAL"); return NULL;} -void *visit(date_type_name_c *symbol) {s4o.print("DATE"); return NULL;} -void *visit(tod_type_name_c *symbol) {s4o.print("TOD"); return NULL;} -void *visit(dt_type_name_c *symbol) {s4o.print("DT"); return NULL;} -void *visit(byte_type_name_c *symbol) {s4o.print("BYTE"); return NULL;} -void *visit(word_type_name_c *symbol) {s4o.print("WORD"); return NULL;} -void *visit(lword_type_name_c *symbol) {s4o.print("LWORD"); return NULL;} -void *visit(dword_type_name_c *symbol) {s4o.print("DWORD"); return NULL;} -void *visit(string_type_name_c *symbol) {s4o.print("STRING"); return NULL;} -void *visit(wstring_type_name_c *symbol) {s4o.print("WSTRING"); return NULL;} - -void *visit(safetime_type_name_c *symbol) {s4o.print("SAFETIME"); return NULL;} -void *visit(safebool_type_name_c *symbol) {s4o.print("SAFEBOOL"); return NULL;} -void *visit(safesint_type_name_c *symbol) {s4o.print("SAFESINT"); return NULL;} -void *visit(safeint_type_name_c *symbol) {s4o.print("SAFEINT"); return NULL;} -void *visit(safedint_type_name_c *symbol) {s4o.print("SAFEDINT"); return NULL;} -void *visit(safelint_type_name_c *symbol) {s4o.print("SAFELINT"); return NULL;} -void *visit(safeusint_type_name_c *symbol) {s4o.print("SAFEUSINT"); return NULL;} -void *visit(safeuint_type_name_c *symbol) {s4o.print("SAFEUINT"); return NULL;} -void *visit(safeudint_type_name_c *symbol) {s4o.print("SAFEUDINT"); return NULL;} -void *visit(safeulint_type_name_c *symbol) {s4o.print("SAFEULINT"); return NULL;} -void *visit(safereal_type_name_c *symbol) {s4o.print("SAFEREAL"); return NULL;} -void *visit(safelreal_type_name_c *symbol) {s4o.print("SAFELREAL"); return NULL;} -void *visit(safedate_type_name_c *symbol) {s4o.print("SAFEDATE"); return NULL;} -void *visit(safetod_type_name_c *symbol) {s4o.print("SAFETOD"); return NULL;} -void *visit(safedt_type_name_c *symbol) {s4o.print("SAFEDT"); return NULL;} -void *visit(safebyte_type_name_c *symbol) {s4o.print("SAFEBYTE"); return NULL;} -void *visit(safeword_type_name_c *symbol) {s4o.print("SAFEWORD"); return NULL;} -void *visit(safelword_type_name_c *symbol) {s4o.print("SAFELWORD"); return NULL;} -void *visit(safedword_type_name_c *symbol) {s4o.print("SAFEDWORD"); return NULL;} -void *visit(safestring_type_name_c *symbol) {s4o.print("SAFESTRING"); return NULL;} +void *visit( time_type_name_c *symbol) {s4o.print("TIME"); return NULL;} +void *visit( bool_type_name_c *symbol) {s4o.print("BOOL"); return NULL;} +void *visit( sint_type_name_c *symbol) {s4o.print("SINT"); return NULL;} +void *visit( int_type_name_c *symbol) {s4o.print("INT"); return NULL;} +void *visit( dint_type_name_c *symbol) {s4o.print("DINT"); return NULL;} +void *visit( lint_type_name_c *symbol) {s4o.print("LINT"); return NULL;} +void *visit( usint_type_name_c *symbol) {s4o.print("USINT"); return NULL;} +void *visit( uint_type_name_c *symbol) {s4o.print("UINT"); return NULL;} +void *visit( udint_type_name_c *symbol) {s4o.print("UDINT"); return NULL;} +void *visit( ulint_type_name_c *symbol) {s4o.print("ULINT"); return NULL;} +void *visit( real_type_name_c *symbol) {s4o.print("REAL"); return NULL;} +void *visit( lreal_type_name_c *symbol) {s4o.print("LREAL"); return NULL;} +void *visit( date_type_name_c *symbol) {s4o.print("DATE"); return NULL;} +void *visit( tod_type_name_c *symbol) {s4o.print("TOD"); return NULL;} +void *visit( dt_type_name_c *symbol) {s4o.print("DT"); return NULL;} +void *visit( byte_type_name_c *symbol) {s4o.print("BYTE"); return NULL;} +void *visit( word_type_name_c *symbol) {s4o.print("WORD"); return NULL;} +void *visit( lword_type_name_c *symbol) {s4o.print("LWORD"); return NULL;} +void *visit( dword_type_name_c *symbol) {s4o.print("DWORD"); return NULL;} +void *visit( string_type_name_c *symbol) {s4o.print("STRING"); return NULL;} +void *visit( wstring_type_name_c *symbol) {s4o.print("WSTRING"); return NULL;} + +void *visit( void_type_name_c *symbol) {s4o.print("VOID"); return NULL;} /* a non-standard extension! */ + +void *visit( safetime_type_name_c *symbol) {s4o.print("SAFETIME"); return NULL;} +void *visit( safebool_type_name_c *symbol) {s4o.print("SAFEBOOL"); return NULL;} +void *visit( safesint_type_name_c *symbol) {s4o.print("SAFESINT"); return NULL;} +void *visit( safeint_type_name_c *symbol) {s4o.print("SAFEINT"); return NULL;} +void *visit( safedint_type_name_c *symbol) {s4o.print("SAFEDINT"); return NULL;} +void *visit( safelint_type_name_c *symbol) {s4o.print("SAFELINT"); return NULL;} +void *visit( safeusint_type_name_c *symbol) {s4o.print("SAFEUSINT"); return NULL;} +void *visit( safeuint_type_name_c *symbol) {s4o.print("SAFEUINT"); return NULL;} +void *visit( safeudint_type_name_c *symbol) {s4o.print("SAFEUDINT"); return NULL;} +void *visit( safeulint_type_name_c *symbol) {s4o.print("SAFEULINT"); return NULL;} +void *visit( safereal_type_name_c *symbol) {s4o.print("SAFEREAL"); return NULL;} +void *visit( safelreal_type_name_c *symbol) {s4o.print("SAFELREAL"); return NULL;} +void *visit( safedate_type_name_c *symbol) {s4o.print("SAFEDATE"); return NULL;} +void *visit( safetod_type_name_c *symbol) {s4o.print("SAFETOD"); return NULL;} +void *visit( safedt_type_name_c *symbol) {s4o.print("SAFEDT"); return NULL;} +void *visit( safebyte_type_name_c *symbol) {s4o.print("SAFEBYTE"); return NULL;} +void *visit( safeword_type_name_c *symbol) {s4o.print("SAFEWORD"); return NULL;} +void *visit( safelword_type_name_c *symbol) {s4o.print("SAFELWORD"); return NULL;} +void *visit( safedword_type_name_c *symbol) {s4o.print("SAFEDWORD"); return NULL;} +void *visit( safestring_type_name_c *symbol) {s4o.print("SAFESTRING"); return NULL;} void *visit(safewstring_type_name_c *symbol) {s4o.print("SAFEWSTRING"); return NULL;} /********************************/