merge
authormjsousa
Sat, 18 Mar 2017 22:02:14 +0000
changeset 1035 0a58b2720976
parent 1034 f802b5494d56 (diff)
parent 997 7518955c875a (current diff)
child 1036 1000db86d0af
merge
stage4/generate_c/generate_c_vardecl.cc
--- 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;}
 
 /********************************/