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.
--- 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();}