Support for semantic verification of calls to standard functions.
authorMario de Sousa <msousa@fe.up.pt>
Fri, 29 Jul 2011 16:03:28 +0100
changeset 350 2c3c4dc34979
parent 341 ba80c3ceb6fb
child 351 e7d236750709
Support for semantic verification of calls to standard functions.
This commit makes a fundamental change in the way standard functions are handled by the compiler.
absyntax/absyntax.cc
absyntax/absyntax.def
absyntax/absyntax.hh
absyntax/visitor.cc
absyntax/visitor.hh
absyntax_utils/absyntax_utils.cc
absyntax_utils/absyntax_utils.hh
absyntax_utils/add_en_eno_param_decl.cc
absyntax_utils/function_call_param_iterator.cc
absyntax_utils/function_call_param_iterator.hh
absyntax_utils/function_param_iterator.cc
absyntax_utils/function_param_iterator.hh
absyntax_utils/search_expression_type.cc
absyntax_utils/search_expression_type.hh
absyntax_utils/spec_init_separator.cc
absyntax_utils/spec_init_separator.hh
lib/iec_std_lib.h
lib/iec_types_all.h
lib/ieclib.txt
main.cc
stage1_2/iec.flex
stage1_2/iec.y
stage3/visit_expression_type.cc
stage3/visit_expression_type.hh
stage4/generate_c/generate_c.cc
stage4/generate_c/generate_c_il.cc
stage4/generate_c/generate_c_inlinefcall.cc
stage4/generate_c/generate_c_sfc.cc
stage4/generate_c/generate_c_st.cc
stage4/generate_c/generate_c_typedecl.cc
stage4/generate_iec/generate_iec.cc
util/dsymtable.cc
util/dsymtable.hh
--- a/absyntax/absyntax.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax/absyntax.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -41,10 +41,11 @@
 //#include "../stage1_2/iec.hh" /* required for BOGUS_TOKEN_ID, etc... */
 #include "visitor.hh"
 
-#define ABORT(str) {printf("ERROR: %s\n", str); exit(0);}
-
-
-
+#define ERROR error_exit(__FILE__,__LINE__)
+/* function defined in main.cc */
+extern void error_exit(const char *file_name, int line_no);
+
+#define ABORT(str) {printf("ERROR: %s\n", str); ERROR;}
 
 
 
@@ -94,7 +95,7 @@
   add_element(elem);
 }
 
-/* insert a new element */
+/* append a new element to the end of the list */
 void list_c::add_element(symbol_c *elem) {
 //printf("list_c::add_element()\n");
   n++;
@@ -125,10 +126,24 @@
   }
 }
 
-
-
-
-#define SYM_LIST(class_name_c)									\
+/* insert a new element before position pos. */
+/* To insert into the begining of list, call with pos=0  */
+/* To insert into the end of list, call with pos=list->n */
+void list_c::insert_element(symbol_c *elem, int pos) {
+  int i;
+  if (pos > n) ERROR;
+  
+  /* add new element to end of list. Basically alocate required memory... */
+  /* will also increment n by 1 ! */
+  add_element(elem);
+  /* if not inserting into end position, shift all elements up one position, to open up a slot in pos for new element */
+  if (pos < (n-1)) for (i = n-2; i >= pos; i--) elements[i+1] = elements[i];
+  elements[pos] = elem;
+}
+
+
+
+#define SYM_LIST(class_name_c, ...)								\
 class_name_c::class_name_c(									\
                            int fl, int fc, const char *ffile, long int forder,			\
                            int ll, int lc, const char *lfile, long int lorder)			\
@@ -139,14 +154,14 @@
 			:list_c(elem, fl, fc, ffile, forder, ll, lc, lfile, lorder) {}		\
 void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
 
-#define SYM_TOKEN(class_name_c)									\
+#define SYM_TOKEN(class_name_c, ...)								\
 class_name_c::class_name_c(const char *value, 							\
                            int fl, int fc, const char *ffile, long int forder,			\
                            int ll, int lc, const char *lfile, long int lorder)			\
 			:token_c(value, fl, fc, ffile, forder, ll, lc, lfile, lorder) {}	\
 void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
 
-#define SYM_REF0(class_name_c)									\
+#define SYM_REF0(class_name_c, ...)								\
 class_name_c::class_name_c(									\
                            int fl, int fc, const char *ffile, long int forder,			\
                            int ll, int lc, const char *lfile, long int lorder)			\
@@ -154,43 +169,43 @@
 void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
 
 
-#define SYM_REF1(class_name_c, ref1)								\
-class_name_c::class_name_c(symbol_c *ref1,							\
-                           int fl, int fc, const char *ffile, long int forder,			\
-                           int ll, int lc, const char *lfile, long int lorder)			\
-			  :symbol_c(fl, fc, ffile, forder, ll, lc, lfile, lorder) {		\
-  this->ref1 = ref1;										\
-}												\
-void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
-
-
-#define SYM_REF2(class_name_c, ref1, ref2)							\
-class_name_c::class_name_c(symbol_c *ref1,							\
-			   symbol_c *ref2,							\
-                           int fl, int fc, const char *ffile, long int forder,			\
-                           int ll, int lc, const char *lfile, long int lorder)			\
-			  :symbol_c(fl, fc, ffile, forder, ll, lc, lfile, lorder) {		\
-  this->ref1 = ref1;										\
-  this->ref2 = ref2;										\
-}												\
-void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
-
-
-#define SYM_REF3(class_name_c, ref1, ref2, ref3)						\
-class_name_c::class_name_c(symbol_c *ref1,							\
-			   symbol_c *ref2,							\
-			   symbol_c *ref3,							\
-                           int fl, int fc, const char *ffile, long int forder,			\
-                           int ll, int lc, const char *lfile, long int lorder)			\
-			  :symbol_c(fl, fc, ffile, forder, ll, lc, lfile, lorder) {		\
-  this->ref1 = ref1;										\
-  this->ref2 = ref2;										\
-  this->ref3 = ref3;										\
-}												\
-void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
-
-
-#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)						\
+#define SYM_REF1(class_name_c, ref1, ...)							\
+class_name_c::class_name_c(symbol_c *ref1,							\
+                           int fl, int fc, const char *ffile, long int forder,			\
+                           int ll, int lc, const char *lfile, long int lorder)			\
+			  :symbol_c(fl, fc, ffile, forder, ll, lc, lfile, lorder) {		\
+  this->ref1 = ref1;										\
+}												\
+void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
+
+
+#define SYM_REF2(class_name_c, ref1, ref2, ...)							\
+class_name_c::class_name_c(symbol_c *ref1,							\
+			   symbol_c *ref2,							\
+                           int fl, int fc, const char *ffile, long int forder,			\
+                           int ll, int lc, const char *lfile, long int lorder)			\
+			  :symbol_c(fl, fc, ffile, forder, ll, lc, lfile, lorder) {		\
+  this->ref1 = ref1;										\
+  this->ref2 = ref2;										\
+}												\
+void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
+
+
+#define SYM_REF3(class_name_c, ref1, ref2, ref3, ...)						\
+class_name_c::class_name_c(symbol_c *ref1,							\
+			   symbol_c *ref2,							\
+			   symbol_c *ref3,							\
+                           int fl, int fc, const char *ffile, long int forder,			\
+                           int ll, int lc, const char *lfile, long int lorder)			\
+			  :symbol_c(fl, fc, ffile, forder, ll, lc, lfile, lorder) {		\
+  this->ref1 = ref1;										\
+  this->ref2 = ref2;										\
+  this->ref3 = ref3;										\
+}												\
+void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
+
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...)					\
 class_name_c::class_name_c(symbol_c *ref1,							\
 			   symbol_c *ref2,							\
 			   symbol_c *ref3,							\
@@ -206,7 +221,7 @@
 void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
 
 
-#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5)					\
+#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...)				\
 class_name_c::class_name_c(symbol_c *ref1,							\
 			   symbol_c *ref2,							\
 			   symbol_c *ref3,							\
@@ -225,7 +240,7 @@
 
 
 
-#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)				\
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6, ...)				\
 class_name_c::class_name_c(symbol_c *ref1,							\
 			   symbol_c *ref2,							\
 			   symbol_c *ref3,							\
--- a/absyntax/absyntax.def	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax/absyntax.def	Fri Jul 29 16:03:28 2011 +0100
@@ -538,6 +538,33 @@
 /* | var1_list ',' variable_name */
 SYM_LIST(var1_list_c)
 
+/* | [var1_list ','] variable_name integer '..' */
+/* NOTE: This is an extension to the standard!!! */
+/* In order to be able to handle extensible standard functions
+ * (i.e. standard functions that may have a variable number of
+ * input parameters, such as AND(word#33, word#44, word#55, word#66),
+ * we have extended the acceptable syntax to allow var_name '..'
+ * in an input variable declaration.
+ *
+ * This allows us to parse the declaration of standard
+ * extensible functions and load their interface definition
+ * into the abstract syntax tree just like we do to other 
+ * user defined functions.
+ * This has the advantage that we can later do semantic
+ * checking of calls to functions (be it a standard or user defined
+ * function) in (almost) exactly the same way.
+ *
+ * The integer tells the compiler the number of the first parameter.
+ * for example, for ADD(IN1 := 11, IN2:=22), the index for IN starts off at 1.
+ * Some other standard library functions, such as MUX, has the extensible
+ * variable starting off from 0 (IN0, IN1, IN2, ...).
+ *
+ * Of course, we have a flag that disables this syntax when parsing user
+ * written code, so we only allow this extra syntax while parsing the 
+ * 'header' file that declares all the standard IEC 61131-3 functions.
+ */
+SYM_REF2(extensible_input_parameter_c, var_name, first_index)
+
 /* var1_list ':' array_spec_init */
 SYM_REF2(array_var_init_decl_c, var1_list, array_spec_init)
 
@@ -632,7 +659,15 @@
 /*  STRING ['[' integer ']'] [ASSIGN single_byte_character_string] */
 /* integer ->may be NULL ! */
 /* single_byte_character_string ->may be NULL ! */
-SYM_REF2(single_byte_string_spec_c, integer, single_byte_character_string)
+SYM_REF2(single_byte_string_spec_c, string_spec, single_byte_character_string)
+
+/*   STRING ['[' integer ']'] */
+/* integer ->may be NULL ! */
+SYM_REF2(single_byte_limited_len_string_spec_c, string_type_name, character_string_len)
+
+/*  WSTRING ['[' integer ']'] */
+/* integer ->may be NULL ! */
+SYM_REF2(double_byte_limited_len_string_spec_c, string_type_name, character_string_len)
 
 /*  var1_list ':' double_byte_string_spec */
 SYM_REF2(double_byte_string_var_declaration_c, var1_list, double_byte_string_spec)
@@ -640,7 +675,7 @@
 /*  WSTRING ['[' integer ']'] [ASSIGN double_byte_character_string] */
 /* integer ->may be NULL ! */
 /* double_byte_character_string ->may be NULL ! */
-SYM_REF2(double_byte_string_spec_c, integer, double_byte_character_string)
+SYM_REF2(double_byte_string_spec_c, string_spec, double_byte_character_string)
 
 /*| VAR [RETAIN|NON_RETAIN] incompl_located_var_decl_list END_VAR */
 /* option ->may be NULL ! */
@@ -885,7 +920,10 @@
 SYM_REF2(il_simple_operation_c, il_simple_operator, il_operand)
 
 /* | function_name [il_operand_list] */
-SYM_REF2(il_function_call_c, function_name, il_operand_list)
+/* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4.
+ *       See the comment above function_invocation_c for more details 
+ */
+SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;)
 
 
 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
@@ -904,7 +942,10 @@
 
 
 /* | function_name '(' eol_list [il_param_list] ')' */
-SYM_REF2(il_formal_funct_call_c, function_name, il_param_list)
+/* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4.
+ *       See the comment above function_invocation_c for more details 
+ */
+SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;)
 
 /* | il_operand_list ',' il_operand */
 SYM_LIST(il_operand_list_c)
@@ -1004,7 +1045,17 @@
 
 /*    formal_param_list -> may be NULL ! */
 /* nonformal_param_list -> may be NULL ! */
-SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list)
+/* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4.
+ *       The IEC 61131-3 standard allows for overloaded standard functions. This means that some
+ *       function calls are not compeletely defined by the name of the function being called,
+ *       and need to be disambiguated with using the data types of the parameters being passed.
+ *       Stage 3 does this to verify semantic correctnes.
+ *       Stage 4 also needs to do this in order to determine which function to call.
+ *       It does not make sense to determine the exact function being called twice (once in stage 3,
+ *       and again in stage 4), so stage 3 will store this infor in the parameter called_function_declaration
+ *       for stage 4 to use it later on.
+ */
+SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count;)
 
 
 /********************/
--- a/absyntax/absyntax.hh	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax/absyntax.hh	Fri Jul 29 16:03:28 2011 +0100
@@ -119,16 +119,22 @@
            int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0, /* order in which it is read by lexcial analyser */
            int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0  /* order in which it is read by lexcial analyser */
           );
-     /* insert a new element */
+     /* append a new element to the end of the list */
     virtual void add_element(symbol_c *elem);
-};
-
-
-
-
-#define SYM_LIST(class_name_c)												\
+     /* insert a new element before position pos. */
+     /* To insert into the begining of list, call with pos=0  */
+     /* To insert into the end of list, call with pos=list->n */
+    virtual void insert_element(symbol_c *elem, int pos = 0);
+};
+
+
+
+
+#define SYM_LIST(class_name_c, ...)												\
 class class_name_c:	public list_c {											\
   public:														\
+    __VA_ARGS__														\
+  public:														\
     class_name_c(													\
                  int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0,			\
                  int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0);			\
@@ -139,9 +145,11 @@
 };
 
 
-#define SYM_TOKEN(class_name_c)												\
+#define SYM_TOKEN(class_name_c, ...)												\
 class class_name_c: 	public token_c {										\
   public:														\
+    __VA_ARGS__														\
+  public:														\
     class_name_c(const char *value, 											\
                  int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0,			\
                  int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0);			\
@@ -149,8 +157,10 @@
 };
 
 
-#define SYM_REF0(class_name_c)												\
-class class_name_c: public symbol_c {											\
+#define SYM_REF0(class_name_c, ...)												\
+class class_name_c: public symbol_c {											\
+  public:														\
+    __VA_ARGS__														\
   public:														\
     class_name_c(		 											\
                  int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0,			\
@@ -159,23 +169,25 @@
 };
 
 
-#define SYM_REF1(class_name_c, ref1)											\
-class class_name_c: public symbol_c {											\
-  public:														\
-    symbol_c *ref1;													\
-  public:														\
-    class_name_c(symbol_c *ref1,											\
-                 int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0,			\
-                 int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0);			\
-    virtual void *accept(visitor_c &visitor);										\
-};
-
-
-#define SYM_REF2(class_name_c, ref1, ref2)										\
-class class_name_c: public symbol_c {											\
-  public:														\
-    symbol_c *ref1;													\
-    symbol_c *ref2;													\
+#define SYM_REF1(class_name_c, ref1, ...)										\
+class class_name_c: public symbol_c {											\
+  public:														\
+    symbol_c *ref1;													\
+    __VA_ARGS__														\
+  public:														\
+    class_name_c(symbol_c *ref1,											\
+                 int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0,			\
+                 int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0);			\
+    virtual void *accept(visitor_c &visitor);										\
+};
+
+
+#define SYM_REF2(class_name_c, ref1, ref2, ...)										\
+class class_name_c: public symbol_c {											\
+  public:														\
+    symbol_c *ref1;													\
+    symbol_c *ref2;													\
+    __VA_ARGS__														\
   public:														\
     class_name_c(symbol_c *ref1,											\
 		 symbol_c *ref2 = NULL,											\
@@ -185,29 +197,31 @@
 };
 
 
-#define SYM_REF3(class_name_c, ref1, ref2, ref3)									\
-class class_name_c: public symbol_c {											\
-  public:														\
-    symbol_c *ref1;													\
-    symbol_c *ref2;													\
-    symbol_c *ref3;													\
-  public:														\
-    class_name_c(symbol_c *ref1,											\
-		 symbol_c *ref2,											\
-		 symbol_c *ref3,											\
-                 int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0,			\
-                 int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0);			\
-    virtual void *accept(visitor_c &visitor);										\
-};
-
-
-#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)									\
+#define SYM_REF3(class_name_c, ref1, ref2, ref3, ...)									\
+class class_name_c: public symbol_c {											\
+  public:														\
+    symbol_c *ref1;													\
+    symbol_c *ref2;													\
+    symbol_c *ref3;													\
+    __VA_ARGS__														\
+  public:														\
+    class_name_c(symbol_c *ref1,											\
+		 symbol_c *ref2,											\
+		 symbol_c *ref3,											\
+                 int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0,			\
+                 int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0);			\
+    virtual void *accept(visitor_c &visitor);										\
+};
+
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...)								\
 class class_name_c: public symbol_c {											\
   public:														\
     symbol_c *ref1;													\
     symbol_c *ref2;													\
     symbol_c *ref3;													\
     symbol_c *ref4;													\
+    __VA_ARGS__														\
   public:														\
     class_name_c(symbol_c *ref1,											\
 		 symbol_c *ref2,											\
@@ -219,7 +233,7 @@
 };
 
 
-#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5)								\
+#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...)								\
 class class_name_c: public symbol_c {											\
   public:														\
     symbol_c *ref1;													\
@@ -227,6 +241,7 @@
     symbol_c *ref3;													\
     symbol_c *ref4;													\
     symbol_c *ref5;													\
+    __VA_ARGS__														\
   public:														\
     class_name_c(symbol_c *ref1,											\
 		 symbol_c *ref2,											\
@@ -239,7 +254,7 @@
 };
 
 
-#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)							\
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6, ...)							\
 class class_name_c: public symbol_c {											\
   public:														\
     symbol_c *ref1;													\
@@ -248,6 +263,7 @@
     symbol_c *ref4;													\
     symbol_c *ref5;													\
     symbol_c *ref6;													\
+    __VA_ARGS__														\
   public:														\
     class_name_c(symbol_c *ref1,											\
 		 symbol_c *ref2,											\
--- a/absyntax/visitor.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax/visitor.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -82,19 +82,19 @@
 #define SYM_REF1(class_name_c, ref1)	\
   void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
 
-#define SYM_REF2(class_name_c, ref1, ref2)	\
-  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
-
-#define SYM_REF3(class_name_c, ref1, ref2, ref3)	\
-  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
-
-#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)	\
-  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
-
-#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5)	\
-  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
-
-#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+#define SYM_REF2(class_name_c, ref1, ref2, ...)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF3(class_name_c, ref1, ref2, ref3, ...)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6, ...)	\
   void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
 
 
@@ -148,31 +148,31 @@
   return NULL;						\
 }
 
-#define SYM_REF2(class_name_c, ref1, ref2)		\
+#define SYM_REF2(class_name_c, ref1, ref2, ...)		\
 void *iterator_visitor_c::visit(class_name_c *symbol) {	\
   if (symbol->ref1!=NULL) symbol->ref1->accept(*this);	\
   if (symbol->ref2!=NULL) symbol->ref2->accept(*this);	\
   return NULL;						\
 }
 
-#define SYM_REF3(class_name_c, ref1, ref2, ref3)	\
-void *iterator_visitor_c::visit(class_name_c *symbol) {	\
-  if (symbol->ref1) symbol->ref1->accept(*this);	\
-  if (symbol->ref2) symbol->ref2->accept(*this);	\
-  if (symbol->ref3) symbol->ref3->accept(*this);	\
-  return NULL;						\
-}
-
-#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)	\
-void *iterator_visitor_c::visit(class_name_c *symbol) {	\
-  if (symbol->ref1) symbol->ref1->accept(*this);	\
-  if (symbol->ref2) symbol->ref2->accept(*this);	\
-  if (symbol->ref3) symbol->ref3->accept(*this);	\
-  if (symbol->ref4) symbol->ref4->accept(*this);	\
-  return NULL;						\
-}
-
-#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5)		\
+#define SYM_REF3(class_name_c, ref1, ref2, ref3, ...)			\
+void *iterator_visitor_c::visit(class_name_c *symbol) {			\
+  if (symbol->ref1) symbol->ref1->accept(*this);			\
+  if (symbol->ref2) symbol->ref2->accept(*this);			\
+  if (symbol->ref3) symbol->ref3->accept(*this);			\
+  return NULL;								\
+}
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...)		\
+void *iterator_visitor_c::visit(class_name_c *symbol) {			\
+  if (symbol->ref1) symbol->ref1->accept(*this);			\
+  if (symbol->ref2) symbol->ref2->accept(*this);			\
+  if (symbol->ref3) symbol->ref3->accept(*this);			\
+  if (symbol->ref4) symbol->ref4->accept(*this);			\
+  return NULL;								\
+}
+
+#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...)	\
 void *iterator_visitor_c::visit(class_name_c *symbol) {			\
   if (symbol->ref1) symbol->ref1->accept(*this);			\
   if (symbol->ref2) symbol->ref2->accept(*this);			\
@@ -182,7 +182,7 @@
   return NULL;								\
 }
 
-#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6, ...)	\
 void *iterator_visitor_c::visit(class_name_c *symbol) {			\
   if (symbol->ref1) symbol->ref1->accept(*this);			\
   if (symbol->ref2) symbol->ref2->accept(*this);			\
@@ -250,7 +250,7 @@
   return NULL;							\
 }
 
-#define SYM_REF2(class_name_c, ref1, ref2)			\
+#define SYM_REF2(class_name_c, ref1, ref2, ...)			\
 void *search_visitor_c::visit(class_name_c *symbol) {		\
   void *res = NULL;						\
   if (symbol->ref1) res =  symbol->ref1->accept(*this);		\
@@ -259,7 +259,7 @@
   return NULL;							\
 }
 
-#define SYM_REF3(class_name_c, ref1, ref2, ref3)		\
+#define SYM_REF3(class_name_c, ref1, ref2, ref3, ...)		\
 void *search_visitor_c::visit(class_name_c *symbol) {		\
   void *res = NULL;						\
   if (symbol->ref1) res =  symbol->ref1->accept(*this);		\
@@ -270,7 +270,7 @@
   return NULL;							\
 }
 
-#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)		\
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...)		\
 void *search_visitor_c::visit(class_name_c *symbol) {		\
   void *res = NULL;						\
   if (symbol->ref1) res =  symbol->ref1->accept(*this);		\
@@ -283,7 +283,7 @@
   return NULL;							\
 }
 
-#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5)		\
+#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...)		\
 void *search_visitor_c::visit(class_name_c *symbol) {			\
   void *res = NULL;							\
   if (symbol->ref1) res =  symbol->ref1->accept(*this);			\
@@ -298,7 +298,7 @@
   return NULL;								\
 }
 
-#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6, ...)	\
 void *search_visitor_c::visit(class_name_c *symbol) {			\
   void *res = NULL;							\
   if (symbol->ref1) res =  symbol->ref1->accept(*this);			\
--- a/absyntax/visitor.hh	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax/visitor.hh	Fri Jul 29 16:03:28 2011 +0100
@@ -78,31 +78,31 @@
 
 
 
-#define SYM_LIST(class_name_c)	\
-  virtual void *visit(class_name_c *symbol) = 0;
-
-#define SYM_TOKEN(class_name_c)	\
-  virtual void *visit(class_name_c *symbol) = 0;
-
-#define SYM_REF0(class_name_c)	\
-  virtual void *visit(class_name_c *symbol) = 0;
-
-#define SYM_REF1(class_name_c, ref1)		\
-  virtual void *visit(class_name_c *symbol) = 0;
-
-#define SYM_REF2(class_name_c, ref1, ref2)	\
-  virtual void *visit(class_name_c *symbol) = 0;
-
-#define SYM_REF3(class_name_c, ref1, ref2, ref3)	\
-  virtual void *visit(class_name_c *symbol) = 0;
-
-#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)	\
-  virtual void *visit(class_name_c *symbol) = 0;
-
-#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5)		\
-  virtual void *visit(class_name_c *symbol) = 0;
-
-#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+#define SYM_LIST(class_name_c, ...)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_TOKEN(class_name_c, ...)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_REF0(class_name_c, ...)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_REF1(class_name_c, ref1, ...)		\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_REF2(class_name_c, ref1, ref2, ...)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_REF3(class_name_c, ref1, ref2, ref3, ...)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...)		\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6, ...)	\
   virtual void *visit(class_name_c *symbol) = 0;
 
 class visitor_c {
@@ -127,31 +127,31 @@
 
 
 
-#define SYM_LIST(class_name_c)	\
-  virtual void *visit(class_name_c *symbol);
-
-#define SYM_TOKEN(class_name_c)	\
-  virtual void *visit(class_name_c *symbol);
-
-#define SYM_REF0(class_name_c)	\
-  virtual void *visit(class_name_c *symbol);
-
-#define SYM_REF1(class_name_c, ref1)		\
-  virtual void *visit(class_name_c *symbol);
-
-#define SYM_REF2(class_name_c, ref1, ref2)	\
-  virtual void *visit(class_name_c *symbol);
-
-#define SYM_REF3(class_name_c, ref1, ref2, ref3)	\
-  virtual void *visit(class_name_c *symbol);
-
-#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)	\
-  virtual void *visit(class_name_c *symbol);
-
-#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5)		\
-  virtual void *visit(class_name_c *symbol);
-
-#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+#define SYM_LIST(class_name_c, ...)	\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_TOKEN(class_name_c, ...)	\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_REF0(class_name_c, ...)	\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_REF1(class_name_c, ref1, ...)		\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_REF2(class_name_c, ref1, ref2, ...)	\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_REF3(class_name_c, ref1, ref2, ref3, ...)	\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...)	\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...)		\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6, ...)	\
   virtual void *visit(class_name_c *symbol);
 
 
--- a/absyntax_utils/absyntax_utils.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax_utils/absyntax_utils.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -50,6 +50,7 @@
 #include <typeinfo>
 #include <list>
 #include <strings.h>
+#include <stdlib.h>  /* required for atoi() */
 
 #include "../util/symtable.hh"
 #include "../util/dsymtable.hh"
@@ -94,6 +95,15 @@
 }
 
 
+/* extract the value of an integer from an integer_c object !! */
+/* NOTE: it must ignore underscores! */
+int extract_integer(symbol_c *sym) {
+  integer_c *integer = dynamic_cast<integer_c *>(sym);  
+  if (integer == NULL) ERROR;
+  
+  return atoi(integer->value);
+}
+
 
 /***********************************************************************/
 /***********************************************************************/
--- a/absyntax_utils/absyntax_utils.hh	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax_utils/absyntax_utils.hh	Fri Jul 29 16:03:28 2011 +0100
@@ -55,9 +55,13 @@
 /* returns 0 if the names are equal!! Case is ignored. */
 int compare_identifiers(symbol_c *ident1, symbol_c *ident2);
 
+/* extract the value of an integer from an integer_c object !! */
+int extract_integer(symbol_c *integer);
+  
 /* A symbol table with all globally declared functions... */
 extern function_declaration_c null_symbol1;
-extern dsymtable_c<function_declaration_c *, &null_symbol1> function_symtable;
+typedef dsymtable_c<function_declaration_c *, &null_symbol1> function_symtable_t;
+extern function_symtable_t function_symtable;
 
 /* A symbol table with all globally declared functions block types... */
 extern function_block_declaration_c null_symbol2;
--- a/absyntax_utils/add_en_eno_param_decl.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax_utils/add_en_eno_param_decl.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -150,8 +150,17 @@
     en_declared  = false; 
     eno_declared = false; 
     iterate_list(symbol);
+    /* insert elements to begining of list! */
+    /* We want EN first, and then ENO.
+     * But, since we are insertin them into the head of the list, we must insert EN last so it will stay in the first position!
+     */
+    if(eno_declared == false) symbol->insert_element(build_eno_param());
+    if(en_declared  == false) symbol->insert_element(build_en_param());
+    /* append elements to end of list! */
+    /*
     if(en_declared  == false) symbol->add_element(build_en_param());
     if(eno_declared == false) symbol->add_element(build_eno_param());
+    */
     return NULL;
 }
 
--- a/absyntax_utils/function_call_param_iterator.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax_utils/function_call_param_iterator.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -221,6 +221,13 @@
   return (symbol_c *)res;
 }
 
+/* Search for the value passed to the parameter named <param_name>...  */
+symbol_c *function_call_param_iterator_c::search_f(const char *param_name) {
+  identifier_c tmp_indentifier(param_name);
+  return search_f(&tmp_indentifier);
+}
+
+
 /* Returns the value being passed to the current parameter. */
 symbol_c *function_call_param_iterator_c::get_current_value(void) {
   return current_value;
--- a/absyntax_utils/function_call_param_iterator.hh	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax_utils/function_call_param_iterator.hh	Fri Jul 29 16:03:28 2011 +0100
@@ -104,6 +104,7 @@
 
     /* Search for the value passed to the parameter named <param_name>...  */
     symbol_c *search_f(symbol_c *param_name);
+    symbol_c *search_f(const char *param_name);
 
     /* Returns the value being passed to the current parameter. */
     symbol_c *get_current_value(void);
--- a/absyntax_utils/function_param_iterator.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax_utils/function_param_iterator.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -48,8 +48,11 @@
 
 
 
-#include "function_param_iterator.hh"
-#include "spec_init_separator.hh"
+#include "absyntax_utils.hh"  /* required for extract_integer() */
+// #include "function_param_iterator.hh"  /* no longer required, aready included by absyntax_utils.hh */
+// #include "spec_init_separator.hh"  /* no longer required, aready included by absyntax_utils.hh */
+#include <stdlib.h>  /* required for strtol() */
+#include <string.h>
 #include <strings.h>
 
 
@@ -67,6 +70,49 @@
 
 
 
+/* compare the name of two __extensible__ function parameters.
+ * The usual use case is to have one of the parameters as used
+ * in the function declaration, and another as used in a formal function call.
+ *
+ * Will return:
+ *         < 0 : if two parameters are not compatible, or one is invalid
+ *        >= 0 : if both parameters ..........
+ */
+/*
+ *   ("in", "i0")      -> returns error (<0)
+ *   ("in1", "in")     -> returns error (<0)
+ *   ("in", "in")      -> returns error (<0)
+ *   ("in", "inw")     -> returns error (<0)
+ *   ("in", "in10.4")  -> returns error (<0)
+ *   ("in", "in10e")   -> returns error (<0)
+ *   ("in", "")        -> returns error (<0)
+ *   ("", "in10e")     -> returns error (<0)
+ *   ("in", "in0")     -> returns 0
+ *   ("in", "in9")     -> returns 9
+ *   ("in", "in42")    -> returns 42
+ *   ("in", "in-42")   -> returns -42 (error!)
+ */
+int function_param_iterator_c::cmp_extparam_names(const char* s1, const char* s2) {
+  int res;
+  char *endptr;
+  int len;
+
+  if ((s1 == NULL) || (s2 == NULL) || (*s1 == '\0') || (*s2 == '\0')) return -1;
+
+  len = strlen(s1);
+  if (strncasecmp(s1, s2, len)) return -2;
+
+  s1 = &s2[len];
+  if (*s1 == '\0') return -3;
+
+  res = strtol(s1, &endptr, 10);
+  if (*endptr != '\0') return -4;
+
+  return res;
+}
+
+
+
 void* function_param_iterator_c::handle_param_list(list_c *list) {
   switch (current_operation) {
     case iterate_op:
@@ -79,12 +125,27 @@
 
     case search_op:
       for(int i = 0; i < list->n; i++) {
-        identifier_c *variable_name = dynamic_cast<identifier_c *>(list->elements[i]);
+        symbol_c *sym = list->elements[i];
+        extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(sym);
+        if (extensible_parameter != NULL) {
+          sym = extensible_parameter->var_name;
+          current_param_is_extensible = true;
+          _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
+        }
+        identifier_c *variable_name = dynamic_cast<identifier_c *>(sym);
         if (variable_name == NULL) ERROR;
-
-        if (strcasecmp(search_param_name->value, variable_name->value) == 0)
-          /* FOUND! This is the same parameter!! */
-          return (void *)variable_name;
+        
+        if (!current_param_is_extensible)
+          if (strcasecmp(search_param_name->value, variable_name->value) == 0)
+            /* FOUND! This is the same parameter!! */
+            return (void *)variable_name;
+  
+        if (current_param_is_extensible) {
+          current_extensible_param_index = cmp_extparam_names(variable_name->value, search_param_name->value);
+          if (current_extensible_param_index >= 0)
+            /* FOUND! This is a compatible extensible parameter!! */
+            return (void *)variable_name;
+        }  
       }
       break;
   } /* switch */
@@ -102,12 +163,26 @@
       break;
 
     case search_op:
+      extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(var_name);
+      if (extensible_parameter != NULL) {
+        var_name = extensible_parameter->var_name;
+        current_param_is_extensible = true;
+        _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
+      }
       identifier_c *variable_name = dynamic_cast<identifier_c *>(var_name);
       if (variable_name == NULL) ERROR;
-
-      if (strcasecmp(search_param_name->value, variable_name->value) == 0)
-        /* FOUND! This is the same parameter!! */
-        return (void *)variable_name;
+      
+      if (!current_param_is_extensible)
+        if (strcasecmp(search_param_name->value, variable_name->value) == 0)
+          /* FOUND! This is the same parameter!! */
+          return (void *)variable_name;
+
+      if (current_param_is_extensible) {
+        current_extensible_param_index = cmp_extparam_names(variable_name->value, search_param_name->value);
+        if (current_extensible_param_index >= 0)
+          /* FOUND! This is a compatible extensible parameter!! */
+          return (void *)variable_name;
+      }  
       break;
   } /* switch */
 
@@ -128,6 +203,8 @@
 /* start off at the first parameter once again... */
 void function_param_iterator_c::reset(void) {
   next_param = param_count = 0;
+  _first_extensible_param_index = -1;
+  current_param_is_extensible = false;
   current_param_name = NULL;
   current_param_type = current_param_default_value = NULL;
 }
@@ -166,6 +243,11 @@
   void *res;
   identifier_c *identifier;
  
+  if (current_param_is_extensible) {
+    current_extensible_param_index++;
+    return current_param_name;
+  }
+  
   param_count = 0;
   en_eno_param_implicit = false;
   next_param++;
@@ -175,6 +257,13 @@
     return NULL;
 
   symbol_c *sym = (symbol_c *)res;
+  extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(sym);
+  if (extensible_parameter != NULL) {
+    sym = extensible_parameter->var_name;
+    current_param_is_extensible = true;
+    _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
+    current_extensible_param_index = _first_extensible_param_index;
+  }
   identifier = dynamic_cast<identifier_c *>(sym);
   if (identifier == NULL)
     ERROR;
@@ -187,6 +276,8 @@
   if (NULL == param_name) ERROR;
   search_param_name = dynamic_cast<identifier_c *>(param_name);
   if (NULL == search_param_name) ERROR;
+  en_eno_param_implicit = false;
+  current_param_is_extensible = false;
   current_operation = function_param_iterator_c::search_op;
   void *res = f_decl->accept(*this);
   identifier_c *res_param_name = dynamic_cast<identifier_c *>((symbol_c *)res);
@@ -210,6 +301,24 @@
   return en_eno_param_implicit;
 }
 
+/* Returns if currently referenced parameter is an extensible parameter. */
+/* extensible paramters only occur in some standard functions, e.g. AND(word#34, word#44, word#65); */
+bool function_param_iterator_c::is_extensible_param(void) {
+  return current_param_is_extensible;
+}
+
+/* Returns the index of the current extensible parameter. */             
+/* If the current parameter is not an extensible paramter, returns -1 */
+int function_param_iterator_c::extensible_param_index(void) {
+  return (current_param_is_extensible? current_extensible_param_index : -1);
+}
+
+/* Returns the index of the first extensible parameter, or -1 if no extensible parameter found. */             
+/* WARNING: Will only return the correct value _after_ an extensible parameter has been found! */
+int function_param_iterator_c::first_extensible_param_index(void) {
+  return _first_extensible_param_index;
+}
+
 /* Returns the currently referenced parameter's data passing direction.
  * i.e. VAR_INPUT, VAR_OUTPUT or VAR_INOUT
  */
@@ -218,7 +327,7 @@
 }
 
 void *function_param_iterator_c::visit(implicit_definition_c *symbol) {
-	en_eno_param_implicit = current_operation == function_param_iterator_c::iterate_op;
+	en_eno_param_implicit = true;
 	return NULL;
 }
 
@@ -243,12 +352,15 @@
    * variables will get overwritten when we visit the next
    * var1_init_decl_c list!
    */
-  symbol->method->accept(*this);
-
   current_param_default_value = symbol->value;
   current_param_type = symbol->type;
 
-  return handle_single_param(symbol->name);
+  void *res = handle_single_param(symbol->name);
+  
+    /* If we have found the parameter we will be returning, we set the en_eno_param_implicit to TRUE if implicitly defined */
+  if (res != NULL) symbol->method->accept(*this);
+  
+  return res;
 }
 
 /* var1_list ':' array_spec_init */
@@ -278,6 +390,7 @@
   current_param_direction = direction_out;
   return symbol->var_init_decl_list->accept(*this);
 }
+
 void *function_param_iterator_c::visit(eno_param_declaration_c *symbol) {
   TRACE("eno_param_declaration_c");
   /* It is OK to store these values in the current_param_XXX
@@ -286,18 +399,23 @@
    * variables will get overwritten when we visit the next
    * var1_init_decl_c list!
    */
-  symbol->method->accept(*this);
-
   current_param_default_value = NULL;
   current_param_type = symbol->type;
 
-  return handle_single_param(symbol->name);
-}
+  void *res = handle_single_param(symbol->name);
+  
+    /* If we have found the parameter we will be returning, we set the en_eno_param_implicit to TRUE if implicitly defined */
+  if (res != NULL) symbol->method->accept(*this);
+  
+  return res;
+}
+
 void *function_param_iterator_c::visit(input_output_declarations_c *symbol) {
   TRACE("input_output_declarations_c");
   current_param_direction = direction_inout;
   return symbol->var_declaration_list->accept(*this);
 }
+
 void *function_param_iterator_c::visit(var_declaration_list_c *symbol) {TRACE("var_declaration_list_c"); return iterate_list(symbol);}
 
 /*  var1_list ':' array_specification */
@@ -425,12 +543,12 @@
 }
 
 
-
 void *function_param_iterator_c::visit(var1_list_c *symbol) {
   TRACE("var1_list_c");
   return handle_param_list(symbol);
 }
 
+
 void *function_param_iterator_c::visit(var_init_decl_list_c *symbol) {TRACE("var_init_decl_list_c"); return iterate_list(symbol);}
 
 
--- a/absyntax_utils/function_param_iterator.hh	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax_utils/function_param_iterator.hh	Fri Jul 29 16:03:28 2011 +0100
@@ -90,6 +90,16 @@
     symbol_c *current_param_default_value;
     param_direction_t current_param_direction;
     bool en_eno_param_implicit;
+    /* used when we reach an extensible parameter in the function declaration */
+    /* NOTE: this will handle syntax that is not in the standard.
+     *       It is used to handle the extensible standard functions
+     *       (e.g. AND(word#3, word#55, word#44); )
+     *       See absyntax.def or iec.y for more details.
+     */
+    bool current_param_is_extensible;
+    int  current_extensible_param_index;
+    int  _first_extensible_param_index;
+
     /* Which operation of the class was called...
      * Search a parameter, or iterate to the next parameter.
      */
@@ -97,6 +107,7 @@
     operation_t current_operation;
 
   private:
+    int   cmp_extparam_names(const char* s1, const char* s2);
     void* handle_param_list(list_c *list);
     void* handle_single_param(symbol_c *var_name);
 
@@ -128,7 +139,8 @@
     /* The seach() function does not in any way affect the internal state related 
      * to the iterate() function.
      * It will, however, affect the internal state necessary to correctly
-     * return the param_type() and default_value() of the found parameter.
+     * return the param_type(), default_value() and is_en_eno_param_implicit()
+     * of the found parameter.
      */
     identifier_c *search(symbol_c *param_name);
 
@@ -143,6 +155,16 @@
     /* Returns if currently referenced parameter is an implicit defined EN/ENO parameter. */
     bool is_en_eno_param_implicit(void);
 
+    /* Returns if currently referenced parameter is an extensible parameter. */
+    /* extensible paramters only occur in some standard functions, e.g. AND(word#34, word#44, word#65); */
+    bool is_extensible_param(void);
+    /* Returns the index of the current extensible parameter. */             
+    /* If the current parameter is not an extensible paramter, returns -1 */
+    int extensible_param_index(void);
+    /* Returns the index of the first extensible parameter, or -1 if no extensible parameter found. */             
+    /* WARNING: Will only return the correct value _after_ an extensible parameter has been found! */
+    int first_extensible_param_index(void);
+    
     /* Returns the currently referenced parameter's data passing direction.
      * i.e. VAR_INPUT, VAR_OUTPUT or VAR_INOUT
      */
--- a/absyntax_utils/search_expression_type.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax_utils/search_expression_type.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -202,11 +202,6 @@
 }
 
 
-integer_c search_expression_type_c::integer("1"); // what default value should we use here ???
-#include "search_type_code.c"
-
-/*static bool_type_name_c bool_type_name;*/
-
 /* A helper function... */
 void *search_expression_type_c::compute_boolean_expression(symbol_c *left_type, symbol_c *right_type) {
   if (!is_same_type(left_type, right_type))
@@ -385,13 +380,8 @@
 }
 
 void *search_expression_type_c::visit(function_invocation_c *symbol) {
-  function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
-  if (f_decl == function_symtable.end_value()) {
-    void *res = compute_standard_function_default(symbol);
-    if (res == NULL)
-       ERROR;
-    return res;
-  }
+  function_declaration_c *f_decl = (function_declaration_c *)symbol->called_function_declaration;
+  if (f_decl == NULL) ERROR;
   return base_type(f_decl->type_name);
 }
 
--- a/absyntax_utils/search_expression_type.hh	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax_utils/search_expression_type.hh	Fri Jul 29 16:03:28 2011 +0100
@@ -39,6 +39,18 @@
  *       etc...
  */
 
+/* WARNING   WARNING  WARNING
+ *
+ * When taking into consideration calls to functions, this search_expression_type_c
+ * class will use internal atributes (i.e. anotation) in the function_invocation_c symbol 
+ * in the abstract syntax tree.
+ *
+ * Since this anotation/atribute is only set/populated with the correct value
+ * during stage3 (semantic verification), this class will only work correctly
+ * after the semantic verification in stage 3 has been executed
+ * (to be more exact, the data type checking of stage 3).
+ */
+
 class search_expression_type_c: public search_constant_type_c {
 
   private:
--- a/absyntax_utils/spec_init_separator.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax_utils/spec_init_separator.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -176,5 +176,35 @@
   return NULL;
 }
 
+
+/* STRING '[' integer ']' 
+ * STRING ASSIGN single_byte_character_string
+ * STRING '[' integer ']' ASSIGN single_byte_character_string
+ */
+void *spec_init_sperator_c::visit(single_byte_string_spec_c *symbol) {
+  TRACE("spec_init_sperator_c::single_byte_string_spec_c");
+  switch (search_what) {
+    case search_spec: return symbol->string_spec;
+    case search_init: return symbol->single_byte_character_string;
+  }
+  ERROR; /* should never occur */
+  return NULL;
+}
+
+/* WSTRING '[' integer ']' 
+ * WSTRING ASSIGN double_byte_character_string
+ * WSTRING '[' integer ']' ASSIGN double_byte_character_string
+ */
+void *spec_init_sperator_c::visit(double_byte_string_spec_c *symbol) {
+  TRACE("spec_init_sperator_c::double_byte_string_spec_c");
+  switch (search_what) {
+    case search_spec: return symbol->string_spec;
+    case search_init: return symbol->double_byte_character_string;
+  }
+  ERROR; /* should never occur */
+  return NULL;
+}
+
+
 spec_init_sperator_c *spec_init_sperator_c ::class_instance = NULL;
 spec_init_sperator_c::search_what_t spec_init_sperator_c::search_what;
--- a/absyntax_utils/spec_init_separator.hh	Mon Jul 11 09:47:27 2011 +0100
+++ b/absyntax_utils/spec_init_separator.hh	Fri Jul 29 16:03:28 2011 +0100
@@ -101,4 +101,17 @@
   /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
   /* structure_initialization -> may be NULL ! */
   void *visit(fb_name_decl_c *symbol);
+  
+  /* STRING '[' integer ']' 
+   * STRING ASSIGN single_byte_character_string
+   * STRING '[' integer ']' ASSIGN single_byte_character_string
+   */
+  void *visit(single_byte_string_spec_c *symbol);
+
+  /* WSTRING '[' integer ']' 
+   * WSTRING ASSIGN double_byte_character_string
+   * WSTRING '[' integer ']' ASSIGN double_byte_character_string
+   */
+  void *visit(double_byte_string_spec_c *symbol);
+    
 };   /* class spec_init_sperator_c */
--- a/lib/iec_std_lib.h	Mon Jul 11 09:47:27 2011 +0100
+++ b/lib/iec_std_lib.h	Fri Jul 29 16:03:28 2011 +0100
@@ -1,5 +1,6 @@
 /*
- * (c) 2008 Edouard TISSERANT
+ * copyright 2008 Edouard TISSERANT
+ * copyright 2011 Mario de Sousa (msousa@fe.up.pt)
  *
  * Offered to the public under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either version 2
@@ -18,6 +19,13 @@
  * IEC 61131-3 standard function library
  */
 
+/* NOTE: This file is full of (what may seem at first) very strange macros.
+ *       If you want to know what all these strange macros are doing,
+ *       just parse this file through a C preprocessor (e.g. cpp), 
+ *       and analyse the output!
+ *       $gcc -E iec_std_lib.h 
+ */
+
 #include <limits.h>
 #include <float.h>
 #include <math.h>
@@ -51,7 +59,7 @@
     u_int16_t body[STR_MAX_LEN];
 } WSTRING;
 */
-
+/*
 # if __WORDSIZE == 64
 #define __32b_sufix
 #define __64b_sufix L
@@ -59,6 +67,19 @@
 #define __32b_sufix L
 #define __64b_sufix LL
 #endif
+*/
+
+# if __WORDSIZE == 64
+#define __32b_sufix
+#define __64b_sufix L
+#else
+#define __32b_sufix L
+/* changed this from LL to L temporarily. It was causing a bug when compiling resulting code with gcc.
+ * I have other things to worry about at the moment.. 
+ */
+#define __64b_sufix L   
+#endif
+
 
 #define __lit(type,value,sfx) (type)value##sfx
 // Keep this macro expention step to let sfx change into L or LL
@@ -83,7 +104,7 @@
 #define __BYTE_LITERAL(value) __literal(BYTE,value,)
 #define __WORD_LITERAL(value) __literal(WORD,value,)
 #define __DWORD_LITERAL(value) __literal(DWORD,value,__32b_sufix)
-#define __LWORD_LITERAL(value) __literal(LWORD,value,__32b_sufix)
+#define __LWORD_LITERAL(value) __literal(LWORD,value,__64b_sufix)
 
 
 
@@ -136,17 +157,33 @@
     DATE    DATEvar;
 } __IL_DEFVAR_T;
 
-/*****************/
-/* Misc internal */
-/*****************/
+
+/**********************************************************************/
+/**********************************************************************/
+/*****                                                            *****/
+/*****      Some helper functions...                              *****/
+/*****                     ...used later:                         *****/
+/*****    - when declaring the IEC 61131-3 standard functions     *****/
+/*****    - in the C source code itself in SFC and ST expressions *****/
+/*****                                                            *****/
+/**********************************************************************/
+/**********************************************************************/
+
+
+/****************************/
+/* Notify IEC runtime error */
+/****************************/
 
 /* function that generates an IEC runtime error */
-static inline void IEC_error(void) {
+static inline void __iec_error(void) {
   /* TODO... */
   fprintf(stderr, "IEC 61131-3 runtime error.\n");
   /*exit(1);*/
 }
 
+/*******************************/
+/* Time normalization function */
+/*******************************/
 
 static inline void __normalize_timespec (IEC_TIMESPEC *ts) {
   if( ts->tv_nsec < -1000000000 || (( ts->tv_sec > 0 ) && ( ts->tv_nsec < 0 ))){
@@ -159,6 +196,10 @@
   }
 }
 
+/**********************************************/
+/* Time conversion to/from timespec functions */
+/**********************************************/
+
 static inline IEC_TIMESPEC __time_to_timespec(int sign, double mseconds, double seconds, double minutes, double hours, double days) {
   IEC_TIMESPEC ts;
 
@@ -197,7 +238,7 @@
   epoch_seconds = mktime(&broken_down_time); /* determine number of seconds since the epoch, i.e. Jan 1st 1970 */
 
   if ((time_t)(-1) == epoch_seconds)
-    IEC_error();
+    __iec_error();
 
   ts.tv_sec = epoch_seconds;
   ts.tv_nsec = 0;
@@ -223,56 +264,35 @@
 
   epoch_seconds = mktime(&broken_down_time); /* determine number of seconds since the epoch, i.e. Jan 1st 1970 */
   if ((time_t)(-1) == epoch_seconds)
-    IEC_error();
+    __iec_error();
 
   ts.tv_sec += epoch_seconds;
   if (ts.tv_sec < epoch_seconds)
     /* since the TOD is always positive, if the above happens then we had an overflow */
-    IEC_error();
+    __iec_error();
 
   return ts;
 }
 
-/********************/
-/*   EN/ENO PARAMS  */
-/********************/
-
-#define EN_ENO_PARAMS BOOL EN, BOOL *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);
-
-/***************/
-/*   Time ops  */
-/***************/
-#define __TIME_CMP(t1, t2) (t2.tv_sec == t1.tv_sec ? t1.tv_nsec - t2.tv_nsec : t1.tv_sec - t2.tv_sec)
-
-static inline TIME __TIME_ADD(TIME IN1, TIME IN2){
+/*******************/
+/* Time operations */
+/*******************/
+
+#define __time_cmp(t1, t2) (t2.tv_sec == t1.tv_sec ? t1.tv_nsec - t2.tv_nsec : t1.tv_sec - t2.tv_sec)
+
+static inline TIME __time_add(TIME IN1, TIME IN2){
   TIME res ={IN1.tv_sec + IN2.tv_sec,
              IN1.tv_nsec + IN2.tv_nsec };
   __normalize_timespec(&res);
   return res;
 }
-static inline TIME __TIME_SUB(TIME IN1, TIME IN2){
+static inline TIME __time_sub(TIME IN1, TIME IN2){
   TIME res ={IN1.tv_sec - IN2.tv_sec,
              IN1.tv_nsec - IN2.tv_nsec };
   __normalize_timespec(&res);
   return res;
 }
-static inline TIME __TIME_MUL(TIME IN1, LREAL IN2){
+static inline TIME __time_mul(TIME IN1, LREAL IN2){
   LREAL s_f = IN1.tv_sec * IN2;
   time_t s = s_f;
   div_t ns = div((LREAL)IN1.tv_nsec * IN2, 1000000000);
@@ -281,7 +301,7 @@
   __normalize_timespec(&res);
   return res;
 }
-static inline TIME __TIME_DIV(TIME IN1, LREAL IN2){
+static inline TIME __time_div(TIME IN1, LREAL IN2){
   LREAL s_f = IN1.tv_sec / IN2;
   time_t s = s_f;
   TIME res = {s,
@@ -290,183 +310,6 @@
   return res;
 }
 
-static inline TIME __date_and_time_to_time_of_day(EN_ENO_PARAMS, TIME IN){
-  TEST_EN(TIME)
-  return (TIME){IN.tv_sec % 86400, IN.tv_nsec};
-}
-static inline TIME __date_and_time_to_date(EN_ENO_PARAMS, TIME IN){
-  TEST_EN(TIME)
-  return (TIME){IN.tv_sec - (IN.tv_sec % (24*60*60)), 0};
-}
-static inline TIME __time_add(EN_ENO_PARAMS, TIME IN1, TIME IN2){
-  TEST_EN(TIME)
-  return __TIME_ADD(IN1, IN2);
-}
-static inline TIME __time_sub(EN_ENO_PARAMS, TIME IN1, TIME IN2){
-  TEST_EN(TIME)
-  return __TIME_SUB(IN1, IN2);
-}
-static inline TIME __time_mul(EN_ENO_PARAMS, TIME IN1, LREAL IN2){
-  TEST_EN(TIME)
-  return __TIME_MUL(IN1, IN2);
-}
-static inline TIME __time_div(EN_ENO_PARAMS, TIME IN1, LREAL IN2){
-  TEST_EN(TIME)
-  return __TIME_DIV(IN1, IN2);
-}
-
-/***************/
-/* String ops  */
-/***************/
-#define __STR_CMP(str1, str2) memcmp((char*)&str1.body,(char*)&str2.body, str1.len < str2.len ? str1.len : str2.len)
-
-static inline __strlen_t __len(EN_ENO_PARAMS, STRING IN){
-    TEST_EN(UINT)
-    return IN.len;
-}
-static inline STRING __left(EN_ENO_PARAMS, STRING IN, __strlen_t L){
-    STRING res;
-    TEST_EN_COND(STRING, L < 0)
-    res = __INIT_STRING;
-    L = L < IN.len ? L : IN.len;
-    memcpy(&res.body, &IN.body, L);
-    res.len = L;
-    return res;
-}
-static inline STRING __right(EN_ENO_PARAMS, STRING IN, __strlen_t L){
-    STRING res;
-    TEST_EN_COND(STRING, L < 0)
-    res = __INIT_STRING;
-    L = L < IN.len ? L : IN.len;
-    memcpy(&res.body, &IN.body[IN.len - L], L);
-    res.len = L;
-    return res;
-}
-static inline STRING __mid(EN_ENO_PARAMS, STRING IN, __strlen_t L, __strlen_t P){
-    STRING res;
-    TEST_EN_COND(STRING, L < 0 || P < 0)
-    res = __INIT_STRING;
-    if(P <= IN.len){
-	    P -= 1; /* now can be used as [index]*/
-	    L = L + P <= IN.len ? L : IN.len - P;
-	    memcpy(&res.body, &IN.body[P] , L);
-        res.len = L;
-    }
-    return res;
-}
-static inline STRING __concat(EN_ENO_PARAMS, UINT param_count, ...){
-  UINT i;
-  STRING res;
-  va_list ap;
-  __strlen_t charcount;
-  TEST_EN(STRING)
-  charcount = 0;
-  res = __INIT_STRING;
-
-  va_start (ap, param_count);         /* Initialize the argument list.  */
-
-  for (i = 0; i < param_count && charcount < STR_MAX_LEN; i++)
-  {
-    STRING tmp = va_arg(ap, STRING);
-    __strlen_t charrem = STR_MAX_LEN - charcount;
-    __strlen_t to_write = tmp.len > charrem ? charrem : tmp.len;
-    memcpy(&res.body[charcount], &tmp.body , to_write);
-    charcount += to_write;
-  }
-
-  res.len = charcount;
-
-  va_end (ap);                  /* Clean up.  */
-  return res;
-}
-static inline STRING __insert(EN_ENO_PARAMS, STRING IN1, STRING IN2, __strlen_t P){
-    STRING res;
-    __strlen_t to_copy;
-    TEST_EN_COND(STRING, P < 0)
-    res = __INIT_STRING;
-
-    to_copy = P > IN1.len ? IN1.len : P;
-    memcpy(&res.body, &IN1.body , to_copy);
-    P = res.len = to_copy;
-
-    to_copy = IN2.len + res.len > STR_MAX_LEN ? STR_MAX_LEN - res.len : IN2.len;
-    memcpy(&res.body[res.len], &IN2.body , to_copy);
-    res.len += to_copy;
-
-    to_copy = IN1.len - P < STR_MAX_LEN - res.len ? IN1.len - P : STR_MAX_LEN - res.len ;
-    memcpy(&res.body[res.len], &IN1.body[P] , to_copy);
-    res.len += to_copy;
-
-    return res;
-}
-static inline STRING __delete(EN_ENO_PARAMS, STRING IN, __strlen_t L, __strlen_t P){
-    STRING res;
-    __strlen_t to_copy;
-    TEST_EN_COND(STRING, L < 0 || P < 0)
-    res = __INIT_STRING;
-
-    to_copy = P > IN.len ? IN.len : P-1;
-    memcpy(&res.body, &IN.body , to_copy);
-    P = res.len = to_copy;
-
-    if( IN.len > P + L ){
-        to_copy = IN.len - P - L;
-        memcpy(&res.body[res.len], &IN.body[P + L], to_copy);
-        res.len += to_copy;
-    }
-
-    return res;
-}
-static inline STRING __replace(EN_ENO_PARAMS, STRING IN1, STRING IN2, __strlen_t L, __strlen_t P){
-    STRING res;
-    __strlen_t to_copy;
-    TEST_EN_COND(STRING, L < 0 || P < 0)
-    res = __INIT_STRING;
-
-    to_copy = P > IN1.len ? IN1.len : P-1;
-    memcpy(&res.body, &IN1.body , to_copy);
-    P = res.len = to_copy;
-
-    to_copy = IN2.len < L ? IN2.len : L;
-
-    if( to_copy + res.len > STR_MAX_LEN )
-       to_copy = STR_MAX_LEN - res.len;
-
-    memcpy(&res.body[res.len], &IN2.body , to_copy);
-    res.len += to_copy;
-
-    P += L;
-    if( res.len <  STR_MAX_LEN && P < IN1.len)
-    {
-        to_copy = IN1.len - P;
-        memcpy(&res.body[res.len], &IN1.body[P] , to_copy);
-        res.len += to_copy;
-    }
-
-    return res;
-}
-
-
-
-static inline __strlen_t __pfind(STRING* IN1, STRING* IN2){
-    UINT count1 = 0; /* offset of first matching char in IN1 */
-    UINT count2 = 0; /* count of matching char */
-    while(count1 + count2 < IN1->len && count2 < IN2->len)
-    {
-        if(IN1->body[count1 + count2] != IN2->body[count2]){
-            count1 += count2 + 1;
-            count2 = 0;
-        }
-        else {
-            count2++;
-        }
-    }
-    return count2 == IN2->len -1 ? 0 : count1 + 1;
-}
-static inline __strlen_t __find(EN_ENO_PARAMS, STRING IN1, STRING IN2){
-    TEST_EN(UINT)
-    return __pfind(&IN1, &IN2);
-}
 
 /***************/
 /* Convertions */
@@ -474,67 +317,49 @@
     /*****************/
     /*  REAL_TO_INT  */
     /*****************/
-static inline LINT __real_round(LREAL IN)
-{
+static inline LINT __real_round(LREAL IN) {
 	return fmod(IN, 1) == 0 ? ((LINT)IN / 2) * 2 : (LINT)IN;
 }
-static inline LINT __preal_to_sint(LREAL IN)
-{
+static inline LINT __preal_to_sint(LREAL IN) {
    return IN >= 0 ? __real_round(IN + 0.5) : __real_round(IN - 0.5);
 }
-static inline LINT __preal_to_uint(LREAL IN)
-{
+static inline LINT __preal_to_uint(LREAL IN) {
    return IN >= 0 ? __real_round(IN + 0.5) : 0;
 }
-static inline LINT __real_to_sint(EN_ENO_PARAMS, LREAL IN){
-    TEST_EN(LINT)
-    return (LINT)__preal_to_sint(IN);
-}
-static inline LWORD __real_to_bit(EN_ENO_PARAMS, LREAL IN){
-    TEST_EN(LWORD)
-    return (LWORD)__preal_to_uint(IN);
-}
-static inline ULINT __real_to_uint(EN_ENO_PARAMS, LREAL IN){
-    TEST_EN(ULINT)
-    return (ULINT)__preal_to_uint(IN);
-}
+static inline LINT __real_to_sint(LREAL IN)  {return (LINT)__preal_to_sint(IN);}
+static inline LWORD __real_to_bit(LREAL IN)  {return (LWORD)__preal_to_uint(IN);}
+static inline ULINT __real_to_uint(LREAL IN) {return (ULINT)__preal_to_uint(IN);}
+
     /***************/
     /*  TO_STRING  */
     /***************/
-static inline STRING __bool_to_string(EN_ENO_PARAMS, BOOL IN)
-{
-    TEST_EN(STRING)
-    if(IN)
-        return (STRING){4, "TRUE"};
+static inline STRING __bool_to_string(BOOL IN) {
+    if(IN) return (STRING){4, "TRUE"};
     return (STRING){5,"FALSE"};
 }
-static inline STRING __bit_to_string(EN_ENO_PARAMS, LWORD IN){
+static inline STRING __bit_to_string(LWORD IN) {
     STRING res;
-    TEST_EN(STRING)
     res = __INIT_STRING;
     res.len = snprintf((char*)res.body, STR_MAX_LEN, "16#%llx", IN);
     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
     return res;
 }
-static inline STRING __real_to_string(EN_ENO_PARAMS, LREAL IN){
+static inline STRING __real_to_string(LREAL IN) {
     STRING res;
-    TEST_EN(STRING)
     res = __INIT_STRING;
     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%.10g", IN);
     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
     return res;
 }
-static inline STRING __sint_to_string(EN_ENO_PARAMS, LINT IN){
+static inline STRING __sint_to_string(LINT IN) {
     STRING res;
-    TEST_EN(STRING)
     res = __INIT_STRING;
     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%lld", IN);
     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
     return res;
 }
-static inline STRING __uint_to_string(EN_ENO_PARAMS, ULINT IN){
+static inline STRING __uint_to_string(ULINT IN) {
     STRING res;
-    TEST_EN(STRING)
     res = __INIT_STRING;
     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%llu", IN);
     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
@@ -543,12 +368,11 @@
     /***************/
     /* FROM_STRING */
     /***************/
-static inline BOOL __string_to_bool(EN_ENO_PARAMS, STRING IN){
-    TEST_EN(BOOL)
+static inline BOOL __string_to_bool(STRING IN) {
     return IN.len == 5 ? !memcmp(&IN.body,"TRUE", IN.len) : 0;
 }
 
-static inline LINT __pstring_to_sint(STRING* IN){
+static inline LINT __pstring_to_sint(STRING* IN) {
     LINT res = 0;
     __strlen_t l;
     unsigned int shift = 0;
@@ -609,22 +433,12 @@
     return res;
 }
 
-static inline LINT __string_to_sint(EN_ENO_PARAMS, STRING IN){
-    TEST_EN(LINT)
-    return (LINT)__pstring_to_sint(&IN);
-}
-static inline LWORD __string_to_bit(EN_ENO_PARAMS, STRING IN){
-    TEST_EN(LWORD)
-    return (LWORD)__pstring_to_sint(&IN);
-}
-static inline ULINT __string_to_uint(EN_ENO_PARAMS, STRING IN){
-    TEST_EN(ULINT)
-    return (ULINT)__pstring_to_sint(&IN);
-}
-static inline LREAL __string_to_real(EN_ENO_PARAMS, STRING IN){
-	__strlen_t l;
-	TEST_EN(LREAL)
-	l = IN.len;
+static inline LINT  __string_to_sint(STRING IN) {return (LINT)__pstring_to_sint(&IN);}
+static inline LWORD __string_to_bit (STRING IN) {return (LWORD)__pstring_to_sint(&IN);}
+static inline ULINT __string_to_uint(STRING IN) {return (ULINT)__pstring_to_sint(&IN);}
+static inline LREAL __string_to_real(STRING IN) {
+    __strlen_t l;
+    l = IN.len;
     /* search the dot */
     while(--l > 0 && IN.body[l] != '.');
     if(l != 0){
@@ -637,18 +451,10 @@
     /***************/
     /*   TO_TIME   */
     /***************/
-static inline TIME __int_to_time(EN_ENO_PARAMS, LINT IN){
-    TEST_EN(TIME)
-    return (TIME){IN, 0};
-}
-
-static inline TIME __real_to_time(EN_ENO_PARAMS, LREAL IN){
-    TEST_EN(TIME)
-    return (TIME){IN, (IN - (LINT)IN) * 1000000000};
-}
-static inline TIME __string_to_time(EN_ENO_PARAMS, STRING IN){
-	__strlen_t l;
-	TEST_EN(TIME)
+static inline TIME    __int_to_time(LINT IN)  {return (TIME){IN, 0};}
+static inline TIME   __real_to_time(LREAL IN) {return (TIME){IN, (IN - (LINT)IN) * 1000000000};}
+static inline TIME __string_to_time(STRING IN){
+    __strlen_t l;
     /* TODO :
      *
      *  Duration literals without underlines: T#14ms    T#-14ms   T#14.7s   T#14.7m
@@ -671,7 +477,7 @@
      */
     /* Quick hack : only transform seconds */
     /* search the dot */
-	l = IN.len;
+    l = IN.len;
     while(--l > 0 && IN.body[l] != '.');
     if(l != 0){
         LREAL IN_val = atof((const char *)&IN.body);
@@ -684,18 +490,13 @@
     /***************/
     /*  FROM_TIME  */
     /***************/
-static inline LREAL __time_to_real(EN_ENO_PARAMS, TIME IN){
-    TEST_EN(LREAL)
+static inline LREAL __time_to_real(TIME IN){
     return (LREAL)IN.tv_sec + ((LREAL)IN.tv_nsec/1000000000);
 }
-static inline LINT __time_to_int(EN_ENO_PARAMS, TIME IN){
-    TEST_EN(LINT)
-    return IN.tv_sec;
-}
-static inline STRING __time_to_string(EN_ENO_PARAMS, TIME IN){
+static inline LINT __time_to_int(TIME IN) {return IN.tv_sec;}
+static inline STRING __time_to_string(TIME IN){
     STRING res;
     div_t days;
-    TEST_EN(STRING)
     /*t#5d14h12m18s3.5ms*/
     res = __INIT_STRING;
     days = div(IN.tv_sec ,86400);
@@ -721,32 +522,30 @@
     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
     return res;
 }
-static inline STRING __date_to_string(EN_ENO_PARAMS, DATE IN){
+static inline STRING __date_to_string(DATE IN){
     STRING res;
     struct tm* broken_down_time;
     time_t seconds;
-	TEST_EN(STRING)
     /* D#1984-06-25 */
     res = __INIT_STRING;
     seconds = IN.tv_sec;
     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
-        IEC_error();
+        __iec_error();
         return (STRING){7,"D#ERROR"};
     }
     res.len = snprintf((char*)&res.body, STR_MAX_LEN, "D#%d-%2.2d-%2.2d", broken_down_time->tm_year + 1900, broken_down_time->tm_mon + 1, broken_down_time->tm_mday);
     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
     return res;
 }
-static inline STRING __tod_to_string(EN_ENO_PARAMS, TOD IN){
+static inline STRING __tod_to_string(TOD IN){
     STRING res;
     struct tm* broken_down_time;
     time_t seconds;
-    TEST_EN(STRING)
     /* TOD#15:36:55.36 */
     res = __INIT_STRING;
     seconds = IN.tv_sec;
     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
-        IEC_error();
+        __iec_error();
         return (STRING){9,"TOD#ERROR"};
     }
     if(IN.tv_nsec == 0){
@@ -757,15 +556,14 @@
     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
     return res;
 }
-static inline STRING __dt_to_string(EN_ENO_PARAMS, DT IN){
+static inline STRING __dt_to_string(DT IN){
     STRING res;
     struct tm* broken_down_time;
     time_t seconds;
-    TEST_EN(STRING)
     /* DT#1984-06-25-15:36:55.36 */
     seconds = IN.tv_sec;
     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
-        IEC_error();
+        __iec_error();
         return (STRING){8,"DT#ERROR"};
     }
     if(IN.tv_nsec == 0){
@@ -788,12 +586,21 @@
     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
     return res;
 }
-    /* BCD */
+
+    /**********************************************/
+    /*  [ANY_DATE | TIME] _TO_ [ANY_DATE | TIME]  */
+    /**********************************************/
+
+static inline TOD __date_and_time_to_time_of_day(DT IN) {return (TOD){IN.tv_sec % 86400, IN.tv_nsec};}
+static inline DATE __date_and_time_to_date(DT IN){return (DATE){IN.tv_sec - (IN.tv_sec % (24*60*60)), 0};}
+
+    /*****************/
+    /*  FROM/TO BCD  */
+    /*****************/
 #define __bcd_digit(fac)
-static inline ULINT __bcd_to_uint(EN_ENO_PARAMS, LWORD IN){
+static inline ULINT __bcd_to_uint(LWORD IN){
     ULINT res;
     ULINT i;
-    TEST_EN(ULINT)
 
     res = IN & 0xf;
     for(i = 10ULL; i <= 1000000000000000ULL; i *= 10){
@@ -804,10 +611,9 @@
     return res;
 }
 
-static inline LWORD __uint_to_bcd(EN_ENO_PARAMS, ULINT IN){
+static inline LWORD __uint_to_bcd(ULINT IN){
     LWORD res;
     USINT i;
-    TEST_EN(LWORD)
 
     res = IN % 10;
     for(i = 4; i<=60; i += 4){
@@ -818,6 +624,296 @@
     return res;
 }
 
+
+    /************/
+    /*  MOVE_*  */
+    /************/
+
+/* some helpful __move_[ANY] functions, used in the *_TO_** and MOVE  standard functions */
+/* e.g. __move_BOOL, __move_BYTE, __move_REAL, __move_TIME, ... */
+#define __iec_(TYPENAME)\
+static inline TYPENAME __move_##TYPENAME(TYPENAME op1) {return op1;}
+__ANY(__iec_)
+#undef __iec_
+
+
+
+/*****************************************************************/
+/*****************************************************************/
+/*****                                                       *****/
+/*****                 IEC 61131-3                           *****/
+/*****      S T A N D A R D     F U N C T I O N S            *****/
+/*****                                                       *****/
+/*****************************************************************/
+/*****************************************************************/
+
+/* NOTE: If you want to know what all these strange macros are doing,
+ *       just parse this file through a C preprocessor, and analyse the output!
+ *       $gcc -E iec_std_lib.h 
+ */
+
+/* NOTE: We only define and declare the explicitly typed standard functions
+ *       (e.g., SIN_REAL, SIN_LREAL, ..., ADD_SINT, ADD_INT, ADD_LINT, ...)
+ *       We do not declare/define the overloaded functions
+ *       (SIN, ADD, ...). 
+ *       When handling a call to an overloaded function, the iec2c compiler 
+ *       will determine in stage3 the data type of the parameter being passed, 
+ *       and in stage4 generate the C code to call the correct
+ *       typed standard function.
+ */
+
+/* NOTE on explicit typing of:
+ *           - Table 25 - Standard bit shift functions
+ *           - Table 29 - Character string Functions
+ *
+ *  In section 2.5.1.4 (Typing, overloading, and type conversion) of the IEC 61131-3 (version 2)
+ *  of the standard, it is stated:
+ * "A standard function, [...] is said to be overloaded when it
+ * can operate on input data elements of various types within a generic type designator as defined in
+ * 2.3.2. For instance, an overloaded addition function on generic type ANY_NUM can operate on data
+ * of types LREAL, REAL, DINT, INT, and SINT."
+ * [...]
+ * "When a function which normally represents an overloaded operator is to be typed, i.e., the types
+ * of its inputs and outputs restricted to a particular elementary or derived data type as defined in
+ * 2.3, this shall be done by appending an "underline" character followed by the required type, as
+ * shown in table 21."
+ *
+ * However, this explanation (as well as the example in table 21) only refers to functions where the same
+ * generic data type is used for the single input and the output parameter.
+ * How can we create explicitly types functions when this is not the case?
+ * It does not seem to be covered by the standard.
+ *
+ * For this reason, we do not define the LEN_SINT, LEN_INT, LEN_STRING, LEN_[ANY_INT], LEN_[ANY_STRING] functions...
+ */
+ 
+
+/********************/
+/*   EN/ENO PARAMS  */
+/********************/
+
+#define EN_ENO_PARAMS BOOL EN, BOOL *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);
+
+  
+  
+/*****************************************/  
+/*****************************************/  
+/*  2.5.1.5.1 Type Conversion Functions  */
+/*****************************************/  
+/*****************************************/  
+
+#define __convert_type(from_TYPENAME,to_TYPENAME, oper) \
+static inline to_TYPENAME from_TYPENAME##_TO_##to_TYPENAME(EN_ENO_PARAMS, from_TYPENAME op){\
+  TEST_EN(to_TYPENAME)\
+  return (to_TYPENAME)oper(op);\
+}
+
+
+#define __to_anynum_(from_TYPENAME)   __ANY_NUM_1(__iec_,from_TYPENAME)
+#define __to_anyint_(from_TYPENAME)   __ANY_INT_1(__iec_,from_TYPENAME)
+#define __to_anybit_(from_TYPENAME)   __ANY_BIT_1(__iec_,from_TYPENAME)
+#define __to_anynbit_(from_TYPENAME) __ANY_NBIT_1(__iec_,from_TYPENAME)
+#define __to_anysint_(from_TYPENAME) __ANY_SINT_1(__iec_,from_TYPENAME)
+#define __to_anyuint_(from_TYPENAME) __ANY_UINT_1(__iec_,from_TYPENAME)
+#define __to_anyreal_(from_TYPENAME) __ANY_REAL_1(__iec_,from_TYPENAME)
+#define __to_anydate_(from_TYPENAME) __ANY_DATE_1(__iec_,from_TYPENAME)
+
+/******** [ANY_BIT]_TO_[ANY_NUM | ANT_BIT]   ************/ 
+#define __iec_(to_TYPENAME,from_TYPENAME) __convert_type(from_TYPENAME, to_TYPENAME, __move_##to_TYPENAME)
+__ANY_BIT(__to_anynum_)
+__ANY_BIT(__to_anybit_)
+#undef __iec_
+
+/******** [ANY_INT]_TO_[ANY_NUM | ANT_BIT]   ************/ 
+#define __iec_(to_TYPENAME,from_TYPENAME) __convert_type(from_TYPENAME, to_TYPENAME, __move_##to_TYPENAME)
+__ANY_INT(__to_anynum_)
+__ANY_INT(__to_anybit_)
+#undef __iec_
+
+/******** [ANY_REAL]_TO_[ANY_BIT]   ************/ 
+#define __iec_(to_TYPENAME,from_TYPENAME) __convert_type(from_TYPENAME, to_TYPENAME, __real_to_bit)
+__ANY_REAL(__to_anybit_)
+#undef __iec_
+
+/******** [ANY_REAL]_TO_[ANY_INT]   ************/ 
+#define __iec_(to_TYPENAME,from_TYPENAME) __convert_type(from_TYPENAME, to_TYPENAME, __real_to_sint)
+__ANY_REAL(__to_anysint_)
+#undef __iec_
+#define __iec_(to_TYPENAME,from_TYPENAME) __convert_type(from_TYPENAME, to_TYPENAME, __real_to_uint)
+__ANY_REAL(__to_anyuint_)
+#undef __iec_
+
+/******** [ANY_REAL]_TO_[ANY_REAL]   ************/ 
+#define __iec_(to_TYPENAME,from_TYPENAME) __convert_type(from_TYPENAME, to_TYPENAME, __move_##to_TYPENAME)
+__ANY_REAL(__to_anyreal_)
+#undef __iec_
+
+/******** [ANY_BIT | ANY_INT]_TO_[TIME | ANY_DATE]   ************/ 
+#define __iec_(from_TYPENAME) __convert_type(from_TYPENAME, TIME, __int_to_time)
+__ANY_BIT(__iec_)
+__ANY_INT(__iec_)
+#undef __iec_
+#define __iec_(to_TYPENAME,from_TYPENAME) __convert_type(from_TYPENAME, to_TYPENAME, __int_to_time)
+__ANY_BIT(__to_anydate_)
+__ANY_INT(__to_anydate_)
+#undef __iec_
+
+/******** [ANY_REAL]_TO_[TIME | ANY_DATE]   ************/ 
+#define __iec_(from_TYPENAME) __convert_type(from_TYPENAME, TIME, __real_to_time)
+__ANY_REAL(__iec_)
+#undef __iec_
+#define __iec_(to_TYPENAME,from_TYPENAME) __convert_type(from_TYPENAME, to_TYPENAME, __real_to_time)
+__ANY_REAL(__to_anydate_)
+#undef __iec_
+
+/******** [TIME | ANY_DATE]_TO_[ANY_BIT | ANY_INT]   ************/ 
+#define __iec_(to_TYPENAME,from_TYPENAME) __convert_type(from_TYPENAME, to_TYPENAME, __time_to_int)
+__to_anyint_(TIME)
+__to_anybit_(TIME)
+__ANY_DATE(__to_anyint_)
+__ANY_DATE(__to_anybit_)
+#undef __iec_
+
+/******** [TIME | ANY_DATE]_TO_[ANY_REAL]   ************/ 
+#define __iec_(to_TYPENAME,from_TYPENAME) __convert_type(from_TYPENAME, to_TYPENAME, __time_to_real)
+__to_anyreal_(TIME)
+__ANY_DATE(__to_anyreal_)
+#undef __iec_
+
+
+/******** [ANY_DATE]_TO_[ANY_DATE | TIME]   ************/ 
+/* Not supported: DT_TO_TIME */
+__convert_type(DT, DATE,  __date_and_time_to_date)
+__convert_type(DT, DT,    __move_DT)
+__convert_type(DT, TOD,   __date_and_time_to_time_of_day)
+/* Not supported: DATE_TO_TIME */
+__convert_type(DATE, DATE, __move_DATE)
+/* Not supported: DATE_TO_DT */
+/* Not supported: DATE_TO_TOD */
+/* Not supported: TOD_TO_TIME */
+/* Not supported: TOD_TO_DATE */
+/* Not supported: TOD_TO_DT */
+__convert_type(TOD, TOD, __move_TOD)
+
+
+/******** TIME_TO_[ANY_DATE]   ************/ 
+/* Not supported: TIME_TO_DATE */
+/* Not supported: TIME_TO_DT */
+/* Not supported: TIME_TO_TOD */
+
+/******** TIME_TO_TIME   ************/ 
+__convert_type(TIME, TIME, __move_TIME)
+
+
+/******** [ANY_BIT]_TO_STRING   ************/ 
+__convert_type(BOOL, STRING, __bool_to_string)
+#define __iec_(from_TYPENAME) __convert_type(from_TYPENAME, STRING, __bit_to_string)
+__ANY_NBIT(__iec_)
+#undef __iec_
+
+/******** [ANY_INT]_TO_STRING   ************/ 
+#define __iec_(from_TYPENAME) __convert_type(from_TYPENAME, STRING, __sint_to_string)
+__ANY_SINT(__iec_)
+#undef __iec_
+#define __iec_(from_TYPENAME) __convert_type(from_TYPENAME, STRING, __uint_to_string)
+__ANY_UINT(__iec_)
+#undef __iec_
+
+/******** [ANY_REAL]_TO_STRING   ************/ 
+#define __iec_(from_TYPENAME) __convert_type(from_TYPENAME, STRING, __real_to_string)
+__ANY_REAL(__iec_)
+#undef __iec_
+
+/******** [ANY_DATE]_TO_STRING   ************/ 
+__convert_type(DATE, STRING, __date_to_string)
+__convert_type(DT,   STRING, __dt_to_string)
+__convert_type(TOD,  STRING, __tod_to_string)
+
+/******** TIME_TO_STRING   ************/ 
+__convert_type(TIME, STRING, __time_to_string)
+
+
+/******** STRING_TO_[ANY_BIT]   ************/ 
+__convert_type(STRING, BOOL, __string_to_bool)
+#define __iec_(to_TYPENAME) __convert_type(STRING, to_TYPENAME, __string_to_bit)
+__ANY_NBIT(__iec_)
+#undef __iec_
+
+/******** STRING_TO_[ANY_INT]   ************/ 
+#define __iec_(to_TYPENAME) __convert_type(STRING, to_TYPENAME, __string_to_sint)
+__ANY_SINT(__iec_)
+#undef __iec_
+#define __iec_(to_TYPENAME) __convert_type(STRING, to_TYPENAME, __string_to_uint)
+__ANY_UINT(__iec_)
+#undef __iec_
+
+/******** STRING_TO_[ANY_REAL]   ************/ 
+#define __iec_(to_TYPENAME) __convert_type(STRING, to_TYPENAME, __string_to_real)
+__ANY_REAL(__iec_)
+#undef __iec_
+
+/******** STRING_TO_[ANY_DATE]   ************/ 
+#define __iec_(to_TYPENAME) __convert_type(STRING, to_TYPENAME, __string_to_time)
+__ANY_DATE(__iec_)
+#undef __iec_
+                                   
+/******** STRING_TO_TIME   ************/ 
+__convert_type(STRING, TIME, __string_to_time)
+
+
+/********   TRUNC   ************/ 
+#define __iec_(to_TYPENAME,from_TYPENAME) \
+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);\
+}
+__ANY_REAL(__to_anyint_)
+#undef __iec_
+
+
+/********   _TO_BCD   ************/ 
+#define __iec_(to_TYPENAME,from_TYPENAME) \
+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);\
+}
+__ANY_UINT(__to_anynbit_)
+#undef __iec_
+
+
+/********   BCD_TO_   ************/ 
+#define __iec_(to_TYPENAME,from_TYPENAME) \
+static inline to_TYPENAME from_TYPENAME##_BCD_TO_##to_TYPENAME(EN_ENO_PARAMS, from_TYPENAME op){\
+  TEST_EN(to_TYPENAME)\
+  return (to_TYPENAME)__bcd_to_uint(op);\
+}
+__ANY_NBIT(__to_anyuint_)
+#undef __iec_
+
+
+/***********************************/  
+/***********************************/  
+/*  2.5.1.5.2 Numerical Functions  */
+/***********************************/  
+/***********************************/  
+
 /* workaround for va-args limitation on shorter than int params */
 #define VA_ARGS_REAL LREAL
 #define VA_ARGS_LREAL LREAL
@@ -841,11 +937,187 @@
 #define VA_ARGS_TOD TOD
 #define VA_ARGS_DT DT
 
-/*******************************************/
-/*     Arithmetic and bitwise functions    */
-/*******************************************/
+
+#define __numeric(fname,TYPENAME, FUNC) \
+static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, TYPENAME op){\
+  TEST_EN(TYPENAME)\
+  return FUNC(op);\
+}
+
+/******************************************************************/
+/***   Table 23 - Standard functions of one numeric variable    ***/
+/******************************************************************/
+
+  /**************/
+  /*    ABS     */
+  /**************/
+/* explicitly typed function */
+#define __iec_(TYPENAME) \
+static inline TYPENAME ABS_##TYPENAME(EN_ENO_PARAMS, TYPENAME op){\
+  TEST_EN(TYPENAME)\
+  if (op < 0)\
+    return -op;\
+  return op;\
+}
+__ANY_REAL(__iec_)
+__ANY_SINT(__iec_)
+#undef __iec_
+
+#define __iec_(TYPENAME) \
+static inline TYPENAME ABS_##TYPENAME(EN_ENO_PARAMS, TYPENAME op){\
+  TEST_EN(TYPENAME)\
+  return op;\
+}
+__ANY_UINT(__iec_)
+#undef __iec_
+
+/* overloaded function */
+#define __iec_(TYPENAME) \
+static inline TYPENAME ABS__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op){\
+  TEST_EN(TYPENAME)\
+  if (op < 0)\
+    return -op;\
+  return op;\
+}
+__ANY_REAL(__iec_)
+__ANY_SINT(__iec_)
+#undef __iec_
+
+#define __iec_(TYPENAME) \
+static inline TYPENAME ABS__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op){\
+  TEST_EN(TYPENAME)\
+  return op;\
+}
+__ANY_UINT(__iec_)
+#undef __iec_
+
+
+  /**************/
+  /*    SQRT    */
+  /**************/
+/* explicitly typed function */
+#define __iec_(TYPENAME) \
+__numeric(SQRT_, TYPENAME, sqrt)                             /* explicitly typed function */\
+__numeric(SQRT__##TYPENAME##__, TYPENAME, sqrt)              /* overloaded function */
+__ANY_REAL(__iec_)
+#undef __iec_
+
+  /**************/
+  /*     LN     */
+  /**************/
+#define __iec_(TYPENAME) \
+__numeric(LN_, TYPENAME, log)                             /* explicitly typed function */\
+__numeric(LN__##TYPENAME##__, TYPENAME, log)              /* overloaded function */
+__ANY_REAL(__iec_)
+#undef __iec_
+
+
+  /**************/
+  /*     LOG    */
+  /**************/
+#define __iec_(TYPENAME) \
+__numeric(LOG_, TYPENAME, log10)                             /* explicitly typed function */\
+__numeric(LOG__##TYPENAME##__, TYPENAME, log10)              /* overloaded function */
+__ANY_REAL(__iec_)
+#undef __iec_
+
+  /**************/
+  /*     EXP    */
+  /**************/
+#define __iec_(TYPENAME) \
+__numeric(EXP_, TYPENAME, exp)                             /* explicitly typed function */\
+__numeric(EXP__##TYPENAME##__, TYPENAME, exp)              /* overloaded function */
+__ANY_REAL(__iec_)
+#undef __iec_
+
+
+  /**************/
+  /*     SIN    */
+  /**************/
+#define __iec_(TYPENAME) \
+__numeric(SIN_, TYPENAME, sin)                              /* explicitly typed function */\
+__numeric(SIN__##TYPENAME##__, TYPENAME, sin)               /* overloaded function */
+__ANY_REAL(__iec_)
+#undef __iec_
+
+
+  /**************/
+  /*     COS    */
+  /**************/
+#define __iec_(TYPENAME) \
+__numeric(COS_, TYPENAME, cos)                             /* explicitly typed function */\
+__numeric(COS__##TYPENAME##__, TYPENAME, cos)              /* overloaded function */
+__ANY_REAL(__iec_)
+#undef __iec_
+
+  /**************/
+  /*     TAN    */
+  /**************/
+#define __iec_(TYPENAME) \
+__numeric(TAN_, TYPENAME, tan)                             /* explicitly typed function */\
+__numeric(TAN__##TYPENAME##__, TYPENAME, tan)              /* overloaded function */
+__ANY_REAL(__iec_)
+#undef __iec_
+
+
+  /**************/
+  /*    ASIN    */
+  /**************/
+#define __iec_(TYPENAME) \
+__numeric(ASIN_, TYPENAME, asin)                             /* explicitly typed function */\
+__numeric(ASIN__##TYPENAME##__, TYPENAME, asin)              /* overloaded function */
+__ANY_REAL(__iec_)
+#undef __iec_
+
+  /**************/
+  /*    ACOS    */
+  /**************/
+#define __iec_(TYPENAME) \
+__numeric(ACOS_, TYPENAME, acos)                             /* explicitly typed function */\
+__numeric(ACOS__##TYPENAME##__, TYPENAME, acos)              /* overloaded function */
+__ANY_REAL(__iec_)
+#undef __iec_
+
+  /**************/
+  /*    ATAN    */
+  /**************/
+#define __iec_(TYPENAME) \
+__numeric(ATAN_, TYPENAME, atan)                             /* explicitly typed function */\
+__numeric(ATAN__##TYPENAME##__, TYPENAME, atan)              /* overloaded function */
+__ANY_REAL(__iec_)
+#undef __iec_
+
+
+
+/*****************************************************/
+/***   Table 24 - Standard arithmetic functions    ***/
+/*****************************************************/
+/*
+   Unfortunately, the following does not work!!
+   
+#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int))
+
 #define __arith_expand(fname,TYPENAME, OP) \
-static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
+#define fname(EN, ENO, ...) fname__(EN, ENO, NUMARGS(__VA_ARGS__), __VA_ARGS__)\
+static inline TYPENAME fname__(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
+  va_list ap;\
+  UINT i;\
+  TEST_EN(TYPENAME)\
+  \
+  va_start (ap, op1);         \
+  \
+  for (i = 0; i < param_count - 1; i++){\
+    op1 = op1 OP va_arg (ap, VA_ARGS_##TYPENAME);\
+  }\
+  \
+  va_end (ap);                  \
+  return op1;\
+}
+*/
+
+
+#define __arith_expand(fname,TYPENAME, OP) \
+static inline TYPENAME fname(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
   va_list ap;\
   UINT i;\
   TEST_EN(TYPENAME)\
@@ -861,291 +1133,353 @@
 }
 
 #define __arith_static(fname,TYPENAME, OP) \
-static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\
+static inline TYPENAME fname(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\
   TEST_EN(TYPENAME)\
   return op1 OP op2;\
 }
 
-/**************/
-/*     ADD    */
-/**************/
-#define __add_(TYPENAME) __arith_expand(__add_, TYPENAME, + )
-ANY_NUM(__add_)
-
-/**************/
-/*     MUL    */
-/**************/
-#define __mul_(TYPENAME) __arith_expand(__mul_, TYPENAME, * )
-ANY_NUM(__mul_)
-
-/**************/
-/*     SUB    */
-/**************/
-#define __sub_(TYPENAME) __arith_static(__sub_, TYPENAME, - )
-ANY_NUM(__sub_)
-
-/**************/
-/*     DIV    */
-/**************/
-#define __div_(TYPENAME)\
-static inline TYPENAME __div_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\
+  /**************/
+  /*     ADD    */
+  /**************/
+#define __iec_(TYPENAME) \
+__arith_expand(ADD_##TYPENAME, TYPENAME, +) 			 /* explicitly typed function */\
+__arith_expand(ADD__##TYPENAME##__##TYPENAME, TYPENAME, +)	 /* overloaded function */
+__ANY_NUM(__iec_)
+#undef __iec_
+
+  /**************/
+  /*     MUL    */
+  /**************/
+#define __iec_(TYPENAME) \
+__arith_expand(MUL_##TYPENAME, TYPENAME, *) 			 /* explicitly typed function */\
+__arith_expand(MUL__##TYPENAME##__##TYPENAME, TYPENAME, *)	 /* overloaded function */
+__ANY_NUM(__iec_)
+#undef __iec_
+
+  /**************/
+  /*     SUB    */
+  /**************/
+#define __iec_(TYPENAME) \
+__arith_expand(SUB_##TYPENAME, TYPENAME, -) 			 /* explicitly typed function */\
+__arith_expand(SUB__##TYPENAME##__##TYPENAME##__##TYPENAME, TYPENAME, -)	 /* overloaded function */
+__ANY_NUM(__iec_)
+#undef __iec_
+
+  /**************/
+  /*     DIV    */
+  /**************/
+/* The explicitly typed standard functions */
+#define __iec_(TYPENAME)\
+static inline TYPENAME DIV_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\
   TEST_EN_COND(TYPENAME, op2 == 0)\
   return op1 / op2;\
 }
-ANY_NUM(__div_)
-
-/**************/
-/*     MOD    */
-/**************/
-#define __mod_(TYPENAME) __arith_static(__mod_, TYPENAME, % )
-ANY_INT(__mod_)
-
-/**************/
-/*     AND    */
-/**************/
-__arith_expand(__and_, BOOL, && )
-#define __and_(TYPENAME) __arith_expand(__and_, TYPENAME, & )
-ANY_NBIT(__and_)
-
-/*************/
-/*     OR    */
-/*************/
-__arith_expand(__or_, BOOL, || )
-#define __or_(TYPENAME) __arith_expand(__or_, TYPENAME, |)
-ANY_NBIT(__or_)
-
-/**************/
-/*     XOR    */
-/**************/
-static inline BOOL __xor_BOOL(EN_ENO_PARAMS, UINT param_count, BOOL op1, ...){
-  va_list ap;
-  UINT i;
-  TEST_EN(BOOL)
-
-  va_start (ap, op1);         /* Initialize the argument list.  */
-
-  for (i = 0; i < param_count - 1; i++){
-    BOOL tmp = va_arg (ap, VA_ARGS_BOOL);
-    op1 = (op1 && !tmp) || (!op1 && tmp);
-  }
-
-  va_end (ap);                  /* Clean up.  */
-  return op1;
-}
-#define __xor_(TYPENAME) __arith_expand(__xor_, TYPENAME, ^)
-ANY_NBIT(__xor_)
-
-/**************/
-/*     NOT    */
-/**************/
-static inline BOOL __not_BOOL(EN_ENO_PARAMS, BOOL op1){
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/* The overloaded standard functions */
+#define __iec_(TYPENAME)\
+static inline TYPENAME DIV__##TYPENAME##__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\
+  TEST_EN_COND(TYPENAME, op2 == 0)\
+  return op1 / op2;\
+}
+__ANY_NUM(__iec_)
+#undef __iec_
+
+  /**************/
+  /*     MOD    */
+  /**************/
+/* The explicitly typed standard functions */
+#define __iec_(TYPENAME)\
+__arith_expand(MOD_##TYPENAME, TYPENAME, %) 			 /* explicitly typed function */\
+__arith_expand(MOD__##TYPENAME##__##TYPENAME##__##TYPENAME, TYPENAME, %)	 /* overloaded function */
+__ANY_INT(__iec_)
+#undef __iec_
+
+  /**************/
+  /*    EXPT    */
+  /**************/
+/* 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){\
+  TEST_EN(in1_TYPENAME)\
+  return pow(IN1, IN2);\
+}
+#define __in1_anyreal_(in2_TYPENAME)   __ANY_REAL_1(__iec_,in2_TYPENAME)
+__ANY_NUM(__in1_anyreal_)
+#undef __iec_
+
+  
+
+  /***************/
+  /*     MOVE    */
+  /***************/
+/* The explicitly typed standard functions */
+#define __iec_(TYPENAME)\
+static inline TYPENAME MOVE_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1){\
+  TEST_EN(TYPENAME)\
+  return op1;\
+}
+__ANY(__iec_)
+#undef __iec_
+
+/* Overloaded function */
+#define __iec_(TYPENAME)\
+static inline TYPENAME MOVE__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op1){\
+  TEST_EN(TYPENAME)\
+  return op1;\
+}
+__ANY(__iec_)
+#undef __iec_
+
+
+
+
+
+
+/***********************************/  
+/***********************************/  
+/*  2.5.1.5.3 Bit String Functions */
+/***********************************/  
+/***********************************/  
+
+/****************************************************/
+/***   Table 25 - Standard bit shift functions    ***/
+/****************************************************/
+
+/* We do not delcare explcitly typed versions of the functions in table 25.
+ * See note above regarding explicitly typed functions for more details.
+ */
+#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) {\
+  TEST_EN(in1_TYPENAME)\
+  return IN OP N;\
+}
+
+  /**************/
+  /*     SHL    */
+  /**************/
+#define __iec_(TYPENAME) \
+/* Overloaded function */\
+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 */\
+}
+__ANY_INT(__iec_)
+#undef __iec_
+
+
+#define __iec_(in1_TYPENAME,in2_TYPENAME) \
+__shift_(SHL__##in1_TYPENAME##__##in1_TYPENAME##__##in2_TYPENAME, in1_TYPENAME, in2_TYPENAME, << )/* Overloaded function */
+__ANY_INT(__in1_anynbit_)
+#undef __iec_
+
+
+  /**************/
+  /*     SHR    */
+  /**************/
+#define __iec_(TYPENAME) \
+/* Overloaded function */\
+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 */\
+}
+__ANY_INT(__iec_)
+#undef __iec_
+
+
+#define __iec_(in1_TYPENAME,in2_TYPENAME) \
+__shift_(SHR__##in1_TYPENAME##__##in1_TYPENAME##__##in2_TYPENAME, in1_TYPENAME, in2_TYPENAME, >> )/* Overloaded function */
+__ANY_INT(__in1_anynbit_)
+#undef __iec_
+
+
+  /**************/
+  /*     ROR    */
+  /**************/
+#define __iec_(TYPENAME) \
+/* Overloaded function */\
+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! */\
+}
+__ANY_INT(__iec_)
+#undef __iec_
+
+
+#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){\
+  TEST_EN(in1_TYPENAME)\
+  N %= 8*sizeof(in1_TYPENAME);\
+  return (IN >> N) | (IN << (8*sizeof(in1_TYPENAME)-N));\
+}
+__ANY_INT(__in1_anynbit_)
+#undef __iec_
+
+
+  /**************/
+  /*     ROL    */
+  /**************/
+#define __iec_(TYPENAME) \
+/* Overloaded function */\
+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! */\
+}
+__ANY_INT(__iec_)
+#undef __iec_
+
+
+#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){\
+  TEST_EN(in1_TYPENAME)\
+  N %= 8*sizeof(in1_TYPENAME);\
+  return (IN << N) | (IN >> (8*sizeof(in1_TYPENAME)-N));\
+}
+__ANY_INT(__in1_anynbit_)
+#undef __iec_
+
+
+
+/*********************/
+/***   Table 26    ***/
+/*********************/
+
+  /**************/
+  /*     AND    */
+  /**************/
+__arith_expand(AND_BOOL, BOOL, && )         /* The explicitly typed standard functions */
+__arith_expand(AND__BOOL__BOOL, BOOL, && )  /* Overloaded function */
+
+#define __iec_(TYPENAME) \
+__arith_expand(AND_##TYPENAME, TYPENAME, &)  /* The explicitly typed standard functions */\
+__arith_expand(AND__##TYPENAME##__##TYPENAME, TYPENAME, &)  /* Overloaded function */
+__ANY_NBIT(__iec_)
+#undef __iec_
+
+  /*************/
+  /*     OR    */
+  /*************/
+__arith_expand(OR_BOOL, BOOL, || )         /* The explicitly typed standard functions */
+__arith_expand(OR__BOOL__BOOL, BOOL, || )  /* Overloaded function */
+
+#define __iec_(TYPENAME) \
+__arith_expand(OR_##TYPENAME, TYPENAME, |)  /* The explicitly typed standard functions */\
+__arith_expand(OR__##TYPENAME##__##TYPENAME, TYPENAME, |)  /* Overloaded function */
+__ANY_NBIT(__iec_)
+#undef __iec_
+
+  /**************/
+  /*     XOR    */
+  /**************/
+#define __xorbool_expand(fname) \
+static inline BOOL fname(EN_ENO_PARAMS, UINT param_count, BOOL op1, ...){ \
+  va_list ap; \
+  UINT i; \
+  TEST_EN(BOOL) \
+\
+  va_start (ap, op1);         /* Initialize the argument list.  */ \
+\
+  for (i = 0; i < param_count - 1; i++){ \
+    BOOL tmp = va_arg (ap, VA_ARGS_BOOL); \
+    op1 = (op1 && !tmp) || (!op1 && tmp); \
+  } \
+\
+  va_end (ap);                  /* Clean up.  */ \
+  return op1; \
+}
+
+__xorbool_expand(XOR_BOOL) /* The explicitly typed standard functions */
+__xorbool_expand(XOR__BOOL__BOOL) /* Overloaded function */
+
+#define __iec_(TYPENAME) \
+__arith_expand(XOR_##TYPENAME, TYPENAME, ^) /* The explicitly typed standard functions */\
+__arith_expand(XOR__##TYPENAME##__##TYPENAME, TYPENAME, ^) /* Overloaded function */\
+__ANY_NBIT(__iec_)
+#undef __iec_
+
+
+  /**************/
+  /*     NOT    */
+  /**************/
+/* The explicitly typed standard functions */
+static inline BOOL NOT_BOOL(EN_ENO_PARAMS, BOOL op1){
   TEST_EN(BOOL)
   return !op1;
 }
 
-#define __not_(TYPENAME)\
-static inline TYPENAME __not_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1){\
+/* Overloaded function */
+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){\
   TEST_EN(TYPENAME)\
   return ~op1;\
 }
-ANY_NBIT(__not_)
-
-/***************/
-/*     MOVE    */
-/***************/
-#define __move_(TYPENAME)\
-static inline TYPENAME __move_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1){\
+__ANY_NBIT(__iec_)
+#undef __iec_
+
+/* Overloaded function */
+#define __iec_(TYPENAME)\
+static inline TYPENAME NOT__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, TYPENAME op1){\
   TEST_EN(TYPENAME)\
-  return op1;\
-}
-ANY(__move_)
-
-/**************/
-/* Binary ops */
-/**************/
-#define __shift_(fname, TYPENAME, OP)\
-static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, TYPENAME IN, USINT N) {\
-  TEST_EN(TYPENAME)\
-  return IN OP N;\
-}
-
-#define __shl_(TYPENAME) __shift_(__shl_, TYPENAME, << )
-/* Call previously defined macro for each ANY_NBIT */
-ANY_NBIT(__shl_)
-
-#define __shr_(TYPENAME) __shift_(__shr_, TYPENAME, >> )
-/* Call previously defined macro for each ANY_NBIT */
-ANY_NBIT(__shr_)
-
-#define __ror_(TYPENAME)\
-static inline TYPENAME __ror_##TYPENAME(EN_ENO_PARAMS, TYPENAME IN, USINT N){\
-  TEST_EN(TYPENAME)\
-  N %= 8*sizeof(TYPENAME);\
-  return (IN >> N) | (IN << (8*sizeof(TYPENAME)-N));\
-}
-/* Call previously defined macro for each ANY_NBIT */
-ANY_NBIT(__ror_)
-
-#define __rol_(TYPENAME)\
-static inline TYPENAME __rol_##TYPENAME(EN_ENO_PARAMS, TYPENAME IN, USINT N){\
-  TEST_EN(TYPENAME)\
-  N %= 8*sizeof(TYPENAME);\
-  return (IN << N) | (IN >> (8*sizeof(TYPENAME)-N));\
-}
-/* Call previously defined macro for each ANY_NBIT */
-ANY_NBIT(__rol_)
-
-/*******************************************/
-/*     Arithmetic and bitwise functions    */
-/*******************************************/
-
-#define __numeric(fname,TYPENAME, FUNC) \
-static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, TYPENAME op){\
-  TEST_EN(TYPENAME)\
-  return FUNC(op);\
-}
-
-  /**************/
-  /*    ABS     */
-  /**************/
-#define __abs_signed(TYPENAME) \
-static inline TYPENAME __abs_##TYPENAME(EN_ENO_PARAMS, TYPENAME op){\
-  TEST_EN(TYPENAME)\
-  if (op < 0)\
-    return -op;\
-  return op;\
-}
-ANY_REAL(__abs_signed)
-ANY_SINT(__abs_signed)
-
-#define __abs_unsigned(TYPENAME) \
-static inline TYPENAME __abs_##TYPENAME(EN_ENO_PARAMS, TYPENAME op){\
-  TEST_EN(TYPENAME)\
-  return op;\
-}
-ANY_UINT(__abs_unsigned)
-
-  /**************/
-  /*    SQRT    */
-  /**************/
-#define __sqrt_(TYPENAME) __numeric(__sqrt_, TYPENAME, sqrt)
-ANY_REAL(__sqrt_)
-
-  /**************/
-  /*     LN     */
-  /**************/
-#define __ln_(TYPENAME) __numeric(__ln_, TYPENAME, log)
-ANY_REAL(__ln_)
-
-  /**************/
-  /*     LOG    */
-  /**************/
-#define __log_(TYPENAME) __numeric(__log_, TYPENAME, log10)
-ANY_REAL(__log_)
-
-  /**************/
-  /*     EXP    */
-  /**************/
-#define __exp_(TYPENAME) __numeric(__exp_, TYPENAME, exp)
-ANY_REAL(__exp_)
-
-  /**************/
-  /*     SIN    */
-  /**************/
-#define __sin_(TYPENAME) __numeric(__sin_, TYPENAME, sin)
-ANY_REAL(__sin_)
-
-  /**************/
-  /*     COS    */
-  /**************/
-#define __cos_(TYPENAME) __numeric(__cos_, TYPENAME, cos)
-ANY_REAL(__cos_)
-
-  /**************/
-  /*     TAN    */
-  /**************/
-#define __tan_(TYPENAME) __numeric(__tan_, TYPENAME, tan)
-ANY_REAL(__tan_)
-
-  /**************/
-  /*    ASIN    */
-  /**************/
-#define __asin_(TYPENAME) __numeric(__asin_, TYPENAME, asin)
-ANY_REAL(__asin_)
-
-  /**************/
-  /*    ACOS    */
-  /**************/
-#define __acos_(TYPENAME) __numeric(__acos_, TYPENAME, acos)
-ANY_REAL(__acos_)
-
-  /**************/
-  /*    ATAN    */
-  /**************/
-#define __atan_(TYPENAME) __numeric(__atan_, TYPENAME, atan)
-ANY_REAL(__atan_)
-
-  /**************/
-  /*    EXPT    */
-  /**************/
-#define __expt_(TYPENAME)\
-static inline TYPENAME __expt_##TYPENAME(EN_ENO_PARAMS, TYPENAME IN1, REAL IN2){\
-  TEST_EN(TYPENAME)\
-  return pow(IN1, IN2);\
-}ANY_REAL(__expt_)
-
-/**************/
-/* Selection  */
-/**************/
-
-  /**************/
-  /*    SEL     */
-  /**************/
-
-#define __sel_(TYPENAME)\
-static inline TYPENAME __sel_##TYPENAME(EN_ENO_PARAMS, BOOL G, TYPENAME op0, TYPENAME op1){\
+  return ~op1;\
+}
+__ANY_NBIT(__iec_)
+#undef __iec_
+
+
+
+
+
+
+/***************************************************/  
+/***************************************************/  
+/*  2.5.1.5.4  Selection and comparison Functions  */
+/***************************************************/  
+/***************************************************/  
+
+/*********************/
+/***   Table 27    ***/
+/*********************/
+
+
+    /**************/
+    /*    SEL     */
+    /**************/
+
+/* The explicitly typed standard functions */
+#define __iec_(TYPENAME)\
+static inline TYPENAME SEL_##TYPENAME(EN_ENO_PARAMS, BOOL G, TYPENAME op0, TYPENAME op1){\
   TEST_EN(TYPENAME)\
   return G ? op1 : op0;\
 }
-ANY(__sel_)
-
-	/**************/
-	/*   limit    */
-	/**************/
-
-#define __limit_(TYPENAME)\
-static inline TYPENAME __limit_##TYPENAME(EN_ENO_PARAMS, TYPENAME MN, TYPENAME IN, TYPENAME MX){\
+__ANY(__iec_)
+#undef __iec_
+
+/* Overloaded function */
+#define __iec_(TYPENAME)\
+static inline TYPENAME SEL__##TYPENAME##__BOOL__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, BOOL G, TYPENAME op0, TYPENAME op1){\
   TEST_EN(TYPENAME)\
-  return IN > MN ? IN < MX ? IN : MX : MN;\
-}
-
-/* Call previously defined macro for each concerned type */
-ANY_NBIT(__limit_)
-ANY_NUM(__limit_)
-
-#define __limit_time(TYPENAME)\
-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;\
-}
-
-/* Call previously defined macro for each concerned type */
-ANY_DATE(__limit_time)
-__limit_time(TIME)
-
-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;
-}
+  return G ? op1 : op0;\
+}
+__ANY(__iec_)
+#undef __iec_
+
 
     /**************/
     /*     MAX    */
     /**************/
 
 #define __extrem_(fname,TYPENAME, COND) \
-static inline TYPENAME fname##TYPENAME(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)\
@@ -1161,52 +1495,130 @@
   return op1;\
 }
 
-#define __max_num(TYPENAME) __extrem_(__max_,TYPENAME, op1 < tmp)
-ANY_NBIT(__max_num)
-ANY_NUM(__max_num)
-
-__extrem_(__max_, STRING, __STR_CMP(op1,tmp) < 0)
-#define __max_time(TYPENAME) __extrem_(__max_, TYPENAME, __TIME_CMP(op1, tmp) < 0)
-
-/* Call previously defined macro for each concerned type */
-ANY_DATE(__max_time)
-__max_time(TIME)
+/* Max for numerical data types */	
+#define __iec_(TYPENAME) \
+__extrem_(MAX_##TYPENAME,TYPENAME, op1 < tmp) /* The explicitly typed standard functions */\
+__extrem_(MAX__##TYPENAME##__##TYPENAME,TYPENAME, op1 < tmp) /* Overloaded function */
+__ANY_BIT(__iec_)
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/* Max for time data types */	
+#define __iec_(TYPENAME) \
+__extrem_(MAX_##TYPENAME, TYPENAME, __time_cmp(op1, tmp) < 0) /* The explicitly typed standard functions */\
+__extrem_(MAX__##TYPENAME##__##TYPENAME, TYPENAME, __time_cmp(op1, tmp) < 0) /* Overloaded function */
+__ANY_DATE(__iec_)
+__iec_(TIME)
+#undef __iec_
+
+/* Max for string data types */	
+__extrem_(MAX_STRING, STRING, __STR_CMP(op1,tmp) < 0) /* The explicitly typed standard functions */
+__extrem_(MAX__STRING__STRING, STRING, __STR_CMP(op1,tmp) < 0) /* Overloaded function */
 
     /**************/
     /*     MIN    */
     /**************/
-#define __min_num(TYPENAME) __extrem_(__min_, TYPENAME, op1 > tmp)
-ANY_NBIT(__min_num)
-ANY_NUM(__min_num)
-
-__extrem_(__min_, STRING, __STR_CMP(op1,tmp) > 0)
-
-#define __min_time(TYPENAME) __extrem_(__min_, TYPENAME, __TIME_CMP(op1, tmp) > 0)
-
-/* Call previously defined macro for each concerned type */
-ANY_DATE(__min_time)
-__min_time(TIME)
+/* Min for numerical data types */	
+#define __iec_(TYPENAME) \
+__extrem_(MIN_##TYPENAME, TYPENAME, op1 > tmp) /* The explicitly typed standard functions */\
+__extrem_(MIN__##TYPENAME##__##TYPENAME, TYPENAME, op1 > tmp) /* Overloaded function */
+__ANY_NBIT(__iec_)
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/* Min for time data types */	
+#define __iec_(TYPENAME) \
+__extrem_(MIN_##TYPENAME, TYPENAME, __time_cmp(op1, tmp) > 0) /* The explicitly typed standard functions */\
+__extrem_(MIN__##TYPENAME##__##TYPENAME, TYPENAME, __time_cmp(op1, tmp) > 0) /* Overloaded function */
+__ANY_DATE(__iec_)
+__iec_(TIME)
+#undef __iec_
+
+/* Min for string data types */
+__extrem_(MIN_STRING, STRING, __STR_CMP(op1,tmp) > 0) /* The explicitly typed standard functions */
+__extrem_(MIN__STRING__STRING, STRING, __STR_CMP(op1,tmp) > 0) /* Overloaded function */
+
+    /**************/
+    /*   LIMIT    */
+    /**************/
+
+/* 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){\
+  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){\
+  TEST_EN(TYPENAME)\
+  return IN > MN ? IN < MX ? IN : MX : MN;\
+}
+__ANY_NBIT(__iec_)
+__ANY_NUM(__iec_)
+#undef __iec_
+
+
+/* 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){\
+    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){\
+    TEST_EN(TYPENAME)\
+    return __time_cmp(IN, MN) > 0 ? /* IN>MN ?*/\
+           __time_cmp(IN, MX) < 0 ? /* IN<MX ?*/\
+           IN : MX : MN;\
+}
+
+__ANY_DATE(__iec_)
+__iec_(TIME)
+#undef __iec_
+
+/* Limit for string data types */	
+/* The explicitly typed standard functions */
+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){
+    TEST_EN(STRING)
+    return __STR_CMP(IN, MN) > 0 ? __STR_CMP(IN, MX) < 0 ? IN : MX : MN;
+}
+
 
     /**************/
     /*     MUX    */
     /**************/
-#define __mux_(TYPENAME) \
-static inline TYPENAME __mux_##TYPENAME(EN_ENO_PARAMS, UINT param_count, UINT K, ...){\
+/* The standard states that the inputs for SEL and MUX must be named starting off from 0,
+ * unlike remaining functions, that start off at 1.
+ */    
+/* 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, UINT param_count, in1_TYPENAME K, ...){\
   va_list ap;\
   UINT i;\
-  TYPENAME tmp;\
-  TEST_EN_COND(TYPENAME, K >= param_count)\
-  tmp = __INIT_##TYPENAME;\
+  in2_TYPENAME tmp;\
+  TEST_EN_COND(in2_TYPENAME, K >= param_count)\
+  tmp = __INIT_##in2_TYPENAME;\
   \
   va_start (ap, K);         /* Initialize the argument list.  */\
   \
   for (i = 0; i < param_count; i++){\
     if(K == i){\
-        tmp = va_arg (ap, VA_ARGS_##TYPENAME);\
+        tmp = va_arg (ap, VA_ARGS_##in2_TYPENAME);\
         va_end (ap);                  /* Clean up.  */\
         return tmp;\
     }else{\
-        va_arg (ap, VA_ARGS_##TYPENAME);\
+        va_arg (ap, VA_ARGS_##in2_TYPENAME);\
     }\
   }\
   \
@@ -1214,14 +1626,17 @@
   return tmp;\
 }
 
-ANY(__mux_)
-
-/**************/
-/* Comparison */
-/**************/
+__ANY(__in1_anyint_)
+#undef __iec_
+
+
+/******************************************/
+/***             Table 28               ***/
+/***   Standard comparison functions    ***/
+/******************************************/
 
 #define __compare_(fname,TYPENAME, COND) \
-static inline BOOL fname##TYPENAME(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)\
@@ -1246,91 +1661,537 @@
 }
 
 #define __compare_num(fname, TYPENAME, TEST) __compare_(fname, TYPENAME, op1 TEST tmp )
-#define __compare_time(fname, TYPENAME, TEST) __compare_(fname, TYPENAME, __TIME_CMP(op1, tmp) TEST 0)
+#define __compare_time(fname, TYPENAME, TEST) __compare_(fname, TYPENAME, __time_cmp(op1, tmp) TEST 0)
 #define __compare_string(fname, TEST) __compare_(fname, STRING, __STR_CMP(op1, tmp) TEST 0 )
 
 
     /**************/
     /*     GT     */
     /**************/
-
-#define __gt_num(TYPENAME) __compare_num(__gt_, TYPENAME, > )
-ANY_NBIT(__gt_num)
-ANY_NUM(__gt_num)
-
-#define __gt_time(TYPENAME) __compare_time(__gt_, TYPENAME, > )
-ANY_DATE(__gt_time)
-__gt_time(TIME)
-
-__compare_string(__gt_, > )
+/* Comparison for numerical data types */
+#define __iec_(TYPENAME) \
+__compare_num(GT_##TYPENAME, TYPENAME, > ) /* The explicitly typed standard functions */\
+__compare_num(GT__BOOL__##TYPENAME, TYPENAME, > ) /* Overloaded function */
+__ANY_NBIT(__iec_)
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/* Comparison for time data types */	
+#define __iec_(TYPENAME) \
+__compare_time(GT_##TYPENAME, TYPENAME, > ) /* The explicitly typed standard functions */\
+__compare_time(GT__BOOL__##TYPENAME, TYPENAME, > ) /* Overloaded function */
+__ANY_DATE(__iec_)
+__iec_(TIME)
+#undef __iec_
+
+/* Comparison for string data types */	
+__compare_string(GT_STRING, > ) /* The explicitly typed standard functions */
+__compare_string(GT__BOOL__STRING, > ) /* Overloaded function */
 
     /**************/
     /*     GE     */
     /**************/
-
-#define __ge_num(TYPENAME) __compare_num(__ge_, TYPENAME, >= )
-ANY_BIT(__ge_num)
-ANY_NUM(__ge_num)
-
-#define __ge_time(TYPENAME) __compare_time(__ge_, TYPENAME, >= )
-ANY_DATE(__ge_time)
-__ge_time(TIME)
-
-__compare_string(__ge_, >=)
+/* Comparison for numerical data types */
+#define __iec_(TYPENAME) \
+__compare_num(GE_##TYPENAME, TYPENAME, >= ) /* The explicitly typed standard functions */\
+__compare_num(GE__BOOL__##TYPENAME, TYPENAME, >= ) /* Overloaded function */
+__ANY_NBIT(__iec_)
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/* Comparison for time data types */	
+#define __iec_(TYPENAME) \
+__compare_time(GE_##TYPENAME, TYPENAME, >= ) /* The explicitly typed standard functions */\
+__compare_time(GE__BOOL__##TYPENAME, TYPENAME, >= ) /* Overloaded function */
+__ANY_DATE(__iec_)
+__iec_(TIME)
+#undef __iec_
+
+/* Comparison for string data types */	
+__compare_string(GE_STRING, >= ) /* The explicitly typed standard functions */
+__compare_string(GE__BOOL__STRING, >= ) /* Overloaded function */
+
+
 
     /**************/
     /*     EQ     */
     /**************/
-
-#define __eq_num(TYPENAME) __compare_num(__eq_, TYPENAME, == )
-ANY_BIT(__eq_num)
-ANY_NUM(__eq_num)
-
-#define __eq_time(TYPENAME) __compare_time(__eq_, TYPENAME, == )
-ANY_DATE(__eq_time)
-__eq_time(TIME)
-
-__compare_string(__eq_, == )
+/* Comparison for numerical data types */
+#define __iec_(TYPENAME) \
+__compare_num(EQ_##TYPENAME, TYPENAME, == ) /* The explicitly typed standard functions */\
+__compare_num(EQ__BOOL__##TYPENAME, TYPENAME, == ) /* Overloaded function */
+__ANY_NBIT(__iec_)
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/* Comparison for time data types */	
+#define __iec_(TYPENAME) \
+__compare_time(EQ_##TYPENAME, TYPENAME, == ) /* The explicitly typed standard functions */\
+__compare_time(EQ__BOOL__##TYPENAME, TYPENAME, == ) /* Overloaded function */
+__ANY_DATE(__iec_)
+__iec_(TIME)
+#undef __iec_
+
+/* Comparison for string data types */	
+__compare_string(EQ_STRING, == ) /* The explicitly typed standard functions */
+__compare_string(EQ__BOOL__STRING, == ) /* Overloaded function */
+
 
     /**************/
     /*     LT     */
     /**************/
-
-#define __lt_num(TYPENAME) __compare_num(__lt_, TYPENAME, < )
-ANY_BIT(__lt_num)
-ANY_NUM(__lt_num)
-
-#define __lt_time(TYPENAME) __compare_time(__lt_, TYPENAME, < )
-ANY_DATE(__lt_time)
-__lt_time(TIME)
-
-__compare_string(__lt_, < )
+/* Comparison for numerical data types */
+#define __iec_(TYPENAME) \
+__compare_num(LT_##TYPENAME, TYPENAME, < ) /* The explicitly typed standard functions */\
+__compare_num(LT__BOOL__##TYPENAME, TYPENAME, < ) /* Overloaded function */
+__ANY_NBIT(__iec_)
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/* Comparison for time data types */	
+#define __iec_(TYPENAME) \
+__compare_time(LT_##TYPENAME, TYPENAME, < ) /* The explicitly typed standard functions */\
+__compare_time(LT__BOOL__##TYPENAME, TYPENAME, < ) /* Overloaded function */
+__ANY_DATE(__iec_)
+__iec_(TIME)
+#undef __iec_
+
+/* Comparison for string data types */	
+__compare_string(LT_STRING, < ) /* The explicitly typed standard functions */
+__compare_string(LT__BOOL__STRING, < ) /* Overloaded function */
+
 
     /**************/
     /*     LE     */
     /**************/
-
-#define __le_num(TYPENAME) __compare_num(__le_, TYPENAME, <= )
-ANY_BIT(__le_num)
-ANY_NUM(__le_num)
-
-#define __le_time(TYPENAME) __compare_time(__le_, TYPENAME, <= )
-ANY_DATE(__le_time)
-__le_time(TIME)
-
-__compare_string(__le_, <= )
+/* Comparison for numerical data types */
+#define __iec_(TYPENAME) \
+__compare_num(LE_##TYPENAME, TYPENAME, <= ) /* The explicitly typed standard functions */\
+__compare_num(LE__BOOL__##TYPENAME, TYPENAME, <= ) /* Overloaded function */
+__ANY_NBIT(__iec_)
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/* Comparison for time data types */	
+#define __iec_(TYPENAME) \
+__compare_time(LE_##TYPENAME, TYPENAME, <= ) /* The explicitly typed standard functions */\
+__compare_time(LE__BOOL__##TYPENAME, TYPENAME, <= ) /* Overloaded function */
+__ANY_DATE(__iec_)
+__iec_(TIME)
+#undef __iec_
+
+/* Comparison for string data types */	
+__compare_string(LE_STRING, <= ) /* The explicitly typed standard functions */
+__compare_string(LE__BOOL__STRING, <= ) /* Overloaded function */
+
 
     /**************/
     /*     NE     */
     /**************/
-
-#define __ne_num(TYPENAME) __compare_num(__ne_, TYPENAME, != )
-ANY_BIT(__ne_num)
-ANY_NUM(__ne_num)
-
-#define __ne_time(TYPENAME) __compare_time(__ne_, TYPENAME, != )
-ANY_DATE(__ne_time)
-__ne_time(TIME)
-
-__compare_string(__ne_, != )
-
+/* Comparison for numerical data types */
+#define __iec_(TYPENAME) \
+__compare_num(NE_##TYPENAME, TYPENAME, != ) /* The explicitly typed standard functions */\
+__compare_num(NE__BOOL__##TYPENAME##__##TYPENAME, TYPENAME, != ) /* Overloaded function */
+__ANY_NBIT(__iec_)
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/* Comparison for time data types */	
+#define __iec_(TYPENAME) \
+__compare_time(NE_##TYPENAME, TYPENAME, != ) /* The explicitly typed standard functions */\
+__compare_time(NE__BOOL__##TYPENAME##__##TYPENAME, TYPENAME, != ) /* Overloaded function */
+__ANY_DATE(__iec_)
+__iec_(TIME)
+#undef __iec_
+
+/* Comparison for string data types */	
+__compare_string(NE_STRING, != ) /* The explicitly typed standard functions */
+__compare_string(NE__BOOL__STRING__STRING, != ) /* Overloaded function */
+
+
+
+
+
+
+/*********************************************/  
+/*********************************************/  
+/*  2.5.1.5.5   Character string  Functions  */
+/*********************************************/  
+/*********************************************/  
+
+/*************************************/
+/***           Table 29            ***/
+/***  Character string  Functions  ***/
+/*************************************/
+
+/* We do not delcare explcitly typed versions of the functions in table 29.
+ * See note above regarding explicitly typed functions for more details.
+ */
+ 
+
+#define __STR_CMP(str1, str2) memcmp((char*)&str1.body,(char*)&str2.body, str1.len < str2.len ? str1.len : str2.len)
+
+
+    /***************/
+    /*     LEN     */
+    /***************/
+static inline __strlen_t __len(STRING IN) {return IN.len;}
+
+/* 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){\
+  TEST_EN(ret_TYPENAME)\
+  return (ret_TYPENAME)OPERATION(par1);\
+}
+
+#define __iec_(TYPENAME) __genoper_1p_(LEN__##TYPENAME##__STRING, TYPENAME, STRING, __len)
+__ANY_INT(__iec_)
+#undef __iec_
+
+
+    /****************/
+    /*     LEFT     */
+    /****************/
+
+static inline STRING __left(STRING IN, __strlen_t L){
+    STRING res;
+    res = __INIT_STRING;
+    L = L < IN.len ? L : IN.len;
+    memcpy(&res.body, &IN.body, L);
+    res.len = L;
+    return res;
+}
+
+#define __iec_(TYPENAME) \
+static inline STRING LEFT__STRING__STRING__##TYPENAME(EN_ENO_PARAMS, STRING str, TYPENAME L){\
+  TEST_EN_COND(STRING, L < 0)\
+  return (STRING)__left(str,L);\
+}
+__ANY_INT(__iec_)
+#undef __iec_
+
+
+    /*****************/
+    /*     RIGHT     */
+    /*****************/
+
+static inline STRING __right(STRING IN, __strlen_t L){
+    STRING res;
+    res = __INIT_STRING;
+    L = L < IN.len ? L : IN.len;
+    memcpy(&res.body, &IN.body[IN.len - L], L);
+    res.len = L;
+    return res;
+}
+
+
+#define __iec_(TYPENAME) \
+static inline STRING RIGHT__STRING__STRING__##TYPENAME(EN_ENO_PARAMS, STRING str, TYPENAME L){\
+  TEST_EN_COND(STRING, L < 0)\
+  return (STRING)__right(str,L);\
+}
+__ANY_INT(__iec_)
+#undef __iec_
+
+
+    /***************/
+    /*     MID     */
+    /***************/
+
+static inline STRING __mid(STRING IN, __strlen_t L, __strlen_t P){
+    STRING res;
+    res = __INIT_STRING;
+    if(P <= IN.len){
+	    P -= 1; /* now can be used as [index]*/
+	    L = L + P <= IN.len ? L : IN.len - P;
+	    memcpy(&res.body, &IN.body[P] , L);
+        res.len = L;
+    }
+    return res;
+}
+
+#define __iec_(TYPENAME) \
+static inline STRING MID__STRING__STRING__##TYPENAME##__##TYPENAME(EN_ENO_PARAMS, STRING str, TYPENAME L, TYPENAME P){\
+  TEST_EN_COND(STRING, L < 0 || P < 0)\
+  return (STRING)__mid(str,L,P);\
+}
+__ANY_INT(__iec_)
+#undef __iec_
+
+
+    /******************/
+    /*     CONCAT     */
+    /******************/
+
+static inline STRING CONCAT__STRING__STRING(UINT param_count, ...){
+  UINT i;
+  STRING res;
+  va_list ap;
+  __strlen_t charcount;
+  charcount = 0;
+  res = __INIT_STRING;
+
+  va_start (ap, param_count);         /* Initialize the argument list.  */
+
+  for (i = 0; i < param_count && charcount < STR_MAX_LEN; i++)
+  {
+    STRING tmp = va_arg(ap, STRING);
+    __strlen_t charrem = STR_MAX_LEN - charcount;
+    __strlen_t to_write = tmp.len > charrem ? charrem : tmp.len;
+    memcpy(&res.body[charcount], &tmp.body , to_write);
+    charcount += to_write;
+  }
+
+  res.len = charcount;
+
+  va_end (ap);                  /* Clean up.  */
+  return res;
+}
+
+    /******************/
+    /*     INSERT     */
+    /******************/
+
+static inline STRING __insert(STRING IN1, STRING IN2, __strlen_t P){
+    STRING res;
+    __strlen_t to_copy;
+    res = __INIT_STRING;
+
+    to_copy = P > IN1.len ? IN1.len : P;
+    memcpy(&res.body, &IN1.body , to_copy);
+    P = res.len = to_copy;
+
+    to_copy = IN2.len + res.len > STR_MAX_LEN ? STR_MAX_LEN - res.len : IN2.len;
+    memcpy(&res.body[res.len], &IN2.body , to_copy);
+    res.len += to_copy;
+
+    to_copy = IN1.len - P < STR_MAX_LEN - res.len ? IN1.len - P : STR_MAX_LEN - res.len ;
+    memcpy(&res.body[res.len], &IN1.body[P] , to_copy);
+    res.len += to_copy;
+
+    return res;
+}
+
+#define __iec_(TYPENAME) \
+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,P);\
+}
+__ANY_INT(__iec_)
+#undef __iec_
+
+
+    /******************/
+    /*     DELETE     */
+    /******************/
+
+static inline STRING __delete(STRING IN, __strlen_t L, __strlen_t P){
+    STRING res;
+    __strlen_t to_copy;
+    res = __INIT_STRING;
+
+    to_copy = P > IN.len ? IN.len : P-1;
+    memcpy(&res.body, &IN.body , to_copy);
+    P = res.len = to_copy;
+
+    if( IN.len > P + L ){
+        to_copy = IN.len - P - L;
+        memcpy(&res.body[res.len], &IN.body[P + L], to_copy);
+        res.len += to_copy;
+    }
+
+    return res;
+}
+
+#define __iec_(TYPENAME) \
+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,L,P);\
+}
+__ANY_INT(__iec_)
+#undef __iec_
+
+
+    /*******************/
+    /*     REPLACE     */
+    /*******************/
+
+static inline STRING __replace(STRING IN1, STRING IN2, __strlen_t L, __strlen_t P){
+    STRING res;
+    __strlen_t to_copy;
+    res = __INIT_STRING;
+
+    to_copy = P > IN1.len ? IN1.len : P-1;
+    memcpy(&res.body, &IN1.body , to_copy);
+    P = res.len = to_copy;
+
+    to_copy = IN2.len < L ? IN2.len : L;
+
+    if( to_copy + res.len > STR_MAX_LEN )
+       to_copy = STR_MAX_LEN - res.len;
+
+    memcpy(&res.body[res.len], &IN2.body , to_copy);
+    res.len += to_copy;
+
+    P += L;
+    if( res.len <  STR_MAX_LEN && P < IN1.len)
+    {
+        to_copy = IN1.len - P;
+        memcpy(&res.body[res.len], &IN1.body[P] , to_copy);
+        res.len += to_copy;
+    }
+
+    return res;
+}
+
+#define __iec_(TYPENAME) \
+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,L,P);\
+}
+__ANY_INT(__iec_)
+#undef __iec_
+
+    /****************/
+    /*     FIND     */
+    /****************/
+
+static inline __strlen_t __pfind(STRING* IN1, STRING* IN2){
+    UINT count1 = 0; /* offset of first matching char in IN1 */
+    UINT count2 = 0; /* count of matching char */
+    while(count1 + count2 < IN1->len && count2 < IN2->len)
+    {
+        if(IN1->body[count1 + count2] != IN2->body[count2]){
+            count1 += count2 + 1;
+            count2 = 0;
+        }
+        else {
+            count2++;
+        }
+    }
+    return count2 == IN2->len -1 ? 0 : count1 + 1;
+}
+
+#define __iec_(TYPENAME) \
+static inline TYPENAME FIND__##TYPENAME##__STRING__STRING(EN_ENO_PARAMS, STRING str1, STRING str2){\
+  TEST_EN(TYPENAME)\
+  return (TYPENAME)__pfind(&str1,&str2);\
+}
+__ANY_INT(__iec_)
+#undef __iec_
+
+
+/*********************************************/  
+/*********************************************/  
+/*  2.5.1.5.6  Functions of time data types  */
+/*********************************************/  
+/*********************************************/  
+
+/**************************************/
+/***           Table 30             ***/
+/***  Functions of time data types  ***/
+/**************************************/
+
+
+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){
+  TEST_EN(TOD)
+  return __time_add(IN1, 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){
+  TEST_EN(TIME)
+  return __time_sub(IN1, 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){
+  TEST_EN(TOD)
+  return __time_sub(IN1, 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){
+  TEST_EN(DT)
+  return __time_sub(IN1, IN2);
+}
+
+static inline TIME SUB_DT_DT(EN_ENO_PARAMS, DT IN1, DT IN2){
+  TEST_EN(TIME)
+  return __time_sub(IN1, IN2);
+}
+
+
+/***  MULTIME  ***/
+#define __iec_(TYPENAME)\
+static inline TIME MULTIME__TIME__TIME__##TYPENAME(EN_ENO_PARAMS, TIME IN1, TYPENAME IN2){\
+  TEST_EN(TIME)\
+  return __time_mul(IN1, IN2);\
+}
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/***  MUL  ***/
+#define __iec_(TYPENAME)\
+static inline TIME MUL__TIME__TIME__##TYPENAME(EN_ENO_PARAMS, TIME IN1, TYPENAME IN2){\
+  TEST_EN(TIME)\
+  return __time_mul(IN1, IN2);\
+}
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/***  DIVTIME  ***/
+#define __iec_(TYPENAME)\
+static inline TIME DIVTIME__TIME__TIME__##TYPENAME(EN_ENO_PARAMS, TIME IN1, TYPENAME IN2){\
+  TEST_EN(TIME)\
+  return __time_div(IN1, IN2);\
+}
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/***  DIV  ***/
+#define __iec_(TYPENAME)\
+static inline TIME DIV__TIME__TIME__##TYPENAME(EN_ENO_PARAMS, TIME IN1, TYPENAME IN2){\
+  TEST_EN(TIME)\
+  return __time_div(IN1, IN2);\
+}
+__ANY_NUM(__iec_)
+#undef __iec_
+
+/*** CONCAT_DATE_TOD ***/
+static inline DT CONCAT_DATE_TOD(EN_ENO_PARAMS, DATE IN1, TOD IN2){
+  TEST_EN(DT)
+  return __time_add(IN1, IN2);
+}
+
+
+
+/****************************************************/  
+/****************************************************/  
+/*  2.5.1.5.6   Functions of enumerated data types  */
+/****************************************************/  
+/****************************************************/  
+
+/********************************************/
+/***              Table 31                ***/
+/***  Functions of enumerated data types  ***/
+/********************************************/
+
+/* Do we support this? */
--- a/lib/iec_types_all.h	Mon Jul 11 09:47:27 2011 +0100
+++ b/lib/iec_types_all.h	Fri Jul 29 16:03:28 2011 +0100
@@ -1,7 +1,59 @@
+/*
+ * Copyright (C) 2007-2011: Edouard TISSERANT and Laurent BESSARD
+ *
+ * See COPYING and COPYING.LESSER files for copyright details.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License 
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
 #ifndef IEC_TYPES_ALL_H
 #define IEC_TYPES_ALL_H
 
-#include "iec_std_lib_generated.h"
+
+/* Macro that expand to subtypes */
+#define __ANY(DO)                 __ANY_DERIVED(DO) __ANY_ELEMENTARY(DO)
+#define __ANY_DERIVED(DO)
+#define __ANY_ELEMENTARY(DO)      __ANY_MAGNITUDE(DO) __ANY_BIT(DO) __ANY_STRING(DO) __ANY_DATE(DO)
+#define __ANY_MAGNITUDE(DO)       __ANY_NUM(DO) DO(TIME)
+#define __ANY_BIT(DO)             __ANY_NBIT(DO) DO(BOOL)
+#define __ANY_NBIT(DO)            DO(BYTE) DO(WORD) DO(DWORD) DO(LWORD)
+#define __ANY_STRING(DO)          DO(STRING)
+#define __ANY_DATE(DO)            DO(DATE) DO(TOD) DO(DT)
+#define __ANY_NUM(DO)             __ANY_REAL(DO) __ANY_INT(DO)
+#define __ANY_REAL(DO)            DO(REAL) DO(LREAL)
+#define __ANY_INT(DO)             __ANY_SINT(DO) __ANY_UINT(DO)
+#define __ANY_SINT(DO)            DO(SINT) DO(INT) DO(DINT) DO(LINT)
+#define __ANY_UINT(DO)            DO(USINT) DO(UINT) DO(UDINT) DO(ULINT)
+
+
+/* Macro that expand to subtypes */
+#define __ANY_1(DO,P1)            __ANY_DERIVED_1(DO,P1) __ANY_ELEMENTARY_1(DO,P1)
+#define __ANY_DERIVED_1(DO,P1)
+#define __ANY_ELEMENTARY_1(DO,P1) __ANY_MAGNITUDE_1(DO,P1) __ANY_BIT_1(DO,P1) __ANY_STRING_1(DO,P1) __ANY_DATE_1(DO,P1)
+#define __ANY_MAGNITUDE_1(DO,P1)  __ANY_NUM_1(DO,P1) DO(TIME,P1)
+#define __ANY_BIT_1(DO,P1)        __ANY_NBIT_1(DO,P1) DO(BOOL,P1)
+#define __ANY_NBIT_1(DO,P1)       DO(BYTE,P1) DO(WORD,P1) DO(DWORD,P1) DO(LWORD,P1)
+#define __ANY_STRING_1(DO,P1)     DO(STRING,P1)
+#define __ANY_DATE_1(DO,P1)       DO(DATE,P1) DO(TOD,P1) DO(DT,P1)
+#define __ANY_NUM_1(DO,P1)        __ANY_REAL_1(DO,P1) __ANY_INT_1(DO,P1)
+#define __ANY_REAL_1(DO,P1)       DO(REAL,P1) DO(LREAL,P1)
+#define __ANY_INT_1(DO,P1)        __ANY_SINT_1(DO,P1) __ANY_UINT_1(DO,P1)
+#define __ANY_SINT_1(DO,P1)       DO(SINT,P1) DO(INT,P1) DO(DINT,P1) DO(LINT,P1)
+#define __ANY_UINT_1(DO,P1)       DO(USINT,P1) DO(UINT,P1) DO(UDINT,P1) DO(ULINT,P1)
+
+
 
 /*********************/
 /*  IEC Types defs   */
@@ -67,7 +119,7 @@
 
 /* Those typdefs clash with windows.h */
 /* i.e. this file cannot be included aside windows.h */
-ANY(__DECLARE_IEC_TYPE)
+__ANY(__DECLARE_IEC_TYPE)
 
 typedef struct {
   __IEC_BOOL_t state;     // current step state. 0 : inative, 1: active
@@ -85,16 +137,16 @@
 } ACTION;
 
 /* Extra debug types for SFC */
-#define ANY_SFC(DO) DO(STEP) DO(TRANSITION) DO(ACTION)
+#define __ANY_SFC(DO) DO(STEP) DO(TRANSITION) DO(ACTION)
 
 /* Enumerate native types */
 #define __decl_enum_type(TYPENAME) TYPENAME##_ENUM,
 #define __decl_enum_pointer(TYPENAME) TYPENAME##_P_ENUM,
 #define __decl_enum_output(TYPENAME) TYPENAME##_O_ENUM,
 typedef enum{
-  ANY(__decl_enum_type)
-  ANY(__decl_enum_pointer)
-  ANY(__decl_enum_output)
+  __ANY(__decl_enum_type)
+  __ANY(__decl_enum_pointer)
+  __ANY(__decl_enum_output)
   /* SFC specific types are never external or global */
   UNKNOWN_ENUM
 } __IEC_types_enum;
@@ -107,7 +159,7 @@
 		return sizeof(TYPENAME);
 static inline USINT __get_type_enum_size(__IEC_types_enum t){
  switch(t){
-  ANY(__decl_size_case)
+  __ANY(__decl_size_case)
   /* size do not correspond to real struct.
    * only a bool is used to represent state*/
   default:
--- a/lib/ieclib.txt	Mon Jul 11 09:47:27 2011 +0100
+++ b/lib/ieclib.txt	Fri Jul 29 16:03:28 2011 +0100
@@ -39,6 +39,6 @@
 {#include "pid_st.txt" }
 {#include "ramp_st.txt" }
 
-(* From later versions of the standard *)
+(* Not in the standard, but useful nonetheless. *)
 {#include "sema.txt" }
 
--- a/main.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/main.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -75,10 +75,13 @@
 
 /* A macro for printing out internal parser errors... */
 #include <iostream> // required for std::cerr
-#define ERROR error_exit(__FILE__,__LINE__)
+
+
+#define ERROR          error_exit(__FILE__,__LINE__)
 void error_exit(const char *file_name, int line_no) {
-  std::cerr << "\nInternal program error in file " << file_name
-            << " at line " << line_no << "\n\n\n";
+  std::cerr << "\nInternal compiler error in file " << file_name
+            << " at line " << line_no << "\n";
+//   if (msg != NULL) std::cerr << message << "\n\n";
   exit(EXIT_FAILURE);
 }
 
--- a/stage1_2/iec.flex	Mon Jul 11 09:47:27 2011 +0100
+++ b/stage1_2/iec.flex	Fri Jul 29 16:03:28 2011 +0100
@@ -814,9 +814,9 @@
 			    fprintf(stderr, "Includes nested too deeply\n");
 			    exit( 1 );
 			  }
-        include_stack[include_stack_ptr].buffer_state = YY_CURRENT_BUFFER;
-        include_stack[include_stack_ptr].env = current_tracking;
-        include_stack[include_stack_ptr].filename = current_filename;
+			  include_stack[include_stack_ptr].buffer_state = YY_CURRENT_BUFFER;
+			  include_stack[include_stack_ptr].env = current_tracking;
+			  include_stack[include_stack_ptr].filename = current_filename;
 			  
 			  for (i = 0, yyin = NULL; (INCLUDE_DIRECTORIES[i] != NULL) && (yyin == NULL); i++) {
 			    char *full_name = strdup3(INCLUDE_DIRECTORIES[i], "/", yytext);
--- a/stage1_2/iec.y	Mon Jul 11 09:47:27 2011 +0100
+++ b/stage1_2/iec.y	Fri Jul 29 16:03:28 2011 +0100
@@ -182,6 +182,14 @@
  */
 extern bool allow_function_overloading;
 
+/* A flag to tell the compiler whether to allow the declaration
+ * of extensible function (i.e. functions that may have a variable number of
+ * input parameters, such as AND(word#33, word#44, word#55, word#66).
+ * This is an extension to the standard syntax.
+ * See comments below for details why we support this!
+ */
+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...
  */
@@ -3587,15 +3595,48 @@
 ;
 
 
+/* NOTE: 
+ * The syntax 
+ *    variable_name DOTDOT 
+ * is an extension to the standard!!! 
+ *
+ * In order to be able to handle extensible standard functions
+ * (i.e. standard functions that may have a variable number of
+ * input parameters, such as AND(word#33, word#44, word#55, word#66),
+ * we have extended the acceptable syntax to allow var_name '..'
+ * in an input variable declaration.
+ *
+ * This allows us to parse the declaration of standard
+ * extensible functions and load their interface definition
+ * into the abstract syntax tree just like we do to other 
+ * user defined functions.
+ * This has the advantage that we can later do semantic
+ * checking of calls to functions (be it a standard or user defined
+ * function) in (almost) exactly the same way.
+ *
+ * Of course, we have a flag that disables this syntax when parsing user
+ * written code, so we only allow this extra syntax while parsing the 
+ * 'header' file that declares all the standard IEC 61131-3 functions.
+ */
 var1_list:
   variable_name
 	{$$ = new var1_list_c(locloc(@$)); $$->add_element($1);
 	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
 	}
+| variable_name integer DOTDOT
+	{$$ = new var1_list_c(locloc(@$)); $$->add_element(new extensible_input_parameter_c($1, $2, locloc(@$)));
+	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
+	 if (!allow_extensible_function_parameters) print_err_msg(locf(@1), locl(@2), "invalid syntax in variable name declaration.");
+	}
  | var1_list ',' variable_name
 	{$$ = $1; $$->add_element($3);
 	 variable_name_symtable.insert($3, prev_declared_variable_name_token);
 	}
+ | var1_list ',' variable_name integer DOTDOT
+	{$$ = $1; $$->add_element(new extensible_input_parameter_c($3, $4, locloc(@$)));
+	 variable_name_symtable.insert($3, prev_declared_variable_name_token);
+	 if (!allow_extensible_function_parameters) print_err_msg(locf(@1), locl(@2), "invalid syntax in variable name declaration.");
+	}
 /* ERROR_CHECK_BEGIN */
 | var1_list variable_name
 	{$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in variable list."); yynerrs++;}
@@ -4307,13 +4348,13 @@
 	{$$ = new single_byte_string_spec_c(NULL, NULL);}
 */
   STRING '[' integer ']'
-	{$$ = new single_byte_string_spec_c($3, NULL, locloc(@$));}
+	{$$ = new single_byte_string_spec_c(new single_byte_limited_len_string_spec_c(new string_type_name_c(locloc(@1)), $3, locloc(@$)), NULL, locloc(@$));}
 /*
 | STRING ASSIGN single_byte_character_string
-	{$$ = new single_byte_string_spec_c(NULL, $3, locloc(@$));}
+	{$$ = new single_byte_string_spec_c($1, NULL, $3, locloc(@$));}
 */
 | STRING '[' integer ']' ASSIGN single_byte_character_string
-	{$$ = new single_byte_string_spec_c($3, $6, locloc(@$));}
+	{$$ = new single_byte_string_spec_c(new single_byte_limited_len_string_spec_c(new string_type_name_c(locloc(@1)), $3, locloc(@$)), $6, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | STRING '[' error ']'
 	{$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited string type specification."); yyerrok;}
@@ -4348,16 +4389,17 @@
 
 double_byte_string_spec:
 /*  WSTRING
-	{$$ = new double_byte_string_spec_c(NULL, NULL, locloc(@$));}
+	{$$ = new double_byte_string_spec_c($1, NULL, NULL, locloc(@$));}
 */
   WSTRING '[' integer ']'
-	{$$ = new double_byte_string_spec_c($3, NULL, locloc(@$));}
+	{$$ = new double_byte_string_spec_c(new double_byte_limited_len_string_spec_c(new wstring_type_name_c(locloc(@1)), $3, locloc(@$)), NULL, locloc(@$));}
+
 /*
 | WSTRING ASSIGN double_byte_character_string
-	{$$ = new double_byte_string_spec_c(NULL, $3, locloc(@$));}
+	{$$ = new double_byte_string_spec_c($1, NULL, $3, locloc(@$));}
 */
 | WSTRING '[' integer ']' ASSIGN double_byte_character_string
-	{$$ = new double_byte_string_spec_c($3, $6, locloc(@$));}
+	{$$ = new double_byte_string_spec_c(new double_byte_limited_len_string_spec_c(new wstring_type_name_c(locloc(@1)), $3, locloc(@$)), $6, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | WSTRING '[' error ']'
 	{$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited double byte string type specification."); yyerrok;}
@@ -4458,27 +4500,18 @@
 
 
 /* helper symbol for var_spec */
-/* NOTE: The constructs
- *
- *       STRING
- *       and
- *       WSTRING
- *
- *       were removed as they are already contained
- *       within a simple_specification.
- */
 string_spec:
 /*  STRING
-	{$$ = new single_byte_string_spec_c(NULL, NULL, locloc(@$));}
+	{$$ = new single_byte_limited_len_string_spec_c($1, NULL, locloc(@$));}
 */
   STRING '[' integer ']'
-	{$$ = new single_byte_string_spec_c($3, NULL, locloc(@$));}
+	{$$ = new single_byte_limited_len_string_spec_c(new string_type_name_c(locloc(@1)), $3, locloc(@$));}
 /*
 | WSTRING
-	{$$ = new double_byte_string_spec_c(NULL, NULL, locloc(@$));}
+	{$$ = new double_byte_limited_len_string_spec_c($1, NULL, locloc(@$));}
 */
 | WSTRING '[' integer ']'
-	{$$ = new double_byte_string_spec_c($3, NULL, locloc(@$));}
+	{$$ = new double_byte_limited_len_string_spec_c(new wstring_type_name_c(locloc(@1)), $3, locloc(@$));}
 ;
 
 
@@ -4665,11 +4698,31 @@
   identifier
 | prev_declared_derived_function_name
 	{$$ = $1;
-	 if (not(allow_function_overloading)) {
+	 if (!allow_function_overloading) {
 	   fprintf(stderr, "Function overloading not allowed. Invalid identifier %s\n", ((token_c *)($1))->value);
 	   ERROR;
 	 }
 	}
+| AND
+	{$$ = new identifier_c("AND", locloc(@$));
+	 if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"AND\" not allowed. Invalid identifier\n");
+	}
+| OR
+	{$$ = new identifier_c("OR", locloc(@$));
+	 if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"OR\" not allowed. Invalid identifier\n");
+	}
+| XOR
+	{$$ = new identifier_c("XOR", locloc(@$));
+	 if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"XOR\" not allowed. Invalid identifier\n");
+	}
+| NOT
+	{$$ = new identifier_c("NOT", locloc(@$));
+	 if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"NOT\" not allowed. Invalid identifier\n");
+	}
+| MOD
+	{$$ = new identifier_c("MOD", locloc(@$));
+	 if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"MOD\" not allowed. Invalid identifier\n");
+	}
 ;
 
 
@@ -7901,6 +7954,28 @@
  */
 bool allow_function_overloading = false;
 
+/* | [var1_list ','] variable_name '..' */
+/* NOTE: This is an extension to the standard!!! */
+/* In order to be able to handle extensible standard functions
+ * (i.e. standard functions that may have a variable number of
+ * input parameters, such as AND(word#33, word#44, word#55, word#66),
+ * we have extended the acceptable syntax to allow var_name '..'
+ * in an input variable declaration.
+ *
+ * This allows us to parse the declaration of standard
+ * extensible functions and load their interface definition
+ * into the abstract syntax tree just like we do to other 
+ * user defined functions.
+ * This has the advantage that we can later do semantic
+ * checking of calls to functions (be it a standard or user defined
+ * function) in (almost) exactly the same way.
+ *
+ * Of course, we have a flag that disables this syntax when parsing user
+ * written code, so we only allow this extra syntax while parsing the 
+ * 'header' file that declares all the standard IEC 61131-3 functions.
+ */
+bool allow_extensible_function_parameters = false;
+
 /* A global flag used to tell the parser whether to include the full variable location
  * when printing out error messages...
  */
@@ -7991,6 +8066,22 @@
 
 
 
+/* If function overloading is on, we allow several functions with the same name.
+ *
+ * However, to support standard functions, we also allow functions named
+ *   AND, MOD, NOT, OR, XOR, ADD, ...
+ */
+/*
+identifier_c *token_2_identifier_c(char *value, ) {
+  identifier_c tmp = new identifier_c(value, locloc(@$));
+	 if (!allow_function_overloading) {
+	   fprintf(stderr, "Function overloading not allowed. Invalid identifier %s\n", ((token_c *)($$))->value);
+	   ERROR;
+	 }
+	}
+}
+*/
+
 /* convert between an il_operator to a function name */
 /* This a kludge!
  * It is required because our language requires more than one
@@ -8124,11 +8215,6 @@
   FILE *in_file = NULL, *lib_file = NULL;
   char *libfilename = NULL;
 	
-  for(int i = 0; standard_function_names[i] != NULL; i++)
-    if (library_element_symtable.find_value(standard_function_names[i]) ==
-        library_element_symtable.end_value())
-      library_element_symtable.insert(standard_function_names[i], standard_function_name_token);
-
   if((in_file = fopen(filename, "r")) == NULL) {
     char *errmsg = strdup2("Error opening main file ", filename);
     perror(errmsg);
@@ -8165,6 +8251,7 @@
   */
   yyin = lib_file;
   allow_function_overloading = true;
+  allow_extensible_function_parameters = true;
   full_token_loc = full_token_loc_;
   current_filename = libfilename;
   current_tracking = GetNewTracking(yyin);
@@ -8193,6 +8280,7 @@
   #endif
   yyin = in_file;
   allow_function_overloading = false;
+  allow_extensible_function_parameters = false;
   full_token_loc = full_token_loc_;
   current_filename = filename;
   current_tracking = GetNewTracking(yyin);
--- a/stage3/visit_expression_type.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/stage3/visit_expression_type.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -604,7 +604,7 @@
 }
 
 
-
+#if 0
 #define is_num_type      is_ANY_NUM_compatible
 #define is_integer_type  is_ANY_INT_compatible
 #define is_real_type     is_ANY_REAL_compatible
@@ -633,7 +633,7 @@
 #undef is_nbinary_type
 #undef is_integer_type
 #undef is_num_type
-
+#endif
 
 
 
@@ -720,12 +720,20 @@
 /* A helper function... */
 /* check the semantics of a FB or Function non-formal call */
 /* e.g. foo(1, 2, 3, 4);  */
-void visit_expression_type_c::check_nonformal_call(symbol_c *f_call, symbol_c *f_decl, bool use_il_defvar) {
+/* If error_count pointer is != NULL, we do not really print out the errors,
+ * but rather only count how many errors were found.
+ * This is used to support overloaded functions, where we have to check each possible
+ * function, one at a time, untill we find a function call without any errors.
+ */
+void visit_expression_type_c::check_nonformal_call(symbol_c *f_call, symbol_c *f_decl, bool use_il_defvar, int *error_count) {
   symbol_c *call_param_value, *call_param_type, *param_type;
   identifier_c *param_name;
   function_param_iterator_c       fp_iterator(f_decl);
   function_call_param_iterator_c fcp_iterator(f_call);
-
+  int extensible_parameter_highest_index = -1;
+  
+  /* reset error counter */
+  if (error_count != NULL) *error_count = 0;
   /* if use_il_defvar, then the first parameter for the call comes from the il_default_variable */
   if (use_il_defvar) {
     /* The first parameter of the function corresponds to the il_default_variable_type of the function call */
@@ -740,20 +748,48 @@
     } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
     /* If the function does not have any parameters (param_name == NULL)
      * then we cannot compare its type with the il_default_variable_type.
+     *
+     * However, I (Mario) think this is invalid syntax, as it seems to me all functions must
+     * have at least one parameter.
+     * However, we will make this semantic verification consider it possible, as later
+     * versions of the standard may change that syntax.
+     * So, instead of generating a syntax error message, we simply check whether the call
+     * is passing any more parameters besides the default variable (the il default variable may be ignored
+     * in this case, and not consider it as being a parameter being passed to the function).
+     * If it does, then we have found a semantic error, otherwise the function call is 
+     * correct, and we simply return.
      */
-    if(param_name != NULL) {
+    if(param_name == NULL) {
+      if (fcp_iterator.next_nf() != NULL)
+        STAGE3_ERROR(f_call, f_call, "Too many parameters in function/FB call.");
+      return;
+    } else { 
+      /* param_name != NULL */
       param_type = fp_iterator.param_type();
-      if(!is_valid_assignment(param_type, il_default_variable_type)) 
-        STAGE3_ERROR(f_call, f_call, "In function/FB call, first parameter has invalid data type.");
+      if(!is_valid_assignment(param_type, il_default_variable_type)) {
+        if (error_count != NULL) (*error_count)++;
+        else STAGE3_ERROR(f_call, f_call, "In function/FB call, first parameter has invalid data type.");
+      }
+    }
+    
+    /* the fisrt parameter (il_def_variable) is correct */
+    if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
+      extensible_parameter_highest_index = fp_iterator.extensible_param_index();
     }
   } // if (use_il_defvar)
+  
+  
 
   /* Iterating through the non-formal parameters of the function call */
   while((call_param_value = fcp_iterator.next_nf()) != NULL) {
     /* Obtaining the type of the value being passed in the function call */
     call_param_type = base_type((symbol_c*)call_param_value->accept(*this));
     if (call_param_type == NULL) {
-      STAGE3_ERROR(call_param_value, call_param_value, "Could not determine data type of value being passed in function/FB call.");
+      if (error_count != NULL) (*error_count)++;
+      /* the following error will usually occur when ST code uses an identifier, that could refer to an enumerated constant,
+       * but was not actually used as a constant in any definitions of an enumerated data type
+       */
+      else STAGE3_ERROR(call_param_value, call_param_value, "Could not determine data type of value being passed in function/FB call.");
       continue;
     }  
     
@@ -762,17 +798,43 @@
      */
     do {
       param_name = fp_iterator.next();
-      /* If there is no parameter declared with that name */
-      if(param_name == NULL) {STAGE3_ERROR(f_call, f_call, "Too many parameters in function/FB call."); break;}
+      /* If there is no other parameter declared, then we are passing too many parameters... */
+      if(param_name == NULL) {
+        if (error_count != NULL) (*error_count)++;
+        /* Note: We don't want to print out the follwoing error message multiple times, so we return instead of continuing with 'break' */
+        else STAGE3_ERROR(f_call, f_call, "Too many parameters in function/FB call."); return;
+      }
     } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
 
-    if(param_name != NULL) {
-      /* Get the parameter type */
-      param_type = base_type(fp_iterator.param_type());
-      /* If the declared parameter and the parameter from the function call do no have the same type */
-      if(!is_valid_assignment(param_type, call_param_type)) STAGE3_ERROR(call_param_value, call_param_value, "Type mismatch in function/FB call parameter.");
+    /* Get the parameter type */
+    param_type = base_type(fp_iterator.param_type());
+    /* If the declared parameter and the parameter from the function call do not have the same type */
+    if(!is_valid_assignment(param_type, call_param_type)) {
+      if (error_count != NULL) (*error_count)++;
+      else STAGE3_ERROR(call_param_value, call_param_value, "Type mismatch in function/FB call parameter.");
     }
-  }
+
+    if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
+      extensible_parameter_highest_index = fp_iterator.extensible_param_index();
+    }
+  }
+  
+  /* The function call may not have any errors! */
+  /* In the case of a call to an extensible function, we store the highest index 
+   * of the extensible parameters this particular call uses, in the symbol_c object
+   * of the function call itself!
+   * In calls to non-extensible functions, this value will be set to -1.
+   * This information is later used in stage4 to correctly generate the
+   * output code.
+   */
+  int extensible_param_count = -1;
+  if (extensible_parameter_highest_index >=0) /* if call to extensible function */
+    extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index();
+  il_function_call_c     *il_function_call = dynamic_cast<il_function_call_c *>(f_call);
+  function_invocation_c  *function_invocation  = dynamic_cast<function_invocation_c  *>(f_call);
+  if      (il_function_call     != NULL) il_function_call   ->extensible_param_count = extensible_param_count;
+  else if (function_invocation  != NULL) function_invocation->extensible_param_count = extensible_param_count;
+  //   else ERROR;  /* this function is also called by Function Blocks, so this is not an error! */
 }
 
 
@@ -814,12 +876,22 @@
 /* A helper function... */
 /* check the semantics of a FB or Function formal call */
 /* e.g. foo(IN1 := 1, OUT1 =>x, EN := true);  */
-void visit_expression_type_c::check_formal_call(symbol_c *f_call, symbol_c *f_decl) {
+/* If error_count pointer is != NULL, we do not really print out the errors,
+ * but rather only count how many errors were found.
+ * This is used to support overloaded functions, where we have to check each possible
+ * function, one at a time, untill we find a function call without any errors.
+ */
+void visit_expression_type_c::check_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) {
   symbol_c *call_param_value, *call_param_type, *call_param_name, *param_type;
   symbol_c *verify_duplicate_param;
   identifier_c *param_name;
   function_param_iterator_c       fp_iterator(f_decl);
   function_call_param_iterator_c fcp_iterator(f_call);
+  int extensible_parameter_highest_index = -1;
+  identifier_c *extensible_parameter_name;
+
+  /* reset error counter */
+  if (error_count != NULL) *error_count = 0;
 
   /* Iterating through the formal parameters of the function call */
   while((call_param_name = fcp_iterator.next_f()) != NULL) {
@@ -832,13 +904,15 @@
     /* Checking if there are duplicated parameter values */
     verify_duplicate_param = fcp_iterator.search_f(call_param_name);
     if(verify_duplicate_param != call_param_value){
-      STAGE3_ERROR(call_param_name, verify_duplicate_param, "Duplicated parameter values.");
+      if (error_count != NULL) (*error_count)++;
+      else STAGE3_ERROR(call_param_name, verify_duplicate_param, "Duplicated parameter values.");
     }   
 
     /* Obtaining the type of the value being passed in the function call */
     call_param_type = (symbol_c*)call_param_value->accept(*this);
     if (call_param_type == NULL) {
-      STAGE3_ERROR(call_param_name, call_param_value, "Could not determine data type of value being passed in function/FB call.");
+      if (error_count != NULL) (*error_count)++;
+      else STAGE3_ERROR(call_param_name, call_param_value, "Could not determine data type of value being passed in function/FB call.");
       /* The data value being passed is possibly any enumerated type value.
        * We do not yet handle semantic verification of enumerated types.
        */
@@ -850,14 +924,58 @@
     /* Find the corresponding parameter of the function being called */
     param_name = fp_iterator.search(call_param_name);
     if(param_name == NULL) {
-      STAGE3_ERROR(call_param_name, call_param_name, "Invalid parameter in function/FB call.");
+      if (error_count != NULL) (*error_count)++;
+      else STAGE3_ERROR(call_param_name, call_param_name, "Invalid parameter in function/FB call.");
     } else {
       /* Get the parameter type */
       param_type = base_type(fp_iterator.param_type());
       /* If the declared parameter and the parameter from the function call have the same type */
-      if(!is_valid_assignment(param_type, call_param_type)) STAGE3_ERROR(call_param_name, call_param_value, "Type mismatch function/FB call parameter.");
+      if(!is_valid_assignment(param_type, call_param_type)) {
+        if (error_count != NULL) (*error_count)++;
+        else STAGE3_ERROR(call_param_name, call_param_value, "Type mismatch function/FB call parameter.");
+      }
+      if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
+        extensible_parameter_highest_index = fp_iterator.extensible_param_index();
+        extensible_parameter_name = param_name;
+      }
     }
   }
+  
+  /* In the case of a call to an extensible function, we store the highest index 
+   * of the extensible parameters this particular call uses, in the symbol_c object
+   * of the function call itself!
+   * In calls to non-extensible functions, this value will be set to -1.
+   * This information is later used in stage4 to correctly generate the
+   * output code.
+   */
+  int extensible_param_count = -1;
+  if (extensible_parameter_highest_index >=0) /* if call to extensible function */
+    extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index();
+  il_formal_funct_call_c *il_formal_funct_call = dynamic_cast<il_formal_funct_call_c *>(f_call);
+  function_invocation_c  *function_invocation  = dynamic_cast<function_invocation_c  *>(f_call);
+  if      (il_formal_funct_call != NULL) il_formal_funct_call->extensible_param_count = extensible_param_count;
+  else if (function_invocation  != NULL) function_invocation->extensible_param_count  = extensible_param_count;
+//   else ERROR;  /* this function is also called by Function Blocks, so this is not an error! */
+
+  /* We have iterated through all the formal parameters of the function call,
+   * and everything seems fine. 
+   * If the function being called in an extensible function, we now check
+   * whether the extensible paramters in the formal invocation do not skip
+   * any indexes...
+   *
+   * f(in1:=0, in2:=0, in4:=0) --> ERROR!!
+   */
+  if (extensible_parameter_highest_index >=0) { /* if call to extensible function */
+    for (int i=fp_iterator.first_extensible_param_index(); i < extensible_parameter_highest_index; i++) {
+      char tmp[256];
+      if (snprintf(tmp, 256, "%s%d", extensible_parameter_name->value, i) >= 256) ERROR;
+      if (fcp_iterator.search_f(tmp) == NULL) {
+        /* error in invocation of extensible function */
+        if (error_count != NULL) (*error_count)++;
+        else STAGE3_ERROR(f_call, f_call, "Missing extensible parameters in call to extensible function.");
+      }  
+    }    
+  }  
 }
 
 
@@ -990,58 +1108,51 @@
   if (il_error)
     return NULL;
 
+  symbol_c *return_data_type = NULL;
+
   /* First find the declaration of the function being called! */
-  function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
-
-  symbol_c *return_data_type = NULL;
-
-  if (f_decl == function_symtable.end_value()) {
-    function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
-    if (current_function_type == function_none) ERROR;
-    /*  This code is for the functions that the user did not declare and that are
-     * part of the IL or ST languagem (built-in functions).
-     *  For now we won't do the semantics analysis for that kind of functions.
-    */
-    /*  
-    return_data_type = (symbol_c *)search_expression_type->compute_standard_function_default(NULL, symbol);
-    if (NULL == return_data_type) ERROR;
-
-    function_call_param_iterator_c fcp_iterator(symbol);
-
-    int nb_param = 0;
-    if (symbol->il_param_list != NULL)
-      nb_param += ((list_c *)symbol->il_param_list)->n;
-
-    identifier_c en_param_name("EN");*/
-    /* Get the value from EN param */
-    /*symbol_c *EN_param_value = fcp_iterator.search(&en_param_name);
-    if (EN_param_value == NULL)
-      EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c()));
-    else
-      nb_param --;
-    ADD_PARAM_LIST(EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in)
-
-    identifier_c eno_param_name("EN0");*/
-    /* Get the value from ENO param */
-    /*symbol_c *ENO_param_value = fcp_iterator.search(&eno_param_name);
-    if (ENO_param_value != NULL)
-      nb_param --;
-    ADD_PARAM_LIST(ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
+  function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
+  function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
+  if (lower == function_symtable.end()) ERROR;
+
+  int error_count = 0; 
+  int *error_count_ptr = NULL;
+
+  function_symtable_t::iterator second = lower;
+  second++;
+  if (second != upper) 
+    /* This is a call to an overloaded function... */  
+    error_count_ptr = &error_count;
+
+  for(; lower != upper; lower++) {
+    function_declaration_c *f_decl = function_symtable.get_value(lower);
     
-    #include "st_code_gen.c"
-    */
-  } else {
-    /* determine the base data type returned by the function being called... */
-    return_data_type = base_type(f_decl->type_name);
-    /* If the following occurs, then we must have some big bug in the syntax parser (stage 2)... */
-    if (NULL == return_data_type) ERROR;
-
-    /* check semantics of data passed in the function call... */
-    check_nonformal_call(symbol, f_decl, true);
-
-    /* set the new ddata type of the default variable for the following verifications... */
-    il_default_variable_type = return_data_type;
-  }
+    check_nonformal_call(symbol, f_decl, true, error_count_ptr);
+    
+    if (0 == error_count) {
+      /* Either: 
+       * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!)  
+       * (ii) we have a call to an overloaded function, with no errors!
+       */
+      
+      /* Store the pointer to the declaration of the function being called.
+       * This data will be used by stage 4 to call the correct function.
+       * Mostly needed to disambiguate overloaded functions...
+       * See comments in absyntax.def for more details
+       */
+      symbol->called_function_declaration = f_decl;
+      /* determine the base data type returned by the function being called... */
+      return_data_type = base_type(f_decl->type_name);
+      /* If the following occurs, then we must have some big bug in the syntax parser (stage 2)... */
+      if (NULL == return_data_type) ERROR;
+      /* set the new data type of the default variable for the following verifications... */
+      il_default_variable_type = return_data_type;
+      return NULL;
+    }
+  }
+
+  /* No compatible function was found for this function call */
+  STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
   return NULL;
 }
 
@@ -1161,58 +1272,55 @@
   if (il_error)
     return NULL;
 
-  function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
-
   symbol_c *return_data_type = NULL;
-
-  if (f_decl == function_symtable.end_value()) {
+  function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
+  function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
+  
+  if (lower == function_symtable.end()) {
     function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
     if (current_function_type == function_none) ERROR;
-    
-    /*  This code is for the functions that the user did not declare and that are
-     * part of the IL or ST languagem (built-in functions).
-     *  For now we won't do the semantics analysis for that kind of functions.
-    */
-    #if 0
-    return_data_type = (symbol_c *)search_expression_type->compute_standard_function_default(NULL, symbol);
-    if (NULL == return_data_type) ERROR;
-    
-    function_call_param_iterator_c fcp_iterator(symbol);
-    
-    int nb_param = 0;
-    if (symbol->il_param_list != NULL)
-      nb_param += ((list_c *)symbol->il_param_list)->n;
-    
-    identifier_c en_param_name("EN");
-    /* Get the value from EN param */
-    symbol_c *EN_param_value = fcp_iterator.search(&en_param_name);
-    if (EN_param_value == NULL)
-      EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c()));
-    else
-      nb_param --;
-    ADD_PARAM_LIST(EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in)
-    
-    identifier_c eno_param_name("EN0");
-    /* Get the value from ENO param */
-    symbol_c *ENO_param_value = fcp_iterator.search(&eno_param_name);
-    if (ENO_param_value != NULL)
-      nb_param --;
-    ADD_PARAM_LIST(ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
-    
-    #include "st_code_gen.c"
-    #endif
-  } else {
-    /* determine the base data type returned by the function being called... */
-    return_data_type = base_type(f_decl->type_name);
-    /* the following should never occur. If it does, then we have a bug in the syntax parser (stage 2)... */
-    if (NULL == return_data_type) ERROR;
-
+    return NULL;
+  }
+
+  int error_count = 0; 
+  int *error_count_ptr = NULL;
+
+  function_symtable_t::iterator second = lower;
+  second++;
+  if (second != upper) 
+    /* This is a call to an overloaded function... */  
+    error_count_ptr = &error_count;
+
+  for(; lower != upper; lower++) {
+    function_declaration_c *f_decl = function_symtable.get_value(lower);
+  
     /* check semantics of data passed in the function call... */
-    check_formal_call(symbol, f_decl);
-
-    /* the data type of the data returned by the function, and stored in the il default variable... */
-    il_default_variable_type = return_data_type;
-  }
+    check_formal_call(symbol, f_decl, error_count_ptr);
+
+    if (0 == error_count) {
+      /* Either: 
+       * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!)  
+       * (ii) we have a call to an overloaded function, with no errors!
+       */
+      
+      /* Store the pointer to the declaration of the function being called.
+       * This data will be used by stage 4 to call the correct function.
+       * Mostly needed to disambiguate overloaded functions...
+       * See comments in absyntax.def for more details
+       */
+      symbol->called_function_declaration = f_decl;
+      /* determine the base data type returned by the function being called... */
+      return_data_type = base_type(f_decl->type_name);
+      /* the following should never occur. If it does, then we have a bug in the syntax parser (stage 2)... */
+      if (NULL == return_data_type) ERROR;
+      /* the data type of the data returned by the function, and stored in the il default variable... */
+      il_default_variable_type = return_data_type;
+      return NULL;
+    }  
+  }
+  
+  /* No compatible function was found for this function call */
+  STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
   return NULL;
 }
 
@@ -1961,22 +2069,52 @@
 
 
 void *visit_expression_type_c::visit(function_invocation_c *symbol) {
-  function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
-  if (f_decl == function_symtable.end_value()) {
-    /* TODO: the following code is for standard library functions. We do not yet support this... */
-    void *res = compute_standard_function_default(symbol);
-    if (res != NULL) return res;
-    ERROR;
-  }
-
-  /* now check the semantics of the function call... */
-  /* If the syntax parser is working correctly, exactly one of the 
-   * following two symbols will be NULL, while the other is != NULL.
-   */
-  if (symbol->   formal_param_list != NULL) check_formal_call   (symbol, f_decl);
-  if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, f_decl);
-
-  return base_type(f_decl->type_name);
+  function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
+  function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
+  if (lower == function_symtable.end()) ERROR;
+
+  function_symtable_t::iterator second = lower;
+  second++;
+  if (second == upper) {
+    /* call to a function that is not overloaded. */	  
+    /* now check the semantics of the function call... */
+    /* If the syntax parser is working correctly, exactly one of the 
+     * following two symbols will be NULL, while the other is != NULL.
+     */
+    function_declaration_c *f_decl = function_symtable.get_value(lower);
+    if (symbol->   formal_param_list != NULL) check_formal_call   (symbol, f_decl);
+    if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, f_decl);
+    /* Store the pointer to the declaration of the function being called.
+     * This data will be used by stage 4 to call the correct function.
+     * Mostly needed to disambiguate overloaded functions...
+     * See comments in absyntax.def for more details
+     */
+    symbol->called_function_declaration = f_decl;
+    return base_type(f_decl->type_name);
+  }  
+
+  /* This is a call to an overloaded function... */
+  if (debug) printf("visit_expression_type_c::visit(function_invocation_c *symbol): FOUND CALL TO OVERLOADED FUNCTION!!\n");
+  for(; lower != upper; lower++) {
+    if (debug) printf("visit_expression_type_c::visit(function_invocation_c *symbol): FOUND CALL TO OVERLOADED FUNCTION!! iterating...\n");
+    int error_count = 0; 
+    function_declaration_c *f_decl = function_symtable.get_value(lower);
+    if (symbol->   formal_param_list != NULL) check_formal_call   (symbol, f_decl, &error_count);
+    if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, f_decl, false, &error_count);
+    if (0 == error_count) {
+      /* Store the pointer to the declaration of the function being called.
+       * This data will be used by stage 4 to call the correct function.
+       * Mostly needed to disambiguate overloaded functions...
+       * See comments in absyntax.def for more details
+       */
+      symbol->called_function_declaration = f_decl;
+      return base_type(f_decl->type_name);
+    }
+  }
+
+  /* No compatible function was found for this function call */
+  STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
+  return NULL;
 }
 
 /********************/
--- a/stage3/visit_expression_type.hh	Mon Jul 11 09:47:27 2011 +0100
+++ b/stage3/visit_expression_type.hh	Fri Jul 29 16:03:28 2011 +0100
@@ -190,10 +190,18 @@
     void check_il_fbcall(symbol_c *symbol, const char *input_operator);
     /* check the semantics of a FB or Function non-formal call */
     /* e.g. foo(1, 2, 3, 4);  */
-    void check_nonformal_call(symbol_c *f_call, symbol_c *f_decl, bool use_il_defvar = false);
+    /* If error_count pointer is NULL, print out error messages.
+     * If error_count pointer is != NULL, do not print out error messages, but tally up
+     * how many errors were found.
+     */
+    void check_nonformal_call(symbol_c *f_call, symbol_c *f_decl, bool use_il_defvar = false, int *error_count = NULL);
     /* check the semantics of a FB or Function formal call */
     /* e.g. foo(IN1 := 1, OUT1 =>x, EN := true);  */
-    void check_formal_call(symbol_c *f_call, symbol_c *f_decl);
+    /* If error_count pointer is NULL, print out error messages.
+     * If error_count pointer is != NULL, do not print out error messages, but tally up
+     * how many errors were found.
+     */
+    void check_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count = NULL);
 
 
     void *compute_standard_function_default(function_invocation_c *st_symbol, il_formal_funct_call_c *il_symbol);
--- a/stage4/generate_c/generate_c.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/stage4/generate_c/generate_c.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -158,12 +158,174 @@
 /***********************************************************************/
 /***********************************************************************/
 
+
+#include "generate_c.hh"
+
+
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+
+/* A helper class that prints out the identifiers for function calls to overloaded functions */
+/* Given a function declaration of the function being called, it 
+ * will simply print out the returned data type,
+ * followed by the data types of all input, output, and in_out parameters.
+ *   for e.g.; 
+ *     SIN( REAL) : REAL      -> prints out ->  REAL__REAL
+ *     LEN( STRING) : INT     -> prints out ->  INT__STRING
+ *     MUL(TIME, INT) : TIME  -> prints out ->  TIME__TIME__INT
+ */
+class print_function_parameter_data_types_c: public generate_c_base_c {
+  private:
+    symbol_c *current_type;
+    bool_type_name_c tmp_bool;
+
+    void print_list(symbol_c *var_list, symbol_c *data_type) { 
+      if (data_type != NULL) {
+        /* print out the data type once for every variable! */
+        list_c *list = dynamic_cast<list_c *>(var_list);
+        if (list == NULL) ERROR;  
+        for (int i=0; i < list->n; i++) {
+          s4o.print("__");
+          data_type->accept(*this);
+        }  
+      }
+    }
+    
+  public:
+    print_function_parameter_data_types_c(stage4out_c *s4o_ptr): 
+      generate_c_base_c(s4o_ptr)
+      {current_type = NULL;}
+
+    /**************************************/
+    /* B.1.5 - Program organization units */
+    /**************************************/
+    /***********************/
+    /* B 1.5.1 - Functions */
+    /***********************/
+    /*   FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
+    /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
+    void *visit(function_declaration_c *symbol) {
+      symbol->type_name->accept(*this); /* return type */
+      symbol->var_declarations_list->accept(*this);
+      return NULL;
+    }
+
+    /* already handled by iterator base class (note that generate_c_base_c inherits from iterator_c) */
+    //void *visit(var_declarations_list_c *symbol) {// iterate through list}
+    
+    /* already handled by iterator base class (note that generate_c_base_c inherits from iterator_c) */
+    //void *visit(input_declarations_c *symbol) {// iterate through list}
+        
+    /* already handled by iterator base class (note that generate_c_base_c inherits from iterator_c) */
+    //void *visit(input_declaration_list_c *symbol) {// iterate through list}
+
+    void *visit(edge_declaration_c *symbol) {
+      current_type = &tmp_bool; 
+      symbol->var1_list->accept(*this);
+      current_type = NULL; 
+      return NULL;
+    }
+    
+    /* We do NOT print out EN and ENO parameters! */
+    void *visit(en_param_declaration_c *symbol) {return NULL;}
+
+    /* already handled by iterator base class (note that generate_c_base_c inherits from iterator_c) */
+    //void *visit(output_declarations_c *symbol) {// iterate through list}    
+    
+    /* already handled by iterator base class (note that generate_c_base_c inherits from iterator_c) */
+    //void *visit(var_init_decl_list_c *symbol) {// iterate through list}
+
+    void *visit(simple_spec_init_c *symbol) {
+      /* return the data type */
+      return symbol->simple_specification; 
+    }
+
+    /* currently we do not support data types defined in the declaration itself */
+    /* For now, sugest the user define a TYPE .. END_TYPE */
+    /* NOTE: although this class may also sometimes point to a previously_declared_subrange_type_name
+     * we don't need this for now, so it is easier to just skip it allocation
+     */
+    void *visit(subrange_spec_init_c *symbol) {return NULL;}
+
+    /* currently we do not support data types defined in the declaration itself */
+    /* For now, sugest the user define a TYPE .. END_TYPE */
+    /* NOTE: although this class may also sometimes point to a previously_declared_enumerated_type_name
+     * we don't need this for now, so it is easier to just skip it allocation
+     */
+    void *visit(enumerated_spec_init_c *symbol) {return NULL;}
+
+    /* currently we do not support data types defined in the declaration itself */
+    /* For now, sugest the user define a TYPE .. END_TYPE */
+    /* NOTE: although this class may also sometimes point to a previously_declared_array_type_name
+     * we don't need this for now, so it is easier to just skip it allocation
+     */
+    void *visit(array_var_init_decl_c *symbol) {return NULL;}
+
+    /* currently we do not support data types defined in the declaration itself */
+    /* For now, sugest the user define a TYPE .. END_TYPE */
+    /* NOTE: although this class may also sometimes point to a previously_declared_structured_type_name
+     * we don't need this for now, so it is easier to just skip it allocation
+     */
+    void *visit(structured_var_init_decl_c *symbol) {return NULL;}
+
+    /* We do NOT print out EN and ENO parameters! */
+    void *visit(eno_param_declaration_c *symbol) {return NULL;}
+
+    /* already handled by iterator base class (note that generate_c_base_c inherits from iterator_c) */
+    //void *visit(input_output_declarations_c *symbol) {// iterate through list}    
+
+    /* already handled by iterator base class (note that generate_c_base_c inherits from iterator_c) */
+    //void *visit(var_declaration_list_c *symbol) {iterate through list}
+
+    void *visit(fb_name_decl_c *symbol) {
+      print_list(symbol->fb_name_list, symbol->function_block_type_name); 
+      return NULL;
+    }
+
+    void *visit(var1_init_decl_c *symbol) {
+      print_list(symbol->var1_list, (symbol_c *)symbol->spec_init->accept(*this));
+      return NULL;
+    }
+
+    /* currently we do not support data types defined in the declaration itself */
+    /* For now, sugest the user define a TYPE .. END_TYPE */
+    void *visit(array_var_declaration_c *symbol) {return NULL;}
+
+    void *visit(structured_var_declaration_c *symbol) {
+      current_type = symbol->structure_type_name; 
+      symbol->var1_list->accept(*this);
+      current_type = NULL; 
+      return NULL;
+    }
+
+    /* currently we do not support data types defined in the declaration itself */
+    /* For now, sugest the user define a TYPE .. END_TYPE */
+    /* Note that this class is used for fixed length strings...
+     *   STRING [ 42 ]
+     */
+    void *visit(single_byte_string_var_declaration_c *symbol) {return NULL;}
+
+    /* currently we do not support data types defined in the declaration itself */
+    /* For now, sugest the user define a TYPE .. END_TYPE */
+    /* Note that this class is used for fixed length strings...
+     *   WSTRING [ 42 ]
+     */
+    void *visit(double_byte_string_var_declaration_c *symbol) {return NULL;}
+};
+    
+
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+
+
 #include "generate_c_st.cc"
 #include "generate_c_il.cc"
 #include "generate_c_inlinefcall.cc"
 
-#include "generate_c.hh"
-
 /***********************************************************************/
 /***********************************************************************/
 /***********************************************************************/
--- a/stage4/generate_c/generate_c_il.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/stage4/generate_c/generate_c_il.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -789,102 +789,122 @@
   
   function_call_param_iterator_c function_call_param_iterator(symbol);
 
-  function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
-  if (f_decl == function_symtable.end_value()) {
-    function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
-    if (current_function_type == function_none) ERROR;
+  function_declaration_c *f_decl = (function_declaration_c *)symbol->called_function_declaration;
+  if (f_decl == NULL) ERROR;
+
+  /* determine the base data type returned by the function being called... */
+  search_base_type_c search_base_type;
+  return_data_type = (symbol_c *)f_decl->type_name->accept(search_base_type);
+  if (NULL == return_data_type) ERROR;
+
+  function_name = symbol->function_name;
+  
+  /* loop through each function parameter, find the value we should pass
+   * to it, and then output the c equivalent...
+   */
+  function_param_iterator_c fp_iterator(f_decl);
+  identifier_c *param_name;
+    /* flag to remember whether we have already used the value stored in the default variable to pass to the first parameter */
+  bool used_defvar = false; 
+    /* flag to cirreclty handle calls to extensible standard functions (i.e. functions with variable number of input parameters) */
+  bool found_first_extensible_parameter = false;  
+  for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
+    if (fp_iterator.is_extensible_param() && (!found_first_extensible_parameter)) {
+      /* We are calling an extensible function. Before passing the extensible
+       * parameters, we must add a dummy paramater value to tell the called
+       * function how many extensible parameters we will be passing.
+       *
+       * Note that stage 3 has already determined the number of extensible
+       * paramters, and stored that info in the abstract syntax tree. We simply
+       * re-use that value.
+       */
+      /* NOTE: we are not freeing the malloc'd memory. This is not really a bug.
+       *       Since we are writing a compiler, which runs to termination quickly,
+       *       we can consider this as just memory required for the compilation process
+       *       that will be free'd when the program terminates.
+       */
+      char *tmp = (char *)malloc(32); /* enough space for a call with 10^31 (larger than 2^64) input parameters! */
+      if (tmp == NULL) ERROR;
+      int res = snprintf(tmp, 32, "%d", symbol->extensible_param_count);
+      if ((res >= 32) || (res < 0)) ERROR;
+      identifier_c *param_value = new identifier_c(tmp);
+      uint_type_name_c *param_type  = new uint_type_name_c();
+      identifier_c *param_name = new identifier_c("");
+      ADD_PARAM_LIST(param_name, param_value, param_type, function_param_iterator_c::direction_in)
+      found_first_extensible_parameter = true;
+    }
     
-    return_data_type = (symbol_c *)search_expression_type->compute_standard_function_il(symbol, param_data_type);
-    if (NULL == return_data_type) ERROR;
+    symbol_c *param_type = fp_iterator.param_type();
+    if (param_type == NULL) ERROR;
     
-    symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN"));
-    /* Add the value from EN param */
-    ADD_PARAM_LIST(en_param_name,
-                   (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c())),
-                   (symbol_c*)(new bool_type_name_c()), 
-                   function_param_iterator_c::direction_in)
+    function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
     
-    symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO"));
-    /* Add the value from ENO param */
-    ADD_PARAM_LIST(eno_param_name, NULL, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
+    symbol_c *param_value = NULL;
+
+    /* Get the value from a foo(<param_name> = <param_value>) style call */
+    /* NOTE: Since the class il_function_call_c only references a non.formal function call,
+     * the following line of code is not required in this case. However, it doesn't
+     * harm to leave it in, as in the case of a non-formal syntax function call,
+     * it will always return NULL.
+     * We leave it in in case we later decide to merge this part of the code together
+     * with the function calling code in generate_c_st_c, which does require
+     * the following line...
+     */
+    if (param_value == NULL)
+      param_value = function_call_param_iterator.search_f(param_name);
+
+    /* if it is the first parameter in a non-formal function call (which is the
+     * case being handled!), semantics specifies that we should
+     * get the value off the IL default variable!
+     *
+     * However, if the parameter is an implicitly defined EN or ENO parameter, we should not
+     * use the default variable as a source of data to pass to those parameters!
+     */
+    if ((param_value == NULL) &&  (!used_defvar) && !fp_iterator.is_en_eno_param_implicit()) {
+      param_value = &this->default_variable_name;
+      used_defvar = true;
+    }
+
+    /* Get the value from a foo(<param_value>) style call */
+    if ((param_value == NULL) && !fp_iterator.is_en_eno_param_implicit()) {
+      param_value = function_call_param_iterator.next_nf();
+    }
     
-    int nb_param = 1;
-    if (symbol->il_operand_list != NULL)
-      nb_param += ((list_c *)symbol->il_operand_list)->n;
-
-    #include "il_code_gen.c"
-
-  }
-  else {
-    /* determine the base data type returned by the function being called... */
-    search_base_type_c search_base_type;
-    return_data_type = (symbol_c *)f_decl->type_name->accept(search_base_type);
-    if (NULL == return_data_type) ERROR;
-  
-    function_name = symbol->function_name;
+    /* if no more parameter values in function call, and the current parameter
+     * of the function declaration is an extensible parameter, we
+     * have reached the end, and should simply jump out of the for loop.
+     */
+    if ((param_value == NULL) && (fp_iterator.is_extensible_param())) {
+      break;
+    }
     
-    /* loop through each function parameter, find the value we should pass
-     * to it, and then output the c equivalent...
-     */
-  
-    function_param_iterator_c fp_iterator(f_decl);
-    identifier_c *param_name;
-    for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
-      symbol_c *param_type = fp_iterator.param_type();
-      if (param_type == NULL) ERROR;
-      
-      function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
-      
-      symbol_c *param_value = NULL;
-  
-      /* if it is the first parameter, semantics specifies that we should
-       * get the value off the IL default variable!
-       */
-     if (1 == i)
-       param_value = &this->default_variable_name;
-  
-      /* Get the value from a foo(<param_name> = <param_value>) style call */
-      /* NOTE: the following line of code is not required in this case, but it doesn't
-       * harm to leave it in, as in the case of a non-formal syntax function call,
-       * it will always return NULL.
-       * We leave it in in case we later decide to merge this part of the code together
-       * with the function calling code in generate_c_st_c, which does require
-       * the following line...
-       */
-      if (param_value == NULL)
-        param_value = function_call_param_iterator.search_f(param_name);
-  
-      /* Get the value from a foo(<param_value>) style call */
-      if (param_value == NULL) {
-        param_value = function_call_param_iterator.next_nf();
-        if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR;
-      }
-      
-      if (param_value == NULL && param_direction == function_param_iterator_c::direction_in) {
-        /* No value given for parameter, so we must use the default... */
-        /* First check whether default value specified in function declaration...*/
-        param_value = fp_iterator.default_value();
-      }
-      
-      ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction())
-    } /* for(...) */
-  }
-  
+    if ((param_value == NULL) && (param_direction == function_param_iterator_c::direction_in)) {
+      /* No value given for parameter, so we must use the default... */
+      /* First check whether default value specified in function declaration...*/
+      param_value = fp_iterator.default_value();
+    }
+    
+    ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction())
+  } /* for(...) */
+
   if (function_call_param_iterator.next_nf() != NULL) ERROR;
 
   bool has_output_params = false;
 
   if (!this->is_variable_prefix_null()) {
     PARAM_LIST_ITERATOR() {
-	  if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
-		   PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
-		  PARAM_VALUE != NULL) {
-	    if (!has_output_params) {
-		  has_output_params = true;
-		}
-	  }
-    }
-  }
+      if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
+           PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
+           PARAM_VALUE != NULL) {
+        has_output_params = true;
+      }
+    }
+  }
+
+  /* Check whether we are calling an overloaded function! */
+  /* (fdecl_mutiplicity==2)  => calling overloaded function */
+  int fdecl_mutiplicity =  function_symtable.multiplicity(symbol->function_name);
+  if (fdecl_mutiplicity == 0) ERROR;
 
   default_variable_name.current_type = return_data_type;
   this->default_variable_name.accept(*this);
@@ -897,21 +917,34 @@
     s4o.print(")");
   }
   if (function_type_suffix != NULL) {
-  	function_type_suffix = search_expression_type->default_literal_type(function_type_prefix);
+    function_type_suffix = search_expression_type->default_literal_type(function_type_prefix);
   }
   if (has_output_params) {
-  	fcall_number++;
-  	s4o.print("__");
+    fcall_number++;
+    s4o.print("__");
     fbname->accept(*this);
     s4o.print("_");
     function_name->accept(*this);
+    if (fdecl_mutiplicity == 2) {
+      /* function being called is overloaded! */
+      s4o.print("__");
+      print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+      f_decl->accept(overloaded_func_suf);
+    }
     s4o.print_integer(fcall_number);
   }
   else {
-    if (function_name != NULL)
-	  function_name->accept(*this);
+    if (function_name != NULL) {
+          function_name->accept(*this);
+          if (fdecl_mutiplicity == 2) {
+            /* function being called is overloaded! */
+            s4o.print("__");
+            print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+            f_decl->accept(overloaded_func_suf);
+          }
+    }	  
     if (function_type_suffix != NULL)
-	  function_type_suffix->accept(*this);
+      function_type_suffix->accept(*this);
   }
   s4o.print("(");
   s4o.indent_right();
@@ -923,8 +956,8 @@
     
     switch (PARAM_DIRECTION) {
       case function_param_iterator_c::direction_in:
-    	if (nb_param > 0)
-    	  s4o.print(",\n"+s4o.indent_spaces);
+        if (nb_param > 0)
+          s4o.print(",\n"+s4o.indent_spaces);
         if (param_value == NULL) {
           /* If not, get the default value of this variable's type */
           param_value = (symbol_c *)current_param_type->accept(*type_initial_value_c::instance());
@@ -943,18 +976,18 @@
         break;
       case function_param_iterator_c::direction_out:
       case function_param_iterator_c::direction_inout:
-    	if (!has_output_params) {
+        if (!has_output_params) {
           if (nb_param > 0)
-    		s4o.print(",\n"+s4o.indent_spaces);
-		  if (param_value == NULL) {
-		    s4o.print("NULL");
-		  } else {
-		    wanted_variablegeneration = fparam_output_vg;
-		    param_value->accept(*this);
-		    wanted_variablegeneration = expression_vg;
-		  }
-		  nb_param++;
-    	}
+            s4o.print(",\n"+s4o.indent_spaces);
+            if (param_value == NULL) {
+              s4o.print("NULL");
+            } else {
+              wanted_variablegeneration = fparam_output_vg;
+              param_value->accept(*this);
+              wanted_variablegeneration = expression_vg;
+            }
+          nb_param++;
+        }
         break;
       case function_param_iterator_c::direction_extref:
         /* TODO! */
@@ -964,7 +997,7 @@
   }
   if (has_output_params) {
     if (nb_param > 0)
-	  s4o.print(",\n"+s4o.indent_spaces);
+      s4o.print(",\n"+s4o.indent_spaces);
     s4o.print(FB_FUNCTION_PARAM);
   }
   
@@ -1072,7 +1105,10 @@
     symbol_c *param_value = function_call_param_iterator.search_f(param_name);
 
     /* Get the value from a foo(<param_value>) style call */
-    if (param_value == NULL)
+    /* When using the informal invocation style, user can not pass values to EN or ENO parameters if these
+     * were implicitly defined!
+     */
+    if ((param_value == NULL) && !fp_iterator.is_en_eno_param_implicit())
       param_value = function_call_param_iterator.next_nf();
 
     symbol_c *param_type = fp_iterator.param_type();
@@ -1116,7 +1152,10 @@
     symbol_c *param_value = function_call_param_iterator.search_f(param_name);
 
     /* Get the value from a foo(<param_value>) style call */
-    if (param_value == NULL)
+    /* When using the informal invocation style, user can not pass values to EN or ENO parameters if these
+     * were implicitly defined!
+     */
+    if ((param_value == NULL) && !fp_iterator.is_en_eno_param_implicit())
       param_value = function_call_param_iterator.next_nf();
 
     /* now output the value assignment */
@@ -1158,85 +1197,100 @@
 
   function_call_param_iterator_c function_call_param_iterator(symbol);
 
-  function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
-  if (f_decl == function_symtable.end_value()) {
-    function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
-    if (current_function_type == function_none) ERROR;
+  function_declaration_c *f_decl = (function_declaration_c *)symbol->called_function_declaration;
+  if (f_decl == NULL) ERROR;
+        
+  /* determine the base data type returned by the function being called... */
+  search_base_type_c search_base_type;
+  return_data_type = (symbol_c *)f_decl->type_name->accept(search_base_type);
+  if (NULL == return_data_type) ERROR;
+  
+  function_name = symbol->function_name;
+
+  /* loop through each function parameter, find the value we should pass
+   * to it, and then output the c equivalent...
+   */
+  function_param_iterator_c fp_iterator(f_decl);
+  identifier_c *param_name;
+
+    /* flag to cirreclty handle calls to extensible standard functions (i.e. functions with variable number of input parameters) */
+  bool found_first_extensible_parameter = false;
+  for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
+    if (fp_iterator.is_extensible_param() && (!found_first_extensible_parameter)) {
+      /* We are calling an extensible function. Before passing the extensible
+       * parameters, we must add a dummy paramater value to tell the called
+       * function how many extensible parameters we will be passing.
+       *
+       * Note that stage 3 has already determined the number of extensible
+       * paramters, and stored that info in the abstract syntax tree. We simply
+       * re-use that value.
+       */
+      /* NOTE: we are not freeing the malloc'd memory. This is not really a bug.
+       *       Since we are writing a compiler, which runs to termination quickly,
+       *       we can consider this as just memory required for the compilation process
+       *       that will be free'd when the program terminates.
+       */
+      char *tmp = (char *)malloc(32); /* enough space for a call with 10^31 (larger than 2^64) input parameters! */
+      if (tmp == NULL) ERROR;
+      int res = snprintf(tmp, 32, "%d", symbol->extensible_param_count);
+      if ((res >= 32) || (res < 0)) ERROR;
+      identifier_c *param_value = new identifier_c(tmp);
+      uint_type_name_c *param_type  = new uint_type_name_c();
+      identifier_c *param_name = new identifier_c("");
+      ADD_PARAM_LIST(param_name, param_value, param_type, function_param_iterator_c::direction_in)
+      found_first_extensible_parameter = true;
+    }
     
-    return_data_type = (symbol_c *)search_expression_type->compute_standard_function_default(NULL, symbol);
-    if (NULL == return_data_type) ERROR;
+    if (fp_iterator.is_extensible_param()) {      
+      /* since we are handling an extensible parameter, we must add the index to the
+       * parameter name so we can go looking for the value passed to the correct
+       * extended parameter (e.g. IN1, IN2, IN3, IN4, ...)
+       */
+      char *tmp = (char *)malloc(32); /* enough space for a call with 10^31 (larger than 2^64) input parameters! */
+      int res = snprintf(tmp, 32, "%d", fp_iterator.extensible_param_index());
+      if ((res >= 32) || (res < 0)) ERROR;
+      param_name = new identifier_c(strdup2(param_name->value, tmp));
+      if (param_name->value == NULL) ERROR;
+    }
+
+    symbol_c *param_type = fp_iterator.param_type();
+    if (param_type == NULL) ERROR;
+
+    function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
+
+    symbol_c *param_value = NULL;
+
+    /* Get the value from a foo(<param_name> = <param_value>) style call */
+    if (param_value == NULL)
+      param_value = function_call_param_iterator.search_f(param_name);
+
+    /* Get the value from a foo(<param_value>) style call */
+    /* NOTE: the following line of code is not required in this case, but it doesn't
+     * harm to leave it in, as in the case of a formal syntax function call,
+     * it will always return NULL.
+     * We leave it in in case we later decide to merge this part of the code together
+     * with the function calling code in generate_c_st_c, which does require
+     * the following line...
+     */
+    if ((param_value == NULL) && !fp_iterator.is_en_eno_param_implicit()) {
+      param_value = function_call_param_iterator.next_nf();
+    }
     
-    int nb_param = 0;
-    if (symbol->il_param_list != NULL)
-      nb_param += ((list_c *)symbol->il_param_list)->n;
+    /* if no more parameter values in function call, and the current parameter
+     * of the function declaration is an extensible parameter, we
+     * have reached the end, and should simply jump out of the for loop.
+     */
+    if ((param_value == NULL) && (fp_iterator.is_extensible_param())) {
+      break;
+    }
     
-    symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN"));
-    /* Get the value from EN param */
-    symbol_c *EN_param_value = function_call_param_iterator.search_f(en_param_name);
-    if (EN_param_value == NULL)
-      EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c()));
-    else
-      nb_param --;
-    ADD_PARAM_LIST(en_param_name, EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in)
+    if ((param_value == NULL) && (param_direction == function_param_iterator_c::direction_in)) {
+      /* No value given for parameter, so we must use the default... */
+      /* First check whether default value specified in function declaration...*/
+      param_value = fp_iterator.default_value();
+    }
     
-    symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO"));
-    /* Get the value from ENO param */
-    symbol_c *ENO_param_value = function_call_param_iterator.search_f(eno_param_name);
-    if (ENO_param_value != NULL)
-      nb_param --;
-    ADD_PARAM_LIST(eno_param_name, ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
-    
-    #include "st_code_gen.c"
-    
-  }
-  else {
-    /* determine the base data type returned by the function being called... */
-    search_base_type_c search_base_type;
-    return_data_type = (symbol_c *)f_decl->type_name->accept(search_base_type);
-    if (NULL == return_data_type) ERROR;
-    
-    function_name = symbol->function_name;
-  
-    /* loop through each function parameter, find the value we should pass
-     * to it, and then output the c equivalent...
-     */
-  
-    function_param_iterator_c fp_iterator(f_decl);
-    identifier_c *param_name;
-    for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
-      symbol_c *param_type = fp_iterator.param_type();
-      if (param_type == NULL) ERROR;
-  
-      function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
-  
-  
-      symbol_c *param_value = NULL;
-  
-      /* Get the value from a foo(<param_name> = <param_value>) style call */
-      if (param_value == NULL)
-        param_value = function_call_param_iterator.search_f(param_name);
-  
-      /* Get the value from a foo(<param_value>) style call */
-      /* NOTE: the following line of code is not required in this case, but it doesn't
-       * harm to leave it in, as in the case of a formal syntax function call,
-       * it will always return NULL.
-       * We leave it in in case we later decide to merge this part of the code together
-       * with the function calling code in generate_c_st_c, which does require
-       * the following line...
-       */
-      if (param_value == NULL) {
-        param_value = function_call_param_iterator.next_nf();
-        if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR;
-      }
-      
-      if (param_value == NULL) {
-        /* No value given for parameter, so we must use the default... */
-        /* First check whether default value specified in function declaration...*/
-        param_value = fp_iterator.default_value();
-      }
-      
-      ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction())
-    }
+    ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction())
   }
   
   if (function_call_param_iterator.next_nf() != NULL) ERROR;
@@ -1245,15 +1299,21 @@
 
   if (!this->is_variable_prefix_null()) {
     PARAM_LIST_ITERATOR() {
-	  if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
-		   PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
-		  PARAM_VALUE != NULL) {
-	    if (!has_output_params) {
-		  has_output_params = true;
-		}
-	  }
-    }
-  }
+      if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
+           PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
+           PARAM_VALUE != NULL) {
+        has_output_params = true;
+      }
+    }
+  }
+
+  /* Check whether we are calling an overloaded function! */
+  /* (fdecl_mutiplicity==2)  => calling overloaded function */
+  int fdecl_mutiplicity =  function_symtable.multiplicity(symbol->function_name);
+  if (fdecl_mutiplicity == 0) ERROR;
+  if (fdecl_mutiplicity == 1) 
+    /* function being called is NOT overloaded! */
+    f_decl = NULL; 
 
   default_variable_name.current_type = return_data_type;
   this->default_variable_name.accept(*this);
@@ -1265,19 +1325,32 @@
     s4o.print(")");
   }
   if (function_type_suffix != NULL) {
-  	function_type_suffix = search_expression_type->default_literal_type(function_type_prefix);
+    function_type_suffix = search_expression_type->default_literal_type(function_type_prefix);
   }
   if (has_output_params) {
-	fcall_number++;
-	s4o.print("__");
+    fcall_number++;
+    s4o.print("__");
     fbname->accept(*this);
     s4o.print("_");
     function_name->accept(*this);
+    if (fdecl_mutiplicity == 2) {
+      /* function being called is overloaded! */
+      s4o.print("__");
+      print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+      f_decl->accept(overloaded_func_suf);
+    }
     s4o.print_integer(fcall_number);
   }
   else {
-    if (function_name != NULL)
+    if (function_name != NULL) {
       function_name->accept(*this);
+      if (fdecl_mutiplicity == 2) {
+        /* function being called is overloaded! */
+        s4o.print("__");
+        print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+        f_decl->accept(overloaded_func_suf);
+      }
+    }  
     if (function_type_suffix != NULL)
       function_type_suffix->accept(*this);
   }
@@ -1286,14 +1359,13 @@
   
   int nb_param = 0;
   PARAM_LIST_ITERATOR() {
-	symbol_c *param_value = PARAM_VALUE;
-	current_param_type = PARAM_TYPE;
-    
+    symbol_c *param_value = PARAM_VALUE;
+    current_param_type = PARAM_TYPE;
     switch (PARAM_DIRECTION) {
       case function_param_iterator_c::direction_in:
-    	if (nb_param > 0)
-    	  s4o.print(",\n"+s4o.indent_spaces);
-    	if (param_value == NULL) {
+        if (nb_param > 0)
+          s4o.print(",\n"+s4o.indent_spaces);
+        if (param_value == NULL) {
           /* If not, get the default value of this variable's type */
           param_value = (symbol_c *)current_param_type->accept(*type_initial_value_c::instance());
         }
@@ -1307,26 +1379,26 @@
           current_param_type->accept(*this);
         s4o.print(")");
         print_check_function(current_param_type, param_value);
-		nb_param++;
+        nb_param++;
         break;
       case function_param_iterator_c::direction_out:
       case function_param_iterator_c::direction_inout:
-    	if (!has_output_params) {
+        if (!has_output_params) {
           if (nb_param > 0)
-        	s4o.print(",\n"+s4o.indent_spaces);
-		  if (param_value == NULL) {
-		    s4o.print("NULL");
-		  } else {
-		    wanted_variablegeneration = fparam_output_vg;
-		    param_value->accept(*this);
-		    wanted_variablegeneration = expression_vg;
-		  }
-    	}
-	    break;
+            s4o.print(",\n"+s4o.indent_spaces);
+          if (param_value == NULL) {
+            s4o.print("NULL");
+          } else {
+            wanted_variablegeneration = fparam_output_vg;
+            param_value->accept(*this);
+            wanted_variablegeneration = expression_vg;
+          }
+        }
+        break;
       case function_param_iterator_c::direction_extref:
         /* TODO! */
         ERROR;
-	      break;
+        break;
     } /* switch */
   } /* for(...) */
   if (has_output_params) {
@@ -1659,7 +1731,7 @@
 void *visit(ADD_operator_c *symbol)	{
   if (search_expression_type->is_time_type(this->default_variable_name.current_type) &&
       search_expression_type->is_time_type(this->current_operand_type)) {
-    XXX_function("__TIME_ADD", &(this->default_variable_name), this->current_operand);
+    XXX_function("__time_add", &(this->default_variable_name), this->current_operand);
     /* the data type resulting from this operation... */
     this->default_variable_name.current_type = this->current_operand_type;
     return NULL;
@@ -1679,7 +1751,7 @@
 void *visit(SUB_operator_c *symbol)	{
   if (search_expression_type->is_time_type(this->default_variable_name.current_type) &&
       search_expression_type->is_time_type(this->current_operand_type)) {
-    XXX_function("__TIME_SUB", &(this->default_variable_name), this->current_operand);
+    XXX_function("__time_sub", &(this->default_variable_name), this->current_operand);
     /* the data type resulting from this operation... */
     this->default_variable_name.current_type = this->current_operand_type;
     return NULL;
@@ -1699,7 +1771,7 @@
 void *visit(MUL_operator_c *symbol)	{
   if (search_expression_type->is_time_type(this->default_variable_name.current_type) &&
       search_expression_type->is_integer_type(this->current_operand_type)) {
-    XXX_function("__TIME_MUL", &(this->default_variable_name), this->current_operand);
+    XXX_function("__time_mul", &(this->default_variable_name), this->current_operand);
     /* the data type resulting from this operation... */
     return NULL;
   }
@@ -1718,7 +1790,7 @@
 void *visit(DIV_operator_c *symbol)	{
   if (search_expression_type->is_time_type(this->default_variable_name.current_type) &&
       search_expression_type->is_integer_type(this->current_operand_type)) {
-    XXX_function("__TIME_DIV", &(this->default_variable_name), this->current_operand);
+    XXX_function("__time_div", &(this->default_variable_name), this->current_operand);
     /* the data type resulting from this operation... */
     return NULL;
   }
@@ -1748,7 +1820,7 @@
 void *visit(GT_operator_c *symbol)	{
   if (!search_base_type.type_is_enumerated(this->default_variable_name.current_type) &&
       search_expression_type->is_same_type(this->default_variable_name.current_type, this->current_operand_type))
-    return CMP_operator(this->current_operand, "__gt_");
+    return CMP_operator(this->current_operand, "GT_");
   ERROR;
   return NULL;
 }
@@ -1756,14 +1828,14 @@
 void *visit(GE_operator_c *symbol)	{
   if (!search_base_type.type_is_enumerated(this->default_variable_name.current_type) &&
       search_expression_type->is_same_type(this->default_variable_name.current_type, this->current_operand_type))
-    return CMP_operator(this->current_operand, "__ge_");
+    return CMP_operator(this->current_operand, "GE_");
   ERROR;
   return NULL;
 }
 
 void *visit(EQ_operator_c *symbol)	{
   if (search_expression_type->is_same_type(this->default_variable_name.current_type, this->current_operand_type))
-    return CMP_operator(this->current_operand, "__eq_");
+    return CMP_operator(this->current_operand, "EQ_");
   ERROR;
   return NULL;
 }
@@ -1771,7 +1843,7 @@
 void *visit(LT_operator_c *symbol)	{
   if (!search_base_type.type_is_enumerated(this->default_variable_name.current_type) &&
       search_expression_type->is_same_type(this->default_variable_name.current_type, this->current_operand_type))
-    return CMP_operator(this->current_operand, "__lt_");
+    return CMP_operator(this->current_operand, "LT_");
   ERROR;
   return NULL;
 }
@@ -1779,14 +1851,14 @@
 void *visit(LE_operator_c *symbol)	{
   if (!search_base_type.type_is_enumerated(this->default_variable_name.current_type) &&
       search_expression_type->is_same_type(this->default_variable_name.current_type, this->current_operand_type))
-    return CMP_operator(this->current_operand, "__le_");
+    return CMP_operator(this->current_operand, "LE_");
   ERROR;
   return NULL;
 }
 
 void *visit(NE_operator_c *symbol)	{
   if (search_expression_type->is_same_type(this->default_variable_name.current_type, this->current_operand_type))
-    return CMP_operator(this->current_operand, "__ne_");
+    return CMP_operator(this->current_operand, "NE_");
   ERROR;
   return NULL;
 }
--- a/stage4/generate_c/generate_c_inlinefcall.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/stage4/generate_c/generate_c_inlinefcall.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -84,10 +84,13 @@
       }
     }
 
+
+
     void generate_inline(symbol_c *function_name,
             symbol_c *function_type_prefix,
             symbol_c *function_type_suffix,
-            std::list<FUNCTION_PARAM*> param_list) {
+            std::list<FUNCTION_PARAM*> param_list,
+            function_declaration_c *f_decl = NULL) {
             std::list<FUNCTION_PARAM*>::iterator pt;
 
       fcall_number++;
@@ -103,8 +106,13 @@
       fbname->accept(*this);
       s4o.print("_");
       function_name->accept(*this);
+      if (f_decl != NULL) {
+printf("generate_inline(): calling print_function_parameter_data_types_c !!!!!!!!!!!!!!!!!!!!!!\n");
+        print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+        f_decl->accept(overloaded_func_suf);
+      }	
       if (function_type_suffix) {
-    	function_type_suffix->accept(*this);
+        function_type_suffix->accept(*this);
       }
       s4o.print_integer(fcall_number);
       s4o.print("(");
@@ -119,11 +127,11 @@
         }
       }
       fbname->accept(*this);
-	  s4o.print(" *");
-	  s4o.print(FB_FUNCTION_PARAM);
-	  s4o.indent_left();
-	  s4o.print(")\n" + s4o.indent_spaces);
-	  s4o.print("{\n");
+      s4o.print(" *");
+      s4o.print(FB_FUNCTION_PARAM);
+      s4o.indent_left();
+      s4o.print(")\n" + s4o.indent_spaces);
+      s4o.print("{\n");
       s4o.indent_right();
 
       s4o.print(s4o.indent_spaces);
@@ -132,59 +140,63 @@
       s4o.print(INLINE_RESULT_TEMP_VAR);
       s4o.print(";\n");
 
-	  PARAM_LIST_ITERATOR() {
-		if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
-		     PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
-		    PARAM_VALUE != NULL) {
-		  s4o.print(s4o.indent_spaces);
-		  PARAM_TYPE->accept(*this);
+      PARAM_LIST_ITERATOR() {
+        if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
+             PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
+             PARAM_VALUE != NULL) {
+          s4o.print(s4o.indent_spaces);
+          PARAM_TYPE->accept(*this);
           s4o.print(" ");
           s4o.print(TEMP_VAR);
           PARAM_NAME->accept(*this);
           s4o.print(" = ");
           print_check_function(PARAM_TYPE, PARAM_VALUE);
           s4o.print(";\n");
-		}
-	  }
-
-	  s4o.print(s4o.indent_spaces + INLINE_RESULT_TEMP_VAR),
-			  s4o.print(" = ");
-	  function_name->accept(*this);
-	  if (function_type_suffix)
+          }
+        }
+
+      s4o.print(s4o.indent_spaces + INLINE_RESULT_TEMP_VAR),
+      s4o.print(" = ");
+      function_name->accept(*this);
+      if (f_decl != NULL) {
+printf("generate_inline(): calling print_function_parameter_data_types_c !!!!!!!!!!!!!!!!!!!!!!\n");
+        print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+        f_decl->accept(overloaded_func_suf);
+      }
+
+      if (function_type_suffix)
         function_type_suffix->accept(*this);
-	  s4o.print("(");
-	  s4o.indent_right();
-
-	  PARAM_LIST_ITERATOR() {
-		if (pt != param_list.begin())
-		  s4o.print(",\n" + s4o.indent_spaces);
-		if (PARAM_DIRECTION == function_param_iterator_c::direction_in)
-		  PARAM_NAME->accept(*this);
-		else if (PARAM_VALUE != NULL){
+      s4o.print("(");
+      s4o.indent_right();
+
+      PARAM_LIST_ITERATOR() {
+        if (pt != param_list.begin())
+        s4o.print(",\n" + s4o.indent_spaces);
+        if (PARAM_DIRECTION == function_param_iterator_c::direction_in)
+          PARAM_NAME->accept(*this);
+        else if (PARAM_VALUE != NULL){
           s4o.print("&");
           s4o.print(TEMP_VAR);
           PARAM_NAME->accept(*this);
-        }
-		else {
-		  s4o.print("NULL");
-		}
-	  }
-	  s4o.print(");\n");
-	  s4o.indent_left();
-
-	  PARAM_LIST_ITERATOR() {
+        } else {
+          s4o.print("NULL");
+         }
+      }
+      s4o.print(");\n");
+      s4o.indent_left();
+
+      PARAM_LIST_ITERATOR() {
         if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
-        	 PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
-        	PARAM_VALUE != NULL) {
-
+             PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
+             PARAM_VALUE != NULL) {
           s4o.print(s4o.indent_spaces);
           print_setter(PARAM_VALUE, PARAM_TYPE, PARAM_NAME);
           s4o.print(";\n");
-		}
-	  }
-	  s4o.print(s4o.indent_spaces + "return ");
-	  s4o.print(INLINE_RESULT_TEMP_VAR);
-	  s4o.print(";\n");
+        }
+      }
+      s4o.print(s4o.indent_spaces + "return ");
+      s4o.print(INLINE_RESULT_TEMP_VAR);
+      s4o.print(";\n");
 
       s4o.indent_left();
       s4o.print(s4o.indent_spaces + "}\n\n");
@@ -342,7 +354,7 @@
 
     void *visit(il_function_call_c *symbol) {
       symbol_c* function_type_prefix = NULL;
-      symbol_c* function_name = NULL;
+      symbol_c* function_name = NULL;     
       symbol_c* function_type_suffix = NULL;
       DECLARE_PARAM_LIST()
 
@@ -350,86 +362,104 @@
 
       function_call_param_iterator_c function_call_param_iterator(symbol);
 
-      function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
-	  if (f_decl == function_symtable.end_value()) {
-        function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
-        if (current_function_type == function_none) ERROR;
-
-        function_type_prefix = (symbol_c *)search_expression_type->compute_standard_function_il(symbol, param_data_type);
-
-        symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN"));
-        /* Add the value from EN param */
-        ADD_PARAM_LIST(en_param_name,
-                       (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c())),
-                       (symbol_c*)(new bool_type_name_c()),
-                       function_param_iterator_c::direction_in)
-
-        symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO"));
-        /* Add the value from ENO param */
-        ADD_PARAM_LIST(eno_param_name, NULL, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
-
-        int nb_param = 1;
-        if (symbol->il_operand_list != NULL)
-          nb_param += ((list_c *)symbol->il_operand_list)->n;
-
-        #include "il_code_gen.c"
-
-      }
-	  else {
-		function_name = symbol->function_name;
-
-		/* determine the base data type returned by the function being called... */
-		search_base_type_c search_base_type;
-		function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
-
-		/* loop through each function parameter, find the value we should pass
-		 * to it, and then output the c equivalent...
-		 */
-
-		function_param_iterator_c fp_iterator(f_decl);
-		identifier_c *param_name;
-		for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
-		  symbol_c *param_type = fp_iterator.param_type();
-		  if (param_type == NULL) ERROR;
-
-		  function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
-
-		  symbol_c *param_value = NULL;
-
-		  /* if it is the first parameter, semantics specifies that we should
-		   * get the value off the IL default variable!
-		   */
-		  if (1 == i)
-		    param_value = &this->default_variable_name;
-
-		  /* Get the value from a foo(<param_name> = <param_value>) style call */
-		  /* NOTE: the following line of code is not required in this case, but it doesn't
-		   * harm to leave it in, as in the case of a non-formal syntax function call,
-		   * it will always return NULL.
-		   * We leave it in in case we later decide to merge this part of the code together
-		   * with the function calling code in generate_c_st_c, which does require
-		   * the following line...
-		   */
-		  if (param_value == NULL)
-			param_value = function_call_param_iterator.search_f(param_name);
-
-		  /* Get the value from a foo(<param_value>) style call */
-          if (param_value == NULL) {
-            param_value = function_call_param_iterator.next_nf();
-            if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR;
-          }
-
-		  if (param_value == NULL && param_direction == function_param_iterator_c::direction_in) {
-			/* No value given for parameter, so we must use the default... */
-			/* First check whether default value specified in function declaration...*/
-			param_value = fp_iterator.default_value();
-		  }
-
-		  ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction())
-		} /* for(...) */
-	  }
-
-	  if (function_call_param_iterator.next_nf() != NULL) ERROR;
+      function_declaration_c *f_decl = (function_declaration_c *)symbol->called_function_declaration;
+      if (f_decl == NULL) ERROR;
+      
+      /* determine the base data type returned by the function being called... */
+      search_base_type_c search_base_type;
+      function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
+      
+      function_name = symbol->function_name;      
+      
+      /* loop through each function parameter, find the value we should pass
+       * to it, and then output the c equivalent...
+       */
+      
+      function_param_iterator_c fp_iterator(f_decl);
+      identifier_c *param_name;
+        /* flag to remember whether we have already used the value stored in the default variable to pass to the first parameter */
+      bool used_defvar = false;       
+        /* flag to cirreclty handle calls to extensible standard functions (i.e. functions with variable number of input parameters) */
+      bool found_first_extensible_parameter = false;  
+      for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
+        if (fp_iterator.is_extensible_param() && (!found_first_extensible_parameter)) {
+          /* We are calling an extensible function. Before passing the extensible
+           * parameters, we must add a dummy paramater value to tell the called
+           * function how many extensible parameters we will be passing.
+           *
+           * Note that stage 3 has already determined the number of extensible
+           * paramters, and stored that info in the abstract syntax tree. We simply
+           * re-use that value.
+           */
+          /* NOTE: we are not freeing the malloc'd memory. This is not really a bug.
+           *       Since we are writing a compiler, which runs to termination quickly,
+           *       we can consider this as just memory required for the compilation process
+           *       that will be free'd when the program terminates.
+           */
+          char *tmp = (char *)malloc(32); /* enough space for a call with 10^31 (larger than 2^64) input parameters! */
+          if (tmp == NULL) ERROR;
+          int res = snprintf(tmp, 32, "%d", symbol->extensible_param_count);
+          if ((res >= 32) || (res < 0)) ERROR;
+          identifier_c *param_value = new identifier_c(tmp);
+          uint_type_name_c *param_type  = new uint_type_name_c();
+          identifier_c *param_name = new identifier_c("");
+          ADD_PARAM_LIST(param_name, param_value, param_type, function_param_iterator_c::direction_in)
+          found_first_extensible_parameter = true;
+        }
+    
+        symbol_c *param_type = fp_iterator.param_type();
+        if (param_type == NULL) ERROR;
+      
+        function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
+      
+        symbol_c *param_value = NULL;
+      
+        /* Get the value from a foo(<param_name> = <param_value>) style call */
+        /* NOTE: the following line of code is not required in this case, but it doesn't
+         * harm to leave it in, as in the case of a non-formal syntax function call,
+         * it will always return NULL.
+         * We leave it in in case we later decide to merge this part of the code together
+         * with the function calling code in generate_c_st_c, which does require
+         * the following line...
+         */
+        if (param_value == NULL)
+          param_value = function_call_param_iterator.search_f(param_name);
+
+        /* if it is the first parameter in a non-formal function call (which is the
+         * case being handled!), semantics specifies that we should
+         * get the value off the IL default variable!
+         *
+         * However, if the parameter is an implicitly defined EN or ENO parameter, we should not
+         * use the default variable as a source of data to pass to those parameters!
+         */
+        if ((param_value == NULL) && (!used_defvar) && !fp_iterator.is_en_eno_param_implicit()) {
+          param_value = &this->default_variable_name;
+          used_defvar = true;
+        }
+
+        /* Get the value from a foo(<param_value>) style call */
+        if ((param_value == NULL) && !fp_iterator.is_en_eno_param_implicit()) {
+          param_value = function_call_param_iterator.next_nf();
+        }
+        
+        /* if no more parameter values in function call, and the current parameter
+         * of the function declaration is an extensible parameter, we
+         * have reached the end, and should simply jump out of the for loop.
+         */
+        if ((param_value == NULL) && (fp_iterator.is_extensible_param())) {
+          break;
+        }
+      
+        if ((param_value == NULL) && (param_direction == function_param_iterator_c::direction_in)) {
+          /* No value given for parameter, so we must use the default... */
+          /* First check whether default value specified in function declaration...*/
+          param_value = fp_iterator.default_value();
+        }
+      
+        ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction())
+      } /* for(...) */
+
+      if (function_call_param_iterator.next_nf() != NULL) ERROR;
       if (NULL == function_type_prefix) ERROR;
 
       bool has_output_params = false;
@@ -442,8 +472,16 @@
         }
       }
 
+      /* Check whether we are calling an overloaded function! */
+      /* (fdecl_mutiplicity==2)  => calling overloaded function */
+      int fdecl_mutiplicity =  function_symtable.multiplicity(symbol->function_name);
+      if (fdecl_mutiplicity == 0) ERROR;
+      if (fdecl_mutiplicity == 1) 
+        /* function being called is NOT overloaded! */
+        f_decl = NULL; 
+
       if (has_output_params)
-        generate_inline(function_name, function_type_prefix, function_type_suffix, param_list);
+        generate_inline(function_name, function_type_prefix, function_type_suffix, param_list, f_decl);
 
       CLEAR_PARAM_LIST()
 
@@ -460,87 +498,103 @@
 
       function_call_param_iterator_c function_call_param_iterator(symbol);
 
-      function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
-      if (f_decl == function_symtable.end_value()) {
-        function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
-        if (current_function_type == function_none) ERROR;
-
-        function_type_prefix = (symbol_c *)search_expression_type->compute_standard_function_default(NULL, symbol);
-
-        int nb_param = 0;
-        if (symbol->il_param_list != NULL)
-          nb_param += ((list_c *)symbol->il_param_list)->n;
-
-        symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN"));
-        /* Get the value from EN param */
-        symbol_c *EN_param_value = function_call_param_iterator.search_f(en_param_name);
-        if (EN_param_value == NULL)
-          EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c()));
-        else
-          nb_param --;
-        ADD_PARAM_LIST(en_param_name, EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in)
-
-        symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO"));
-        /* Get the value from ENO param */
-        symbol_c *ENO_param_value = function_call_param_iterator.search_f(eno_param_name);
-        if (ENO_param_value != NULL)
-          nb_param --;
-        ADD_PARAM_LIST(eno_param_name, ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
-
-        #include "st_code_gen.c"
-
-      }
-      else {
-        function_name = symbol->function_name;
-
-		/* determine the base data type returned by the function being called... */
-		search_base_type_c search_base_type;
-		function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
-
-		/* loop through each function parameter, find the value we should pass
-		 * to it, and then output the c equivalent...
-		 */
-
-		function_param_iterator_c fp_iterator(f_decl);
-		identifier_c *param_name;
-		for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
-		  symbol_c *param_type = fp_iterator.param_type();
-		  if (param_type == NULL) ERROR;
-
-		  function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
-
-
-		  symbol_c *param_value = NULL;
-
-		  /* Get the value from a foo(<param_name> = <param_value>) style call */
-		  if (param_value == NULL)
-			param_value = function_call_param_iterator.search_f(param_name);
-
-		  /* Get the value from a foo(<param_value>) style call */
-		  /* NOTE: the following line of code is not required in this case, but it doesn't
-		   * harm to leave it in, as in the case of a formal syntax function call,
-		   * it will always return NULL.
-		   * We leave it in in case we later decide to merge this part of the code together
-		   * with the function calling code in generate_c_st_c, which does require
-		   * the following line...
-		   */
-		  if (param_value == NULL) {
-            param_value = function_call_param_iterator.next_nf();
-            if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR;
-          }
-
-		  if (param_value == NULL) {
-			/* No value given for parameter, so we must use the default... */
-			/* First check whether default value specified in function declaration...*/
-			param_value = fp_iterator.default_value();
-		  }
-
-		  ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction())
-		}
+      function_declaration_c *f_decl = (function_declaration_c *)symbol->called_function_declaration;
+      if (f_decl == NULL) ERROR;
+
+      /* determine the base data type returned by the function being called... */
+      search_base_type_c search_base_type;
+      function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
+      if (NULL == function_type_prefix) ERROR;
+      
+      function_name = symbol->function_name;
+
+      /* loop through each function parameter, find the value we should pass
+       * to it, and then output the c equivalent...
+       */
+      function_param_iterator_c fp_iterator(f_decl);
+      identifier_c *param_name;
+
+        /* flag to cirreclty handle calls to extensible standard functions (i.e. functions with variable number of input parameters) */
+      bool found_first_extensible_parameter = false;
+      for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
+        if (fp_iterator.is_extensible_param() && (!found_first_extensible_parameter)) {
+          /* We are calling an extensible function. Before passing the extensible
+           * parameters, we must add a dummy paramater value to tell the called
+           * function how many extensible parameters we will be passing.
+           *
+           * Note that stage 3 has already determined the number of extensible
+           * paramters, and stored that info in the abstract syntax tree. We simply
+           * re-use that value.
+           */
+          /* NOTE: we are not freeing the malloc'd memory. This is not really a bug.
+           *       Since we are writing a compiler, which runs to termination quickly,
+           *       we can consider this as just memory required for the compilation process
+           *       that will be free'd when the program terminates.
+           */
+          char *tmp = (char *)malloc(32); /* enough space for a call with 10^31 (larger than 2^64) input parameters! */
+          if (tmp == NULL) ERROR;
+          int res = snprintf(tmp, 32, "%d", symbol->extensible_param_count);
+          if ((res >= 32) || (res < 0)) ERROR;
+          identifier_c *param_value = new identifier_c(tmp);
+          uint_type_name_c *param_type  = new uint_type_name_c();
+          identifier_c *param_name = new identifier_c("");
+          ADD_PARAM_LIST(param_name, param_value, param_type, function_param_iterator_c::direction_in)
+          found_first_extensible_parameter = true;
+        }
+        
+        if (fp_iterator.is_extensible_param()) {      
+          /* since we are handling an extensible parameter, we must add the index to the
+           * parameter name so we can go looking for the value passed to the correct
+           * extended parameter (e.g. IN1, IN2, IN3, IN4, ...)
+           */
+          char *tmp = (char *)malloc(32); /* enough space for a call with 10^31 (larger than 2^64) input parameters! */
+          int res = snprintf(tmp, 32, "%d", fp_iterator.extensible_param_index());
+          if ((res >= 32) || (res < 0)) ERROR;
+          param_name = new identifier_c(strdup2(param_name->value, tmp));
+          if (param_name->value == NULL) ERROR;
+        }
+    
+        symbol_c *param_type = fp_iterator.param_type();
+        if (param_type == NULL) ERROR;
+      
+        function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
+      
+        symbol_c *param_value = NULL;
+      
+        /* Get the value from a foo(<param_name> = <param_value>) style call */
+        if (param_value == NULL)
+          param_value = function_call_param_iterator.search_f(param_name);
+      
+        /* Get the value from a foo(<param_value>) style call */
+        /* NOTE: the following line of code is not required in this case, but it doesn't
+         * harm to leave it in, as in the case of a formal syntax function call,
+         * it will always return NULL.
+         * We leave it in in case we later decide to merge this part of the code together
+         * with the function calling code in generate_c_st_c, which does require
+         * the following line...
+         */
+        if ((param_value == NULL) && !fp_iterator.is_en_eno_param_implicit()) {
+          param_value = function_call_param_iterator.next_nf();
+        }
+        
+        /* if no more parameter values in function call, and the current parameter
+         * of the function declaration is an extensible parameter, we
+         * have reached the end, and should simply jump out of the for loop.
+         */
+        if ((param_value == NULL) && (fp_iterator.is_extensible_param())) {
+          break;
+        }
+    
+        if ((param_value == NULL) && (param_direction == function_param_iterator_c::direction_in)) {
+          /* No value given for parameter, so we must use the default... */
+          /* First check whether default value specified in function declaration...*/
+          param_value = fp_iterator.default_value();
+        }
+
+        ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction())
       }
 
       if (function_call_param_iterator.next_nf() != NULL) ERROR;
-      if (NULL == function_type_prefix) ERROR;
 
       bool has_output_params = false;
 
@@ -552,8 +606,16 @@
         }
       }
 
+      /* Check whether we are calling an overloaded function! */
+      /* (fdecl_mutiplicity==2)  => calling overloaded function */
+      int fdecl_mutiplicity =  function_symtable.multiplicity(symbol->function_name);
+      if (fdecl_mutiplicity == 0) ERROR;
+      if (fdecl_mutiplicity == 1) 
+        /* function being called is NOT overloaded! */
+        f_decl = NULL; 
+
       if (has_output_params)
-        generate_inline(function_name, function_type_prefix, function_type_suffix, param_list);
+        generate_inline(function_name, function_type_prefix, function_type_suffix, param_list, f_decl);
 
       CLEAR_PARAM_LIST()
 
@@ -580,81 +642,100 @@
 
       function_call_param_iterator_c function_call_param_iterator(symbol);
 
-      function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
-      if (f_decl == function_symtable.end_value()) {
-        /* The function called is not in the symtable, so we test if it is a
-         * standard function defined in standard */
-
-        function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
-        if (current_function_type == function_none) ERROR;
-
-        function_type_prefix = search_expression_type->get_type(symbol);
-
-        int nb_param = ((list_c *)parameter_assignment_list)->n;
-
-        symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN"));
-        /* Get the value from EN param */
-        symbol_c *EN_param_value = function_call_param_iterator.search_f(en_param_name);
-        if (EN_param_value == NULL)
-          EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c()));
-        else
-          nb_param --;
-        ADD_PARAM_LIST(en_param_name, EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in)
-
-        symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO"));
-        /* Get the value from ENO param */
-        symbol_c *ENO_param_value = function_call_param_iterator.search_f(eno_param_name);
-        if (ENO_param_value != NULL)
-          nb_param --;
-        ADD_PARAM_LIST(eno_param_name, ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
-
-        #include "st_code_gen.c"
-
-      }
-      else {
-        function_name = symbol->function_name;
-
-	    /* determine the base data type returned by the function being called... */
-		search_base_type_c search_base_type;
-		function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
-
-    	/* loop through each function parameter, find the value we should pass
-         * to it, and then output the c equivalent...
+      function_declaration_c *f_decl = (function_declaration_c *)symbol->called_function_declaration;
+      if (f_decl == NULL) ERROR;
+
+      function_name = symbol->function_name;
+
+      /* determine the base data type returned by the function being called... */
+      search_base_type_c search_base_type;
+      function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
+      if (NULL == function_type_prefix) ERROR;
+
+      /* loop through each function parameter, find the value we should pass
+       * to it, and then output the c equivalent...
+       */
+      function_param_iterator_c fp_iterator(f_decl);
+      identifier_c *param_name;
+        /* flag to cirreclty handle calls to extensible standard functions (i.e. functions with variable number of input parameters) */
+      bool found_first_extensible_parameter = false;  
+      for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
+        if (fp_iterator.is_extensible_param() && (!found_first_extensible_parameter)) {
+          /* We are calling an extensible function. Before passing the extensible
+           * parameters, we must add a dummy paramater value to tell the called
+           * function how many extensible parameters we will be passing.
+           *
+           * Note that stage 3 has already determined the number of extensible
+           * paramters, and stored that info in the abstract syntax tree. We simply
+           * re-use that value.
+           */
+          /* NOTE: we are not freeing the malloc'd memory. This is not really a bug.
+           *       Since we are writing a compiler, which runs to termination quickly,
+           *       we can consider this as just memory required for the compilation process
+           *       that will be free'd when the program terminates.
+           */
+          char *tmp = (char *)malloc(32); /* enough space for a call with 10^31 (larger than 2^64) input parameters! */
+          if (tmp == NULL) ERROR;
+          int res = snprintf(tmp, 32, "%d", symbol->extensible_param_count);
+          if ((res >= 32) || (res < 0)) ERROR;
+          identifier_c *param_value = new identifier_c(tmp);
+          uint_type_name_c *param_type  = new uint_type_name_c();
+          identifier_c *param_name = new identifier_c("");
+          ADD_PARAM_LIST(param_name, param_value, param_type, function_param_iterator_c::direction_in)
+          found_first_extensible_parameter = true;
+        }
+    
+        if (fp_iterator.is_extensible_param()) {      
+          /* since we are handling an extensible parameter, we must add the index to the
+           * parameter name so we can go looking for the value passed to the correct
+           * extended parameter (e.g. IN1, IN2, IN3, IN4, ...)
+           */
+          char *tmp = (char *)malloc(32); /* enough space for a call with 10^31 (larger than 2^64) input parameters! */
+          int res = snprintf(tmp, 32, "%d", fp_iterator.extensible_param_index());
+          if ((res >= 32) || (res < 0)) ERROR;
+          param_name = new identifier_c(strdup2(param_name->value, tmp));
+          if (param_name->value == NULL) ERROR;
+        }
+        
+        symbol_c *param_type = fp_iterator.param_type();
+        if (param_type == NULL) ERROR;
+
+        function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
+
+        symbol_c *param_value = NULL;
+    
+        /* Get the value from a foo(<param_name> = <param_value>) style call */
+        if (param_value == NULL)
+          param_value = function_call_param_iterator.search_f(param_name);
+
+        /* Get the value from a foo(<param_value>) style call */
+        if ((param_value == NULL) && !fp_iterator.is_en_eno_param_implicit()) {
+          param_value = function_call_param_iterator.next_nf();
+        }
+        
+        /* if no more parameter values in function call, and the current parameter
+         * of the function declaration is an extensible parameter, we
+         * have reached the end, and should simply jump out of the for loop.
          */
-        function_param_iterator_c fp_iterator(f_decl);
-        identifier_c *param_name;
-        for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
-          symbol_c *param_type = fp_iterator.param_type();
-          if (param_type == NULL) ERROR;
-
-          function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
-
-          /* Get the value from a foo(<param_name> = <param_value>) style call */
-          symbol_c *param_value = function_call_param_iterator.search_f(param_name);
-
-          /* Get the value from a foo(<param_value>) style call */
-          if (param_value == NULL) {
-            param_value = function_call_param_iterator.next_nf();
-            if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR;
-          }
-
-          if (param_value == NULL && param_direction == function_param_iterator_c::direction_in) {
-            /* No value given for parameter, so we must use the default... */
-            /* First check whether default value specified in function declaration...*/
-            param_value = fp_iterator.default_value();
-          }
-
-          ADD_PARAM_LIST(param_name, param_value, param_type, param_direction)
-        } /* for(...) */
-        // symbol->parameter_assignment->accept(*this);
-      }
+        if ((param_value == NULL) && (fp_iterator.is_extensible_param())) {
+          break;
+        }
+    
+        if ((param_value == NULL) && (param_direction == function_param_iterator_c::direction_in)) {
+          /* No value given for parameter, so we must use the default... */
+          /* First check whether default value specified in function declaration...*/
+          param_value = fp_iterator.default_value();
+        }
+
+        ADD_PARAM_LIST(param_name, param_value, param_type, param_direction)
+      } /* for(...) */
+      // symbol->parameter_assignment->accept(*this);
 
       if (function_call_param_iterator.next_nf() != NULL) ERROR;
-      if (NULL == function_type_prefix) ERROR;
-
-	  bool has_output_params = false;
-
-	  PARAM_LIST_ITERATOR() {
+
+      bool has_output_params = false;
+
+      PARAM_LIST_ITERATOR() {
         if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
              PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
              PARAM_VALUE != NULL) {
@@ -662,12 +743,20 @@
         }
       }
 
+      /* Check whether we are calling an overloaded function! */
+      /* (fdecl_mutiplicity==2)  => calling overloaded function */
+      int fdecl_mutiplicity =  function_symtable.multiplicity(symbol->function_name);
+      if (fdecl_mutiplicity == 0) ERROR;
+      if (fdecl_mutiplicity == 1) 
+        /* function being called is NOT overloaded! */
+        f_decl = NULL; 
+
       if (has_output_params)
-        generate_inline(function_name, function_type_prefix, function_type_suffix, param_list);
+        generate_inline(function_name, function_type_prefix, function_type_suffix, param_list, f_decl);
 
       CLEAR_PARAM_LIST()
 
-	  return NULL;
+      return NULL;
     }
 
 };  /* generate_c_inlinefcall_c */
--- a/stage4/generate_c/generate_c_sfc.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/stage4/generate_c/generate_c_sfc.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -519,7 +519,7 @@
               s4o.print("activated");
             }
             if (strcmp(qualifier, "D") == 0 || strcmp(qualifier, "L") == 0) {
-              s4o.print("active && __TIME_CMP(");
+              s4o.print("active && __time_cmp(");
               print_step_argument(current_step, "elapsed_time");
               s4o.print(", ");
               symbol->action_time->accept(*this);
@@ -640,7 +640,9 @@
       /* 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 = __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");
       s4o.print(s4o.indent_spaces);
@@ -686,7 +688,9 @@
       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 = __time_add(__BOOL_LITERAL(TRUE), NULL, ");
+//      s4o.print("__step_list[i].elapsed_time = ADD_TIME(__BOOL_LITERAL(TRUE), NULL, ");
+      s4o.print("__step_list[i].elapsed_time = __time_add(");
       print_variable_prefix();
       s4o.print("__step_list[i].elapsed_time, elapsed_time);\n");
       s4o.indent_left();
@@ -710,17 +714,19 @@
       print_variable_prefix();
       s4o.print("__action_list[i].reset = 0;\n");
       s4o.print(s4o.indent_spaces + "if (");
-      s4o.print("__TIME_CMP(");
+      s4o.print("__time_cmp(");
       print_variable_prefix();
       s4o.print("__action_list[i].set_remaining_time, __time_to_timespec(1, 0, 0, 0, 0, 0)) > 0) {\n");
       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 = __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");
       s4o.print(s4o.indent_spaces + "if (");
-      s4o.print("__TIME_CMP(");
+      s4o.print("__time_cmp(");
       print_variable_prefix();
       s4o.print("__action_list[i].set_remaining_time, __time_to_timespec(1, 0, 0, 0, 0, 0)) <= 0) {\n");
       s4o.indent_right();
@@ -735,17 +741,19 @@
       s4o.indent_left();
       s4o.print(s4o.indent_spaces + "}\n");
       s4o.print(s4o.indent_spaces + "if (");
-      s4o.print("__TIME_CMP(");
+      s4o.print("__time_cmp(");
       print_variable_prefix();
       s4o.print("__action_list[i].reset_remaining_time, __time_to_timespec(1, 0, 0, 0, 0, 0)) > 0) {\n");
       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 = __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");
       s4o.print(s4o.indent_spaces + "if (");
-      s4o.print("__TIME_CMP(");
+      s4o.print("__time_cmp(");
       print_variable_prefix();
       s4o.print("__action_list[i].reset_remaining_time, __time_to_timespec(1, 0, 0, 0, 0, 0)) <= 0) {\n");
       s4o.indent_right();
--- a/stage4/generate_c/generate_c_st.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/stage4/generate_c/generate_c_st.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -35,6 +35,9 @@
  */
 
 
+
+#include "../../util/strdup.hh"
+
 /***********************************************************************/
 /***********************************************************************/
 /***********************************************************************/
@@ -434,7 +437,7 @@
       ERROR;
   if (search_expression_type->is_time_type(left_type) ||
       search_expression_type->is_string_type(left_type))
-    return print_compare_function("__eq_", left_type, symbol->l_exp, symbol->r_exp);
+    return print_compare_function("EQ_", left_type, symbol->l_exp, symbol->r_exp);
   return print_binary_expression(symbol->l_exp, symbol->r_exp, " == ");
 }
 
@@ -445,7 +448,7 @@
       ERROR;
   if (search_expression_type->is_time_type(left_type) ||
       search_expression_type->is_string_type(left_type))
-    return print_compare_function("__ne_", left_type, symbol->l_exp, symbol->r_exp);
+    return print_compare_function("NE_", left_type, symbol->l_exp, symbol->r_exp);
   return print_binary_expression(symbol->l_exp, symbol->r_exp, " != ");
 }
 
@@ -456,7 +459,7 @@
       ERROR;
   if (search_expression_type->is_time_type(left_type) ||
       search_expression_type->is_string_type(left_type))
-    return print_compare_function("__lt_", left_type, symbol->l_exp, symbol->r_exp);
+    return print_compare_function("LT_", left_type, symbol->l_exp, symbol->r_exp);
   if (!search_base_type.type_is_enumerated(left_type))
     return print_binary_expression(symbol->l_exp, symbol->r_exp, " < ");
   ERROR;
@@ -470,7 +473,7 @@
       ERROR;
   if (search_expression_type->is_time_type(left_type) ||
       search_expression_type->is_string_type(left_type))
-    return print_compare_function("__gt_", left_type, symbol->l_exp, symbol->r_exp);
+    return print_compare_function("GT_", left_type, symbol->l_exp, symbol->r_exp);
   if (!search_base_type.type_is_enumerated(left_type))
     return print_binary_expression(symbol->l_exp, symbol->r_exp, " > ");
   ERROR;
@@ -484,7 +487,7 @@
       ERROR;
   if (search_expression_type->is_time_type(left_type) ||
       search_expression_type->is_string_type(left_type))
-    return print_compare_function("__le_", left_type, symbol->l_exp, symbol->r_exp);
+    return print_compare_function("LE_", left_type, symbol->l_exp, symbol->r_exp);
   if (!search_base_type.type_is_enumerated(left_type))
     return print_binary_expression(symbol->l_exp, symbol->r_exp, " <= ");
   ERROR;
@@ -498,7 +501,7 @@
       ERROR;
   if (search_expression_type->is_time_type(left_type) ||
       search_expression_type->is_string_type(left_type))
-    return print_compare_function("__ge_", left_type, symbol->l_exp, symbol->r_exp);
+    return print_compare_function("GE_", left_type, symbol->l_exp, symbol->r_exp);
   if (!search_base_type.type_is_enumerated(left_type))
     return print_binary_expression(symbol->l_exp, symbol->r_exp, " >= ");
   ERROR;
@@ -511,7 +514,7 @@
 	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);
+    return print_binary_function("__time_add", symbol->l_exp, symbol->r_exp);
   if (!search_expression_type->is_same_type(left_type, right_type))
       ERROR;
   if (search_expression_type->is_integer_type(left_type) || search_expression_type->is_real_type(left_type))
@@ -529,7 +532,7 @@
       (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);
+    return print_binary_function("__time_sub", symbol->l_exp, symbol->r_exp);
   if (!search_expression_type->is_same_type(left_type, right_type))
       ERROR;
   if (search_expression_type->is_integer_type(left_type) || search_expression_type->is_real_type(left_type))
@@ -543,7 +546,7 @@
   symbol_c *right_type = search_expression_type->get_type(symbol->r_exp);
   if ((typeid(*left_type) == typeid(time_type_name_c) && search_expression_type->is_integer_type(right_type)) ||
       (typeid(*left_type) == typeid(time_type_name_c) && search_expression_type->is_real_type(right_type)))
-    return print_binary_function("__TIME_MUL", symbol->l_exp, symbol->r_exp);
+    return print_binary_function("__time_mul", symbol->l_exp, symbol->r_exp);
   if (!search_expression_type->is_same_type(left_type, right_type))
       ERROR;
   if (search_expression_type->is_integer_type(left_type) || search_expression_type->is_real_type(left_type))
@@ -557,7 +560,7 @@
   symbol_c *right_type = search_expression_type->get_type(symbol->r_exp);
   if ((typeid(*left_type) == typeid(time_type_name_c) && search_expression_type->is_integer_type(right_type)) ||
       (typeid(*left_type) == typeid(time_type_name_c) && search_expression_type->is_real_type(right_type)))
-    return print_binary_function("__TIME_DIV", symbol->l_exp, symbol->r_exp);
+    return print_binary_function("__time_div", symbol->l_exp, symbol->r_exp);
   if (!search_expression_type->is_same_type(left_type, right_type))
       ERROR;
   if (search_expression_type->is_integer_type(left_type) || search_expression_type->is_real_type(left_type))
@@ -614,71 +617,89 @@
 
   function_call_param_iterator_c function_call_param_iterator(symbol);
 
-  function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
-  if (f_decl == function_symtable.end_value()) {
-    /* The function called is not in the symtable, so we test if it is a
-     * standard function defined in standard */
-
-    function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
-    if (current_function_type == function_none) ERROR;
-
-    symbol_c *function_return_type = search_expression_type->get_type(symbol);
-
-    int nb_param = ((list_c *)parameter_assignment_list)->n;
-
-    symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN"));
-    /* Get the value from EN param */
-    symbol_c *EN_param_value = function_call_param_iterator.search_f(en_param_name);
-    if (EN_param_value == NULL)
-      EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c()));
-    else
-      nb_param --;
-    ADD_PARAM_LIST(en_param_name, EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in)
-
-    symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO"));
-    /* Get the value from ENO param */
-    symbol_c *ENO_param_value = function_call_param_iterator.search_f(eno_param_name);
-    if (ENO_param_value != NULL)
-      nb_param --;
-    ADD_PARAM_LIST(eno_param_name, ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
-
-    #include "st_code_gen.c"
-
-  }
-  else {
-	function_name = symbol->function_name;
-
-	/* loop through each function parameter, find the value we should pass
-     * to it, and then output the c equivalent...
+  function_declaration_c *f_decl = (function_declaration_c *)symbol->called_function_declaration;
+  if (f_decl == NULL) ERROR;
+  
+  function_name = symbol->function_name;
+  
+  /* loop through each function parameter, find the value we should pass
+   * to it, and then output the c equivalent...
+   */
+  function_param_iterator_c fp_iterator(f_decl);
+  identifier_c *param_name;
+    /* flag to cirreclty handle calls to extensible standard functions (i.e. functions with variable number of input parameters) */
+  bool found_first_extensible_parameter = false;  
+  for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
+    if (fp_iterator.is_extensible_param() && (!found_first_extensible_parameter)) {
+      /* We are calling an extensible function. Before passing the extensible
+       * parameters, we must add a dummy paramater value to tell the called
+       * function how many extensible parameters we will be passing.
+       *
+       * Note that stage 3 has already determined the number of extensible
+       * paramters, and stored that info in the abstract syntax tree. We simply
+       * re-use that value.
+       */
+      /* NOTE: we are not freeing the malloc'd memory. This is not really a bug.
+       *       Since we are writing a compiler, which runs to termination quickly,
+       *       we can consider this as just memory required for the compilation process
+       *       that will be free'd when the program terminates.
+       */
+      char *tmp = (char *)malloc(32); /* enough space for a call with 10^31 (larger than 2^64) input parameters! */
+      if (tmp == NULL) ERROR;
+      int res = snprintf(tmp, 32, "%d", symbol->extensible_param_count);
+      if ((res >= 32) || (res < 0)) ERROR;
+      identifier_c *param_value = new identifier_c(tmp);
+      uint_type_name_c *param_type  = new uint_type_name_c();
+      identifier_c *param_name = new identifier_c("");
+      ADD_PARAM_LIST(param_name, param_value, param_type, function_param_iterator_c::direction_in)
+      found_first_extensible_parameter = true;
+    }
+
+    if (fp_iterator.is_extensible_param()) {      
+      /* since we are handling an extensible parameter, we must add the index to the
+       * parameter name so we can go looking for the value passed to the correct
+       * extended parameter (e.g. IN1, IN2, IN3, IN4, ...)
+       */
+      char *tmp = (char *)malloc(32); /* enough space for a call with 10^31 (larger than 2^64) input parameters! */
+      int res = snprintf(tmp, 32, "%d", fp_iterator.extensible_param_index());
+      if ((res >= 32) || (res < 0)) ERROR;
+      param_name = new identifier_c(strdup2(param_name->value, tmp));
+      if (param_name->value == NULL) ERROR;
+    }
+    
+    symbol_c *param_type = fp_iterator.param_type();
+    if (param_type == NULL) ERROR;
+
+    function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
+    
+    symbol_c *param_value = NULL;
+    
+    /* Get the value from a foo(<param_name> = <param_value>) style call */
+    if (param_value == NULL)
+      param_value = function_call_param_iterator.search_f(param_name);
+
+    /* Get the value from a foo(<param_value>) style call */
+    if ((param_value == NULL) && !fp_iterator.is_en_eno_param_implicit()) {
+      param_value = function_call_param_iterator.next_nf();
+    }
+
+    /* if no more parameter values in function call, and the current parameter
+     * of the function declaration is an extensible parameter, we
+     * have reached the end, and should simply jump out of the for loop.
      */
-    function_param_iterator_c fp_iterator(f_decl);
-    identifier_c *param_name;
-    for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
-      
-      symbol_c *param_type = fp_iterator.param_type();
-      if (param_type == NULL) ERROR;
-
-      function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
-      
-      /* Get the value from a foo(<param_name> = <param_value>) style call */
-      symbol_c *param_value = function_call_param_iterator.search_f(param_name);
-  
-      /* Get the value from a foo(<param_value>) style call */
-      if (param_value == NULL) {
-        param_value = function_call_param_iterator.next_nf();
-        if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR;
-      }
-      
-      if (param_value == NULL && param_direction == function_param_iterator_c::direction_in) {
-        /* No value given for parameter, so we must use the default... */
-        /* First check whether default value specified in function declaration...*/
-        param_value = fp_iterator.default_value();
-      }
-      
-      ADD_PARAM_LIST(param_name, param_value, param_type, param_direction)
-    } /* for(...) */
-    // symbol->parameter_assignment->accept(*this);
-  }
+    if ((param_value == NULL) && (fp_iterator.is_extensible_param())) {
+      break;
+    }
+    
+    if ((param_value == NULL) && (param_direction == function_param_iterator_c::direction_in)) {
+      /* No value given for parameter, so we must use the default... */
+      /* First check whether default value specified in function declaration...*/
+      param_value = fp_iterator.default_value();
+    }
+    
+    ADD_PARAM_LIST(param_name, param_value, param_type, param_direction)
+  } /* for(...) */
+  // symbol->parameter_assignment->accept(*this);
   
   if (function_call_param_iterator.next_nf() != NULL) ERROR;
 
@@ -686,15 +707,18 @@
 
   if (!this->is_variable_prefix_null()) {
     PARAM_LIST_ITERATOR() {
-	  if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
-		   PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
-		  PARAM_VALUE != NULL) {
-	    if (!has_output_params) {
-		  has_output_params = true;
-		}
-	  }
-    }
-  }
+      if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
+           PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
+           PARAM_VALUE != NULL) {
+        has_output_params = true;
+      }
+    }
+  }
+
+  /* Check whether we are calling an overloaded function! */
+  /* (fdecl_mutiplicity==2)  => calling overloaded function */
+  int fdecl_mutiplicity =  function_symtable.multiplicity(symbol->function_name);
+  if (fdecl_mutiplicity == 0) ERROR;
 
   if (function_type_prefix != NULL) {
     s4o.print("(");
@@ -702,20 +726,32 @@
     s4o.print(")");
   }
   if (function_type_suffix != NULL) {
-	function_type_suffix = search_expression_type->default_literal_type(function_type_prefix);
+    function_type_suffix = search_expression_type->default_literal_type(function_type_prefix);
   }
   if (has_output_params) {
-	fcall_number++;
-	s4o.print("__");
+    fcall_number++;
+    s4o.print("__");
     fbname->accept(*this);
     s4o.print("_");
     function_name->accept(*this);
+    if (fdecl_mutiplicity == 2) {
+      /* function being called is overloaded! */
+      s4o.print("__");
+      print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+      f_decl->accept(overloaded_func_suf);
+    }
     if (function_type_suffix != NULL)
       function_type_suffix->accept(*this);
     s4o.print_integer(fcall_number);
   }
   else {
     function_name->accept(*this);
+    if (fdecl_mutiplicity == 2) {
+      /* function being called is overloaded! */
+      s4o.print("__");
+      print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+      f_decl->accept(overloaded_func_suf);
+    }
     if (function_type_suffix != NULL)
       function_type_suffix->accept(*this);
   }
@@ -845,7 +881,10 @@
     symbol_c *param_value = function_call_param_iterator.search_f(param_name);
 
     /* Get the value from a foo(<param_value>) style call */
-    if (param_value == NULL)
+    /* When using the informal invocation style, user can not pass values to EN or ENO parameters if these
+     * were implicitly defined!
+     */
+    if ((param_value == NULL) && !fp_iterator.is_en_eno_param_implicit())
       param_value = function_call_param_iterator.next_nf();
 
     symbol_c *param_type = fp_iterator.param_type();
@@ -889,7 +928,10 @@
     symbol_c *param_value = function_call_param_iterator.search_f(param_name);
 
     /* Get the value from a foo(<param_value>) style call */
-    if (param_value == NULL)
+    /* When using the informal invocation style, user can not pass values to EN or ENO parameters if these
+     * were implicitly defined!
+     */
+    if ((param_value == NULL) && !fp_iterator.is_en_eno_param_implicit())
       param_value = function_call_param_iterator.next_nf();
 
     /* now output the value assignment */
--- a/stage4/generate_c/generate_c_typedecl.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/stage4/generate_c/generate_c_typedecl.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -76,10 +76,6 @@
     
     basetypedeclaration_t current_basetypedeclaration;
 
-    int extract_integer(symbol_c *integer) {
-      return atoi(((integer_c *)integer)->value);
-    }
-
     void print_integer(unsigned int integer) {
       char str[10];
       sprintf(str, "%d", integer);
--- a/stage4/generate_iec/generate_iec.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/stage4/generate_iec/generate_iec.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -704,6 +704,32 @@
 
 void *visit(var1_list_c *symbol) {return print_list(symbol, "", ", ");}
 
+/* | [var1_list ','] variable_name '..' */
+/* NOTE: This is an extension to the standard!!! */
+/* In order to be able to handle extensible standard functions
+ * (i.e. standard functions that may have a variable number of
+ * input parameters, such as AND(word#33, word#44, word#55, word#66),
+ * we have extended the acceptable syntax to allow var_name '..'
+ * in an input variable declaration.
+ *
+ * This allows us to parse the declaration of standard
+ * extensible functions and load their interface definition
+ * into the abstract syntax tree just like we do to other 
+ * user defined functions.
+ * This has the advantage that we can later do semantic
+ * checking of calls to functions (be it a standard or user defined
+ * function) in (almost) exactly the same way.
+ *
+ * Of course, we have a flag that disables this syntax when parsing user
+ * written code, so we only allow this extra syntax while parsing the 
+ * 'header' file that declares all the standard IEC 61131-3 functions.
+ */
+void *visit(extensible_input_parameter_c *symbol) {
+  symbol->var_name->accept(*this);
+  s4o.print(" .. ");
+  return NULL;
+}
+
 
 /* var1_list ':' array_spec_init */
 void *visit(array_var_init_decl_c *symbol) {
@@ -930,14 +956,10 @@
   return NULL;
 }
 
-/*  STRING ['[' integer ']'] [ASSIGN single_byte_character_string] */
-/* integer ->may be NULL ! */
+/*  single_byte_limited_len_string_spec [ASSIGN single_byte_character_string] */
 /* single_byte_character_string ->may be NULL ! */
 void *visit(single_byte_string_spec_c *symbol) {
-  s4o.print("STRING [");
-  if (symbol->integer != NULL)
-    symbol->integer->accept(*this);
-  s4o.print("]");
+  symbol->string_spec->accept(*this);
   if (symbol->single_byte_character_string != NULL) {
     s4o.print(" := ");
     symbol->single_byte_character_string->accept(*this);
@@ -945,6 +967,18 @@
   return NULL;
 }
 
+/*  STRING ['[' integer ']'] */
+/* integer ->may be NULL ! */
+void *visit(single_byte_limited_len_string_spec_c *symbol) {
+  symbol->string_type_name->accept(*this);
+  if (symbol->character_string_len != NULL) {
+    s4o.print(" [");
+    symbol->character_string_len->accept(*this);
+    s4o.print("]");
+  }
+  return NULL;
+}
+
 /*  var1_list ':' double_byte_string_spec */
 void *visit(double_byte_string_var_declaration_c *symbol) {
   symbol->var1_list->accept(*this);
@@ -953,14 +987,11 @@
   return NULL;
 }
 
-/*  WSTRING ['[' integer ']'] [ASSIGN double_byte_character_string] */
+/*  double_byte_limited_len_string_spec [ASSIGN double_byte_character_string] */
 /* integer ->may be NULL ! */
 /* double_byte_character_string ->may be NULL ! */
 void *visit(double_byte_string_spec_c *symbol) {
-  s4o.print("WSTRING [");
-  if (symbol->integer != NULL)
-    symbol->integer->accept(*this);
-  s4o.print("]");
+  symbol->string_spec->accept(*this);
   if (symbol->double_byte_character_string != NULL) {
     s4o.print(" := ");
     symbol->double_byte_character_string->accept(*this);
@@ -968,6 +999,18 @@
   return NULL;
 }
 
+/* WSTRING ['[' integer ']'] */
+/* integer ->may be NULL ! */
+void *visit(double_byte_limited_len_string_spec_c *symbol) {
+  symbol->string_type_name->accept(*this);
+  if (symbol->character_string_len != NULL) {
+    s4o.print(" [");
+    symbol->character_string_len->accept(*this);
+    s4o.print("]");
+  }
+  return NULL;
+}
+
 /*| VAR [RETAIN|NON_RETAIN] incompl_located_var_decl_list END_VAR */
 /* option ->may be NULL ! */
 void *visit(incompl_located_var_declarations_c *symbol) {
--- a/util/dsymtable.cc	Mon Jul 11 09:47:27 2011 +0100
+++ b/util/dsymtable.cc	Fri Jul 29 16:03:28 2011 +0100
@@ -91,6 +91,28 @@
 #endif
 
 
+
+/* Determine how many entries are associated to key identifier_str */ 
+/* returns:
+ *         0: if no entry is found
+ *         1: if 1 entry is found
+ *         2: if more than 1 entry is found 
+ */
+template<typename value_type, value_type null_value>
+int dsymtable_c<value_type, null_value>::multiplicity(const char *identifier_str) {
+  iterator lower = _base.lower_bound(identifier_str);
+  if (lower == _base.end()) return 0;
+
+  iterator upper = _base.upper_bound(identifier_str);
+  iterator second = lower;
+  second++;
+  
+  if (second == upper) return 1;
+  
+  return 2;
+}
+
+
 /* returns null_value if not found! */
 template<typename value_type, value_type null_value>
 value_type dsymtable_c<value_type, null_value>::find_value(const char *identifier_str) {
@@ -104,11 +126,11 @@
 
 
 template<typename value_type, value_type null_value>
-value_type dsymtable_c<value_type, null_value>::find_value(const symbol_c *symbol) {
+const char * dsymtable_c<value_type, null_value>::symbol_to_string(const symbol_c *symbol) {
   const token_c *name = dynamic_cast<const token_c *>(symbol);
   if (name == NULL)
     ERROR;
-  return find_value(name->value);
+  return name->value;
 }
 
 
--- a/util/dsymtable.hh	Mon Jul 11 09:47:27 2011 +0100
+++ b/util/dsymtable.hh	Fri Jul 29 16:03:28 2011 +0100
@@ -78,6 +78,7 @@
 
   private:
     void reset(void); /* clear all entries... */
+    const char *symbol_to_string(const symbol_c *symbol);
 
   public:
     dsymtable_c(void) {};
@@ -85,12 +86,35 @@
     void insert(const char *identifier_str, value_t value);
     void insert(const symbol_c *symbol, value_t value);
 
+    /* Determine how many entries are associated to key identifier_str */ 
+    /* returns:
+     *         0: if no entry is found
+     *         1: if 1 entry is found
+     *         2: if more than 1 entry is found 
+     */
+    int multiplicity(const char *identifier_str);
+    int multiplicity(const symbol_c *symbol)        {return multiplicity(symbol_to_string(symbol));}
+    
     /* Search for an entry. Will return end_value() if not found */
     value_t end_value(void) {return null_value;}
     value_t find_value(const char *identifier_str);
-    value_t find_value(const symbol_c *symbol);
+    value_t find_value(const symbol_c *symbol)       {return find_value(symbol_to_string(symbol));}
 
-    iterator find(const char *identifier_str) {return _base.find(identifier_str);}
+    /* Search for an entry associated with identifier_str. Will return end() if not found */
+    iterator find(const char *identifier_str)        {return _base.find(identifier_str);}
+    iterator find(const symbol_c *symbol)            {return find(symbol_to_string(symbol));}
+    
+    /* Search for the first entry associated with (i.e. with key ==) identifier_str. Will return end() if not found */
+    /* Basically, the same as find() */
+    iterator lower_bound(const char *identifier_str) {return _base.lower_bound(identifier_str);}
+    iterator lower_bound(const symbol_c *symbol)     {return lower_bound(symbol_to_string(symbol));}
+    
+    /* Search for the first entry with key greater than identifier_str. Will return end() if not found */
+    iterator upper_bound(const char *identifier_str) {return _base.upper_bound(identifier_str);}
+    iterator upper_bound(const symbol_c *symbol)     {return upper_bound(symbol_to_string(symbol));}
+
+    /* get the value to which an iterator is pointing to... */
+    value_t get_value(const iterator i) {return i->second;}
 
   /* iterators pointing to beg/end of map... */
     iterator begin() 			{return _base.begin();}