Mario changes merged
author'Laurent Bessard <laurent.bessard@lolitech.fr>'
Wed, 02 Sep 2009 14:05:27 +0200
changeset 205 96d8b6e006f0
parent 200 fde2d08ebaee (current diff)
parent 204 8ffa211b7f9a (diff)
child 206 261beef39000
Mario changes merged
stage4/generate_c/generate_c_tempvardecl.cc
--- a/Makefile	Wed Sep 02 13:39:05 2009 +0200
+++ b/Makefile	Wed Sep 02 14:05:27 2009 +0200
@@ -30,7 +30,8 @@
 
 LIBS  = absyntax/absyntax.o absyntax/visitor.o
 LIBS += stage1_2/stage1_2.o stage1_2/iec.y.o stage1_2/iec.flex.o
-
+LIBS += stage3/stage3.o
+LIBS += stage3/visit_expression_type.o
 LIBS += absyntax_utils/absyntax_utils.o
 LIBS += absyntax_utils/search_expression_type.o
 LIBS += absyntax_utils/decompose_var_instance_name.o
@@ -45,6 +46,8 @@
 LIBS += absyntax_utils/search_var_instance_decl.o
 LIBS += absyntax_utils/spec_init_separator.o
 LIBS += absyntax_utils/type_initial_value.o
+LIBS += absyntax_utils/add_en_eno_param_decl.o
+LIBS += absyntax_utils/get_sizeof_datatype.o
 LIBS += absyntax_utils/get_function_type.o
 
 
@@ -69,4 +72,3 @@
 
 
 
-
--- a/absyntax/absyntax.def	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax/absyntax.def	Wed Sep 02 14:05:27 2009 +0200
@@ -84,8 +84,14 @@
 
 
 /* EN/ENO */
+/* NOTE we store 'EN' and 'ENO' tokens in an identifier_c
+ *      as they may be used as variables, and it is much easier 
+ *      to handle them (fewer special cases) if we do it that way...
+ */
+/*
 SYM_REF0(en_param_c)
 SYM_REF0(eno_param_c)
+*/
 
 /***************************/
 /* 2.1.6 - Pragmas */
@@ -132,7 +138,9 @@
 
 SYM_REF1(neg_literal_c, exp)
 
+/* Not required:
 SYM_REF2(numeric_literal_c, type, value)
+*/
 SYM_REF2(integer_literal_c, type, value)
 SYM_REF2(real_literal_c, type, value)
 SYM_REF2(bit_string_literal_c, type, value)
@@ -206,8 +214,11 @@
 SYM_REF0(lword_type_name_c)
 SYM_REF0(string_type_name_c)
 SYM_REF0(wstring_type_name_c)
+
+/*
 SYM_REF0(constant_int_type_name_c)
 SYM_REF0(constant_real_type_name_c)
+*/
 
 
 /********************************/
@@ -403,16 +414,42 @@
 SYM_REF0(non_retain_option_c)
 
 /* option -> the RETAIN/NON_RETAIN/<NULL> directive... */
-SYM_REF2(input_declarations_c, option, input_declaration_list)
+/* NOTE: We need to implicitly define the EN and ENO function and FB parameters when the user
+ *       does not do it explicitly in the IEC 61131-3 source code. 
+ *       To be able to distinguish later on between implictly and explicitly defined
+ *       variables, we use the 'method' flag that allows us to remember
+ *       whether this declaration was in the original source code (method -> implicit_definition_c) 
+ *       or not (method -> explicit_definition_c).
+ */
+SYM_REF3(input_declarations_c, option, input_declaration_list, method)
 
 /* helper symbol for input_declarations */
 SYM_LIST(input_declaration_list_c)
 
+/* NOTE: The formal definition of the standard is erroneous, as it simply does not
+ *       consider the EN and ENO keywords!
+ *       The semantic description of the languages clearly states that these may be
+ *       used in several ways. One of them is to declare an EN input parameter, or
+ *       an ENO output parameter.
+ *       We have added the 'en_param_declaration_c' and 'eno_param_declaration_c' 
+ *       to cover for this.
+ *
+ *       We could have re-used the standard class used for all other input variables (with
+ *       an identifier set to 'EN' or 'ENO') however we may sometimes need to add this
+ *       declaration implicitly (if the user does not include it in the source
+ *       code himself), and it is good to know whether it was added implicitly or not.
+ *       So we create a new class that has a 'method' flag that allows us to remember
+ *       whether this declaration was in the original source code (method -> implicit_definition_c) 
+ *       or not (method -> explicit_definition_c).
+ */
+SYM_REF0(implicit_definition_c)
+SYM_REF0(explicit_definition_c)
+SYM_REF4(en_param_declaration_c, name, type, value, method)
+SYM_REF3(eno_param_declaration_c, name, type, method)
+
 /* edge -> The F_EDGE or R_EDGE directive */
 SYM_REF2(edge_declaration_c, edge, var1_list)
 
-SYM_REF0(en_param_declaration_c)
-
 SYM_REF0(raising_edge_option_c)
 SYM_REF0(falling_edge_option_c)
 
@@ -441,9 +478,14 @@
 
 /* VAR_OUTPUT [RETAIN | NON_RETAIN] var_init_decl_list END_VAR */
 /* option -> may be NULL ! */
-SYM_REF2(output_declarations_c, option, var_init_decl_list)
-
-SYM_REF0(eno_param_declaration_c)
+/* NOTE: We need to implicitly define the EN and ENO function and FB parameters when the user
+ *       does not do it explicitly in the IEC 61131-3 source code. 
+ *       To be able to distinguish later on between implictly and explicitly defined
+ *       variables, we use the 'method' flag that allows us to remember
+ *       whether this declaration was in the original source code (method -> implicit_definition_c) 
+ *       or not (method -> explicit_definition_c).
+ */
+SYM_REF3(output_declarations_c, option, var_init_decl_list, method)
 
 /*  VAR_IN_OUT var_declaration_list END_VAR */
 SYM_REF1(input_output_declarations_c, var_declaration_list)
@@ -885,7 +927,9 @@
 SYM_REF1(neg_expression_c, exp)
 SYM_REF1(not_expression_c, exp)
 
-SYM_REF2(function_invocation_c, function_name, parameter_assignment_list)
+/*    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)
 
 
 /********************/
@@ -908,8 +952,9 @@
 SYM_REF0(return_statement_c)
 
 /* fb_name '(' [param_assignment_list] ')' */
-/* param_assignment_list -> may be NULL ! */
-SYM_REF2(fb_invocation_c, fb_name, param_assignment_list)
+/*    formal_param_list -> may be NULL ! */
+/* nonformal_param_list -> may be NULL ! */
+SYM_REF3(fb_invocation_c, fb_name, formal_param_list, nonformal_param_list)
 
 /* helper symbol for fb_invocation */
 /* param_assignment_list ',' param_assignment */
--- a/absyntax_utils/Makefile	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/Makefile	Wed Sep 02 14:05:27 2009 +0200
@@ -14,10 +14,13 @@
 SEARCH_UTIL_FILES += search_constant_type.o
 SEARCH_UTIL_FILES += search_fb_instance_decl.o
 SEARCH_UTIL_FILES += search_fb_typedecl.o
+SEARCH_UTIL_FILES += search_il_operand_type.o
 SEARCH_UTIL_FILES += search_varfb_instance_type.o
 SEARCH_UTIL_FILES += search_var_instance_decl.o
 SEARCH_UTIL_FILES += spec_init_separator.o
 SEARCH_UTIL_FILES += type_initial_value.o
+SEARCH_UTIL_FILES += add_en_eno_param_decl.o
+SEARCH_UTIL_FILES += get_sizeof_datatype.o
 SEARCH_UTIL_FILES += get_function_type.o
 
 
--- a/absyntax_utils/absyntax_utils.hh	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/absyntax_utils.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -85,7 +85,10 @@
 #include "decompose_var_instance_name.hh"
 #include "search_varfb_instance_type.hh"
 #include "search_constant_type.hh"
+#include "search_il_operand_type.hh"
 #include "search_expression_type.hh"
+#include "add_en_eno_param_decl.hh"
+#include "get_sizeof_datatype.hh"
 #include "get_function_type.h"
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax_utils/add_en_eno_param_decl.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -0,0 +1,196 @@
+/*
+ * (c) 2009 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/*
+ * Iterate through all declared functions and Function Blocks, 
+ * and, for each function/FB, add a declaration of the EN and ENO 
+ * parameters, if they have not already been explicitly declared.
+ *
+ * EN and ENO parameters declared explicitly (by the user in the source code)
+ * and implicitly (by the comnpiler, i.e. by this visitor class) may be
+ * distinguished later on by the 'method' flag in the en_param_declaration_c
+ * and eno_param_declaration_c objects.
+ */
+
+#include "add_en_eno_param_decl.hh"
+#include <strings.h>
+
+
+// #define DEBUG
+#ifdef DEBUG
+#define TRACE(classname) printf("\n____%s____\n",classname);
+#else
+#define TRACE(classname)
+#endif
+
+
+#define ERROR error_exit(__FILE__,__LINE__)
+/* function defined in main.cc */
+extern void error_exit(const char *file_name, int line_no);
+
+
+
+/* This class is a singleton.
+ * So we need a pointer to the singe instance...
+ */
+add_en_eno_param_decl_c *add_en_eno_param_decl_c::singleton = NULL;
+
+/* Constructor for the singleton class */
+symbol_c *add_en_eno_param_decl_c::add_to(symbol_c *tree_root) {
+      if (NULL == singleton) {
+        singleton = new add_en_eno_param_decl_c;
+        if (NULL == singleton)
+          return NULL;
+      }
+      tree_root->accept(*singleton);
+      return tree_root;
+    }
+
+/* Destructor for the singleton class */
+add_en_eno_param_decl_c::~add_en_eno_param_decl_c(void) {
+      if (NULL != singleton) delete singleton;
+      singleton = NULL;
+    }
+
+
+
+void* add_en_eno_param_decl_c::iterate_list(list_c *list) {
+  for (int i = 0; i < list->n; i++) {
+    list->elements[i]->accept(*this);
+  }
+  return NULL;
+}
+
+
+input_declarations_c *add_en_eno_param_decl_c::build_en_param(void) {
+  boolean_literal_c *boolean_literal = 
+    new boolean_literal_c(new bool_type_name_c(), new boolean_true_c());
+  identifier_c *identifier =
+    new identifier_c("EN");
+  en_param_declaration_c *en_param_declaration = 
+    new en_param_declaration_c(identifier, new bool_type_name_c(), boolean_literal, new implicit_definition_c());
+    /* the last paramater is to flag that this
+     * declaration was inserted automatically, i.e. an implicit declaration 
+     */
+  input_declaration_list_c *input_declaration_list = new input_declaration_list_c();
+  input_declaration_list->add_element(en_param_declaration);
+
+  input_declarations_c *input_declarations = new input_declarations_c(NULL, input_declaration_list, new implicit_definition_c());
+  return input_declarations;
+}
+
+
+output_declarations_c *add_en_eno_param_decl_c::build_eno_param(void) {
+  identifier_c *identifier =
+    new identifier_c("ENO");
+  eno_param_declaration_c *eno_param_declaration =
+    new eno_param_declaration_c(identifier, new bool_type_name_c(), new implicit_definition_c()); 
+    /* the last paramater is to flag that this
+     * declaration was inserted automatically, i.e. an implicit declaration 
+     */
+  var_init_decl_list_c *var_init_decl_list = new var_init_decl_list_c();
+  var_init_decl_list->add_element(eno_param_declaration);
+
+  output_declarations_c *output_declarations = new output_declarations_c(NULL, var_init_decl_list, new implicit_definition_c());
+  return output_declarations;
+}
+
+
+
+
+/***************************/
+/* B 0 - Programming Model */
+/***************************/
+void *add_en_eno_param_decl_c::visit(library_c *symbol) {
+  TRACE("library_c"); 
+  return iterate_list(symbol);
+}
+
+
+/***********************/
+/* B 1.5.1 - Functions */
+/***********************/
+void *add_en_eno_param_decl_c::visit(function_declaration_c *symbol) {
+  TRACE("function_declaration_c"); 
+  return symbol->var_declarations_list->accept(*this);
+}
+
+void *add_en_eno_param_decl_c::visit(var_declarations_list_c *symbol) {
+    TRACE("var_declarations_list_c");
+    en_declared  = false; 
+    eno_declared = false; 
+    iterate_list(symbol);
+    if(en_declared  == false) symbol->add_element(build_en_param());
+    if(eno_declared == false) symbol->add_element(build_eno_param());
+    return NULL;
+}
+
+
+
+/****************************************/
+/* 1.4.3 - Declaration & Initialisation */
+/****************************************/
+void *add_en_eno_param_decl_c::visit(input_declarations_c *symbol) {
+  TRACE("input_declarations_c");
+//   current_param_direction = direction_in;
+  return symbol->input_declaration_list->accept(*this);
+}
+
+void *add_en_eno_param_decl_c::visit(input_declaration_list_c *symbol) {TRACE("input_declaration_list_c"); return iterate_list(symbol);}
+
+void *add_en_eno_param_decl_c::visit(en_param_declaration_c *symbol) {
+  TRACE("en_param_declaration_c");
+  en_declared = true;
+  return NULL;
+}
+
+void *add_en_eno_param_decl_c::visit(eno_param_declaration_c *symbol) {
+  TRACE("eno_param_declaration_c");
+  eno_declared = true;
+  return NULL;
+}
+
+void *add_en_eno_param_decl_c::visit(output_declarations_c *symbol) {
+  TRACE("output_declarations_c");
+//   current_param_direction = direction_out;
+  return symbol->var_init_decl_list->accept(*this);
+}
+
+void *add_en_eno_param_decl_c::visit(var_init_decl_list_c *symbol) 
+{TRACE("var_init_decl_list_c"); return iterate_list(symbol);}
+
+
+/*****************************/
+/* B 1.5.2 - Function Blocks */
+/*****************************/
+/*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
+void *add_en_eno_param_decl_c::visit(function_block_declaration_c *symbol) {
+  TRACE("function_block_declaration_c"); 
+  return symbol->var_declarations->accept(*this);
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax_utils/add_en_eno_param_decl.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -0,0 +1,96 @@
+/*
+ * (c) 2009 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/*
+ * Iterate through all declared functions and Function Blocks, 
+ * and, for each function/FB, add a declaration of the EN and ENO 
+ * parameters, if they have not already been explicitly declared.
+ *
+ * EN and ENO parameters declared explicitly (by the user in the source code)
+ * and implicitly (by the comnpiler, i.e. by this visitor class) may be
+ * distinguished later on by the 'method' flag in the en_param_declaration_c
+ * and eno_param_declaration_c objects.
+ */
+
+#include "../absyntax/visitor.hh"
+
+
+class add_en_eno_param_decl_c : public null_visitor_c {
+  public:
+    static symbol_c *add_to(symbol_c *tree_root);
+    ~add_en_eno_param_decl_c(void);
+
+  private:
+    /* this class is a singleton. So we need a pointer to the single instance... */
+    static add_en_eno_param_decl_c *singleton;
+
+    /* flags to remember whether the EN and/or ENO parameters have already
+     * been explicitly declared by the user in the IEC 61131-3 source code we are parsing...
+     */
+    bool en_declared;
+    bool eno_declared;
+
+  private:
+    void* iterate_list(list_c *list);
+    input_declarations_c  *build_en_param (void);
+    output_declarations_c *build_eno_param(void);
+
+  private:
+    /***************************/
+    /* B 0 - Programming Model */
+    /***************************/
+    void *visit(library_c *symbol);
+
+    /***********************/
+    /* B 1.5.1 - Functions */
+    /***********************/
+    void *visit(function_declaration_c *symbol);
+    /* intermediate helper symbol for function_declaration */
+    void *visit(var_declarations_list_c *symbol);
+
+    /******************************************/
+    /* B 1.4.3 - Declaration & Initialisation */
+    /******************************************/
+    void *visit(input_declarations_c *symbol);
+    void *visit(input_declaration_list_c *symbol);
+    void *visit(en_param_declaration_c *symbol);
+    void *visit(eno_param_declaration_c *symbol);
+    void *visit(output_declarations_c *symbol);
+    void *visit(var_init_decl_list_c *symbol);
+
+    /*****************************/
+    /* B 1.5.2 - Function Blocks */
+    /*****************************/
+    /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
+    void *visit(function_block_declaration_c *symbol);
+
+}; // function_param_iterator_c
+
+
+
+
+
+
+
--- a/absyntax_utils/decompose_var_instance_name.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/decompose_var_instance_name.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -60,6 +60,16 @@
   return res;
 }
 
+
+/*************************/
+/* B.1 - Common elements */
+/*************************/
+/*******************************************/
+/* B 1.1 - Letters, digits and identifiers */
+/*******************************************/
+/* sometimes (e.g. FB calls) the name of the variable is stored directly in an identifier_c object */
+void *decompose_var_instance_name_c::visit(identifier_c *symbol) {return (void *)symbol;}
+
 /*********************/
 /* B 1.4 - Variables */
 /*********************/
--- a/absyntax_utils/decompose_var_instance_name.hh	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/decompose_var_instance_name.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -56,11 +56,19 @@
     symbol_c *next_part(void);
 
   private:
+  /*************************/
+  /* B.1 - Common elements */
+  /*************************/
+  /*******************************************/
+  /* B 1.1 - Letters, digits and identifiers */
+  /*******************************************/
+    void *visit(identifier_c *symbol);
+
   /*********************/
   /* B 1.4 - Variables */
   /*********************/
     void *visit(symbolic_variable_c *symbol);
-  
+
   /********************************************/
   /* B.1.4.1   Directly Represented Variables */
   /********************************************/
--- a/absyntax_utils/function_call_iterator.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/function_call_iterator.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -32,8 +32,7 @@
  */
 
 /* given a function_body_c, iterate through each
- * function in/out/inout parameter, returning the name
- * of each parameter...
+ * function/FB call in that code.
  */
 
 
--- a/absyntax_utils/function_call_iterator.hh	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/function_call_iterator.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -37,9 +37,9 @@
 
 
 /* given a function_body_c, iterate through each
- * function in/out/inout parameter, returning the name
- * of each parameter...
+ * function/FB call in that code.
  */
+
 class function_call_iterator_c : public iterator_visitor_c {
 
   private:
--- a/absyntax_utils/function_call_param_iterator.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/function_call_param_iterator.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -24,15 +24,16 @@
 
 /*
  * Function call parameter iterator.
- * It will iterate through the formal parameters of a function call
+ * It will iterate through the non-formal parameters of a function call
  * (i.e. function calls using the foo(<param1>, <param2>, ...) syntax).
- * and/or search through the non-formal parameters of a function call
+ * and/or search through the formal parameters of a function call
  * (i.e. function calls using the foo(<name1> = <param1>, <name2> = <param2>, ...) syntax).
  *
  * Calls to function blocks and programs are also supported.
  *
- * Note that calls to next() will only iterate through formal parameters,
- * and calls to search()  will only serach through non-formal parameters.
+ * Note that calls to next_nf() will only iterate through non-formal parameters,
+ * calls to next_f() will only iterate through formal parameters,
+ * and calls to search_f() will only serach through formal parameters.
  */
 
 
@@ -58,7 +59,7 @@
 
 void *function_call_param_iterator_c::search_list(list_c *list) {
   switch (current_operation) {
-    case iterate_op:
+    case iterate_nf_op:
       for(int i = 0; i < list->n; i++) {
         void *res = list->elements[i]->accept(*this);
         if (NULL != res) {
@@ -69,7 +70,7 @@
           /* we do nothing... */
         } else {
           param_count++;
-          if (param_count == next_param) {
+          if (param_count == iterate_nf_next_param) {
             return list->elements[i];
           }
         }
@@ -77,7 +78,26 @@
       return NULL;
       break;
 
-    case search_op:
+    case iterate_f_op:
+      for(int i = 0; i < list->n; i++) {
+        void *res = list->elements[i]->accept(*this);
+        if (NULL != res) {
+          /* It went through the handle_parameter_assignment() function,
+           * and is therefore a parameter assignment (<param> = <value>),
+           * and not a simple expression (<value>).
+           */
+          param_count++;
+          if (param_count == iterate_f_next_param) {
+            return res;
+          }
+        } else {
+          /* we do nothing... */
+        }
+      }
+      return NULL;
+      break;
+
+    case search_f_op:
       for(int i = 0; i < list->n; i++) {
         void *res = list->elements[i]->accept(*this);
         if (res != NULL)
@@ -93,28 +113,21 @@
 
 void *function_call_param_iterator_c::handle_parameter_assignment(symbol_c *variable_name, symbol_c *expression) {
   switch (current_operation) {
-    case iterate_op:
+    case iterate_nf_op:
           /* UGLY HACK -> this will be detected in the search_list() function */
-      return (void *)this; /* anything, as long as it is not NULL!! */
+      return (void *)variable_name; /* anything, as long as it is not NULL!! */
       break;
 
-    case search_op:
+    case iterate_f_op:
+      current_value = expression;
+      return (void *)variable_name;
+      break;
+
+    case search_f_op:
       identifier_c *variable_name2 = dynamic_cast<identifier_c *>(variable_name);
-      
-      if (variable_name2 == NULL) {
-        en_param_c *en_param = dynamic_cast<en_param_c *>(variable_name);
-        if (en_param != NULL)
-          variable_name2 = new identifier_c("EN");
-      }
-      
-      if (variable_name2 == NULL) {
-        eno_param_c *eno_param = dynamic_cast<eno_param_c *>(variable_name);
-        if (eno_param != NULL)
-          variable_name2 = new identifier_c("ENO");
-      }
-      
+
       if (variable_name2 == NULL) ERROR;
-      
+
       if (strcasecmp(search_param_name->value, variable_name2->value) == 0)
         /* FOUND! This is the same parameter!! */
         return (void *)expression;
@@ -129,7 +142,9 @@
 
 /* start off at the first parameter once again... */
 void function_call_param_iterator_c::reset(void) {
-  next_param = param_count = 0;
+  iterate_nf_next_param = 0;
+  iterate_f_next_param  = 0;
+  param_count = 0;
 }
 
 /* initialise the iterator object.
@@ -150,32 +165,58 @@
   reset();
 }
 
-/* Skip to the next parameter. After object creation,
+/* Skip to the next formal parameter. After object creation,
  * the object references on parameter _before_ the first, so
  * this function must be called once to get the object to
  * reference the first parameter...
  *
- * Returns whatever is being passed to the parameter!
- */
-symbol_c *function_call_param_iterator_c::next(void) {
+ * Returns the paramater name to which a value is being passed!
+ * You can determine the value being passed by calling 
+ * function_call_param_iterator_c::search_f()
+ */
+symbol_c *function_call_param_iterator_c::next_f(void) {
+  current_value = NULL;
   param_count = 0;
-  next_param++;
-  current_operation = function_call_param_iterator_c::iterate_op;
+  iterate_f_next_param++;
+  current_operation = function_call_param_iterator_c::iterate_f_op;
   void *res = f_call->accept(*this);
   return (symbol_c *)res;
 }
 
+
+/* Skip to the next non-formal parameter. After object creation,
+ * the object references on parameter _before_ the first, so
+ * this function must be called once to get the object to
+ * reference the first parameter...
+ *
+ * Returns whatever is being passed to the parameter!
+ */
+symbol_c *function_call_param_iterator_c::next_nf(void) {
+  current_value = NULL;
+  param_count = 0;
+  iterate_nf_next_param++;
+  current_operation = function_call_param_iterator_c::iterate_nf_op;
+  void *res = f_call->accept(*this);
+  current_value = (symbol_c *)res;
+  return (symbol_c *)res;
+}
+
 /* Search for the value passed to the parameter named <param_name>...  */
-symbol_c *function_call_param_iterator_c::search(symbol_c *param_name) {
+symbol_c *function_call_param_iterator_c::search_f(symbol_c *param_name) {
+  current_value = NULL;
   if (NULL == param_name) ERROR;
   search_param_name = dynamic_cast<identifier_c *>(param_name);
   if (NULL == search_param_name) ERROR;
-  current_operation = function_call_param_iterator_c::search_op;
+  current_operation = function_call_param_iterator_c::search_f_op;
   void *res = f_call->accept(*this);
+  current_value = (symbol_c *)res;
   return (symbol_c *)res;
 }
 
-
+/* Returns the value being passed to the current parameter. */
+symbol_c *function_call_param_iterator_c::get_current_value(void) {
+  return current_value;
+}
 
 /********************************/
 /* B 1.7 Configuration elements */
@@ -403,7 +444,7 @@
   // since we do not yet support it, it is best to simply stop than to fail silently...
   if (NULL != symbol->simple_instr_list) ERROR;
 
-  return handle_parameter_assignment(symbol->il_assign_operator, symbol->il_operand);
+  return handle_parameter_assignment((symbol_c *)symbol->il_assign_operator->accept(*this), symbol->il_operand);
 }
 
 /*  il_assign_out_operator variable */
@@ -417,6 +458,13 @@
 /*******************/
 /* B 2.2 Operators */
 /*******************/
+/*  any_identifier ASSIGN */
+// SYM_REF1(il_assign_operator_c, variable_name)
+void *function_call_param_iterator_c::visit(il_assign_operator_c *symbol) {
+  TRACE("il_assign_operator_c");
+  return (void *)symbol->variable_name;
+}
+
 /*| [NOT] any_identifier SENDTO */
 // SYM_REF2(il_assign_out_operator_c, option, variable_name)
 void *function_call_param_iterator_c::visit(il_assign_out_operator_c *symbol) {
@@ -424,7 +472,7 @@
 
   // TODO : Handle not_param !!!
   // we do not yet support it, so it is best to simply stop than to fail silently...
-  if (NULL != symbol->option) ERROR;
+  // if (NULL != symbol->option) ERROR;
 
   return (void *)symbol->variable_name;
 }
@@ -444,10 +492,13 @@
 */
 void *function_call_param_iterator_c::visit(function_invocation_c *symbol) {
   TRACE("function_invocation_c");
-  if ((symbol_c *)symbol == f_call && symbol->parameter_assignment_list != NULL)
-    return symbol->parameter_assignment_list->accept(*this);
-  else
-    return NULL;
+  /* 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) return symbol->   formal_param_list->accept(*this);
+  if (symbol->nonformal_param_list != NULL) return symbol->nonformal_param_list->accept(*this);
+
+  return NULL;
 }
 
 
@@ -474,10 +525,14 @@
 // SYM_REF2(fb_invocation_c, fb_name, param_assignment_list)
 void *function_call_param_iterator_c::visit(fb_invocation_c *symbol) {
   TRACE("fb_invocation_c");
-  if (symbol->param_assignment_list != NULL)
-    return symbol->param_assignment_list->accept(*this);
-  else
-    return NULL;
+  /* If the syntax parser is working correctly, only one of the 
+   * following two symbols will be != NULL.
+   * However, both may be NULL simultaneously!
+   */
+  if (symbol->   formal_param_list != NULL) return symbol->   formal_param_list->accept(*this);
+  if (symbol->nonformal_param_list != NULL) return symbol->nonformal_param_list->accept(*this);
+
+  return NULL;
 }
 
 /* helper symbol for fb_invocation */
--- a/absyntax_utils/function_call_param_iterator.hh	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/function_call_param_iterator.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -24,15 +24,16 @@
 
 /*
  * Function call parameter iterator.
- * It will iterate through the formal parameters of a function call
+ * It will iterate through the non-formal parameters of a function call
  * (i.e. function calls using the foo(<param1>, <param2>, ...) syntax).
- * and/or search through the non-formal parameters of a function call
+ * and/or search through the formal parameters of a function call
  * (i.e. function calls using the foo(<name1> = <param1>, <name2> = <param2>, ...) syntax).
  *
  * Calls to function blocks and programs are also supported.
  *
- * Note that calls to next() will only iterate through formal parameters,
- * and calls to search()  will only serach through non-formal parameters.
+ * Note that calls to next_nf() will only iterate through non-formal parameters,
+ * calls to next_f() will only iterate through formal parameters,
+ * and calls to search_f() will only serach through formal parameters.
  */
 
 
@@ -46,13 +47,16 @@
        * (or function block or program call!)
        */
     symbol_c *f_call;
-    int next_param, param_count;
+    int iterate_f_next_param, iterate_nf_next_param, param_count;
     identifier_c *search_param_name;
-
-    /* Which operation of the class was called...
-     * Search a parameter, or iterate to the next parameter.
+    symbol_c *current_value;
+
+    /* Which operation of the class was called:
+     *  - iterate to the next non-formal parameter. 
+     *  - iterate to the next formal parameter. 
+     *  - search a formal parameter, 
      */
-    typedef enum {iterate_op, search_op} operation_t;
+    typedef enum {iterate_nf_op, iterate_f_op, search_f_op} operation_t;
     operation_t current_operation;
 
   private:
@@ -70,17 +74,31 @@
      */
     function_call_param_iterator_c(symbol_c *f_call);
 
-    /* Skip to the next parameter. After object creation,
+    /* Skip to the next formal parameter. After object creation,
+     * the object references on parameter _before_ the first, so
+     * this function must be called once to get the object to
+     * reference the first parameter...
+     *
+     * Returns the paramater name to which a value is being passed!
+     * You can determine the value being passed by calling 
+     * function_call_param_iterator_c::search_f()
+     */
+    symbol_c *next_f(void);
+
+    /* Skip to the next non-formal parameter. After object creation,
      * the object references on parameter _before_ the first, so
      * this function must be called once to get the object to
      * reference the first parameter...
      *
      * Returns whatever is being passed to the parameter!
      */
-    symbol_c *next(void);
+    symbol_c *next_nf(void);
 
     /* Search for the value passed to the parameter named <param_name>...  */
-    symbol_c *search(symbol_c *param_name);
+    symbol_c *search_f(symbol_c *param_name);
+
+    /* Returns the value being passed to the current parameter. */
+    symbol_c *get_current_value(void);
 
 
   private:
@@ -254,6 +272,10 @@
   /*******************/
   /* B 2.2 Operators */
   /*******************/
+  /*  any_identifier ASSIGN */
+  // SYM_REF1(il_assign_operator_c, variable_name)
+    void *visit(il_assign_operator_c *symbol);
+
   /*| [NOT] any_identifier SENDTO */
   // SYM_REF2(il_assign_out_operator_c, option, variable_name)
     void *visit(il_assign_out_operator_c *symbol);
--- a/absyntax_utils/function_param_iterator.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/function_param_iterator.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -60,21 +60,51 @@
 
 
 void* function_param_iterator_c::handle_param_list(list_c *list) {
-  if (next_param <= param_count + list->n)
-    return list->elements[next_param - param_count - 1];
-
-  /* the desired param is not on this list... */
-  param_count += list->n;
- return NULL;
+  switch (current_operation) {
+    case iterate_op:
+      if (next_param <= param_count + list->n)
+        return list->elements[next_param - param_count - 1];
+
+      /* the desired param is not on this list... */
+      param_count += list->n;
+      break;
+
+    case search_op:
+      for(int i = 0; i < list->n; i++) {
+        identifier_c *variable_name = dynamic_cast<identifier_c *>(list->elements[i]);
+        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;
+      }
+      break;
+  } /* switch */
+
+  /* Not found! */
+  return NULL;
 }
 
 void* function_param_iterator_c::handle_single_param(symbol_c *var_name) {
-  param_count++;
-  if (next_param == param_count)
-    return var_name;
-
-  /* not yet the desired param... */
- return NULL;
+  switch (current_operation) {
+    case iterate_op:
+      param_count++;
+      if (next_param == param_count)
+        return var_name;
+      break;
+
+    case search_op:
+      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;
+      break;
+  } /* switch */
+
+  /* Not found! */
+  return NULL;
 }
 
 void* function_param_iterator_c::iterate_list(list_c *list) {
@@ -92,36 +122,30 @@
   next_param = param_count = 0;
   current_param_name = NULL;
   current_param_type = current_param_default_value = NULL;
-  en_declared = false;
-  eno_declared = false;
-}
+}
+
 
 /* initialise the iterator object.
- * We must be given a reference to the function declaration
+ * We must be given a reference to one of the following
+ *     - function_declaration_c
+ *     - function_block_declaration_c
+ *     - program_declaration_c
  * that will be analysed...
  */
-function_param_iterator_c::function_param_iterator_c(function_declaration_c *f_decl) {
-  this->f_decl = f_decl;
+function_param_iterator_c::function_param_iterator_c(symbol_c *pou_decl) {
+  /* do some consistency checks... */
+  function_declaration_c       * f_decl = dynamic_cast<function_declaration_c       *>(pou_decl);
+  function_block_declaration_c *fb_decl = dynamic_cast<function_block_declaration_c *>(pou_decl);
+  program_declaration_c        * p_decl = dynamic_cast<program_declaration_c        *>(pou_decl);
+
+  if ((NULL == f_decl) && (NULL == fb_decl) && (NULL == p_decl)) ERROR;
+
+  /* OK. Now initialise this object... */
+  this->f_decl = pou_decl;
   reset();
 }
 
-/* initialise the iterator object.
- * We must be given a reference to the function block declaration
- * that will be analysed...
- */
-function_param_iterator_c::function_param_iterator_c(function_block_declaration_c *fb_decl) {
-  this->f_decl = fb_decl;
-  reset();
-}
-
-/* initialise the iterator object.
- * We must be given a reference to the program declaration
- * that will be analysed...
- */
-function_param_iterator_c::function_param_iterator_c(program_declaration_c *p_decl) {
-  this->f_decl = p_decl;
-  reset();
-}
+
 
 /* Skip to the next parameter. After object creation,
  * the object references on parameter _before_ the first, so
@@ -133,44 +157,31 @@
 identifier_c *function_param_iterator_c::next(void) {
   void *res;
   identifier_c *identifier;
+ 
   param_count = 0;
   next_param++;
+  current_operation = function_param_iterator_c::iterate_op;
   res = f_decl->accept(*this);
-  if (res != NULL) {
-    symbol_c *sym = (symbol_c *)res;
-    identifier = dynamic_cast<identifier_c *>(sym);
-    if (identifier == NULL)
-      ERROR;
-  }
-  else if (!en_declared) {
-    current_param_direction = direction_in;
-    identifier = declare_en_param();
-  }
-  else if (!eno_declared) {
-    current_param_direction = direction_out;
-    identifier = declare_eno_param();
-  }
-  else
+  if (res == NULL) 
     return NULL;
-  
+
+  symbol_c *sym = (symbol_c *)res;
+  identifier = dynamic_cast<identifier_c *>(sym);
+  if (identifier == NULL)
+    ERROR;
   current_param_name = identifier;
   return current_param_name;
 }
 
-identifier_c *function_param_iterator_c::declare_en_param(void) {
-  en_declared = true;
-  identifier_c *identifier = new identifier_c("EN");
-  current_param_type = (symbol_c*)(new bool_type_name_c());
-  current_param_default_value = (symbol_c*)(new boolean_literal_c(current_param_type, new boolean_true_c()));
-  return identifier;
-}
-
-identifier_c *function_param_iterator_c::declare_eno_param(void) {
-  eno_declared = true;
-  identifier_c *identifier = new identifier_c("ENO");
-  current_param_type = (symbol_c*)(new bool_type_name_c());
-  current_param_default_value = NULL;
-  return identifier;
+/* Search for the value passed to the parameter named <param_name>...  */
+identifier_c *function_param_iterator_c::search(symbol_c *param_name) {
+  if (NULL == param_name) ERROR;
+  search_param_name = dynamic_cast<identifier_c *>(param_name);
+  if (NULL == search_param_name) ERROR;
+  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);
+  return res_param_name;
 }
 
 /* Returns the currently referenced parameter's default value,
@@ -207,8 +218,16 @@
 
 void *function_param_iterator_c::visit(en_param_declaration_c *symbol) {
   TRACE("en_param_declaration_c");
-  if (en_declared) ERROR;
-  return (void *)declare_en_param();
+  /* It is OK to store these values in the current_param_XXX
+   * variables, because if the desired parameter is not in the
+   * variable list we will be analysing, the current_param_XXXX
+   * variables will get overwritten when we visit the next
+   * var1_init_decl_c list!
+   */
+  current_param_default_value = symbol->value;
+  current_param_type = symbol->type;
+
+  return handle_single_param(symbol->name);
 }
 
 /* var1_list ':' array_spec_init */
@@ -226,8 +245,20 @@
 }
 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
+   * variables, because if the desired parameter is not in the
+   * variable list we will be analysing, the current_param_XXXX
+   * variables will get overwritten when we visit the next
+   * var1_init_decl_c list!
+   */
+  current_param_default_value = NULL;
+  current_param_type = symbol->type;
+
+  return handle_single_param(symbol->name);
+#if 0
   if (eno_declared) ERROR;
   return (void *)declare_eno_param();
+#endif
 }
 void *function_param_iterator_c::visit(input_output_declarations_c *symbol) {
   TRACE("input_output_declarations_c");
--- a/absyntax_utils/function_param_iterator.hh	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/function_param_iterator.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -69,17 +69,23 @@
 
 
   private:
-      /* a pointer to the function_block_declaration_c
-       * or function_declaration_c currently being analysed.
-       */
+    /* a pointer to the function_block_declaration_c
+    * or function_declaration_c currently being analysed.
+    */
     symbol_c *f_decl;
     int next_param, param_count;
+    /* used when called to search() for a parameter by name */
+    identifier_c *search_param_name;
+    /* used when called to iterate() for a parameter */
     identifier_c *current_param_name;
     symbol_c *current_param_type;
     symbol_c *current_param_default_value;
     param_direction_t current_param_direction;
-    bool en_declared;
-    bool eno_declared;
+    /* Which operation of the class was called...
+     * Search a parameter, or iterate to the next parameter.
+     */
+    typedef enum {iterate_op, search_op} operation_t;
+    operation_t current_operation;
 
   private:
     void* handle_param_list(list_c *list);
@@ -92,22 +98,13 @@
     void reset(void);
 
     /* initialise the iterator object.
-     * We must be given a reference to the function declaration
+     * We must be given a reference to one of the following
+     *     - function_declaration_c
+     *     - function_block_declaration_c
+     *     - program_declaration_c
      * that will be analysed...
      */
-    function_param_iterator_c(function_declaration_c *f_decl);
-
-    /* initialise the iterator object.
-     * We must be given a reference to the function block declaration
-     * that will be analysed...
-     */
-    function_param_iterator_c(function_block_declaration_c *fb_decl);
-
-    /* initialise the iterator object.
-     * We must be given a reference to the program declaration
-     * that will be analysed...
-     */
-    function_param_iterator_c(program_declaration_c *p_decl);
+    function_param_iterator_c(symbol_c *pou_decl);
 
     /* Skip to the next parameter. After object creation,
      * the object references on parameter _before_ the first, so
@@ -118,9 +115,13 @@
      */
     identifier_c *next(void);
 
-    identifier_c *declare_en_param(void);
-
-    identifier_c *declare_eno_param(void);
+    /* Search for the parameter named <param_name>...  */
+    /* 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.
+     */
+    identifier_c *search(symbol_c *param_name);
 
     /* Returns the currently referenced parameter's default value,
      * or NULL if none is specified in the function declrataion itself.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax_utils/get_sizeof_datatype.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -0,0 +1,363 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+/* Determine the size, in bits, of the data type.
+ * 
+ * NOTE: Currently, only elementary data types with well defined sizes (in the standard) are supported.
+ *       - derived data types are not supported, and these will return 0
+ *       - TIME, DATE, TIME_OF_DAY, and DATE_AND_TIME are not supported, and will return 0
+ *       - STRING and WSTRING are not supported, and the standard merely defines bit per character,
+ *              and not the maximum number of characters, so these will return 0
+ *
+ *       We also support the 'Numeric Literals' Data types.
+ *       i.e., numeric literals are considerd basic data types
+ *       as their data type is undefined (e.g. the datat type of '30'
+ *       could be 'INT' or 'SINT' or 'LINT' or 'USINT' or ...
+ *       NOTE: for base 10 numeric literals, any number taking up more than 64 bits
+ *             will only return a bitsize of 1024!
+ *
+ *       For numeric literals, we return the minimum number of bits
+ *       required to store the value.
+ *
+ * E.g. TYPE new_int_t : INT; END_TYPE;
+ *      TYPE new_int2_t : INT = 2; END_TYPE;
+ *      TYPE new_subr_t : INT (4..5); END_TYPE;
+ *
+ *    sizeof(SINT) ->  8
+ *    sizeof(INT)  -> 16
+ *    sizeof(DINT) -> 32
+ *    sizeof(LINT) -> 64
+ *
+ *    sizeof('1')       ->  1
+ *    sizeof('015')     ->  4    # Leading zeros are ignored!
+ *    sizeof('0')       ->  1    # This is a special case! Even the value 0 needs at least 1 bit to store!
+ *    sizeof('16')      ->  5
+ *    sizeof('2#00101') ->  3
+ *    sizeof('8#334')   ->  9
+ *    sizeof('16#2A')   ->  8
+ *
+ *    sizeof('7.4')     ->  32   # all real literals return 32 bits, the size of a 'REAL'
+ *                               # TODO: study IEC 60559 for the range of values that may be
+ *                               #       stored in a REAL (basic single width floating point format)
+ *                               #       and in a LREAL (basic double width floating point format)
+ *                               #       and see if some real literals need to return 64 instead!
+ */
+
+#include "get_sizeof_datatype.hh"
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>  // get definition of ULLONG_MAX
+/* tell stdint.h we want the definition of UINT64_MAX */
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>  // get definition of uint64_t and UINT64_MAX
+
+
+#define ERROR error_exit(__FILE__,__LINE__)
+/* function defined in main.cc */
+extern void error_exit(const char *file_name, int line_no);
+
+
+/* This class is a singleton.
+ * So we need a pointer to the singe instance...
+ */
+get_sizeof_datatype_c *get_sizeof_datatype_c::singleton = NULL;
+
+
+#define _encode_int(value)   ((void *)(((char *)NULL) + value))
+#define _decode_int(ptr)     (((char *)ptr) - ((char *)NULL))
+
+
+
+
+/* divide a base 10 literal in a string by 2 */
+/* returns remainder of division (0 or 1)    */
+static int strdivby2(char **strptr) {
+  char *str = *strptr;
+  int carry = 0;
+
+  while (*str != '\0') {
+    /* Assumes ASCII */
+    int newcarry;
+//     newcarry = ((*str-'0') mod 2);
+    newcarry = ((*str-'0') - ((*str-'0')/2)*2);
+    *str = (((*str-'0') + 10*carry)/2) + '0';
+    carry = newcarry;
+    str++;
+  }
+
+  /* ignore leading zeros in result... */
+  while (**strptr == '0') 
+    (*strptr)++;
+
+  return carry;
+}
+
+
+/* Constructor for the singleton class */
+int get_sizeof_datatype_c::getsize(symbol_c *data_type_symbol) {
+      if (NULL == singleton) {
+        singleton = new get_sizeof_datatype_c;
+        if (NULL == singleton)
+          ERROR;
+      }
+      return _decode_int(data_type_symbol->accept(*singleton));
+    }
+
+/* Destructor for the singleton class */
+get_sizeof_datatype_c::~get_sizeof_datatype_c(void) {
+      if (NULL != singleton) delete singleton;
+      singleton = NULL;
+    }
+
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+
+/******************************/
+/* B 1.2.1 - Numeric Literals */
+/******************************/
+ /* Numeric literals without any explicit type cast have unknown data type, 
+  * so we continue considering them as their own basic data types until
+  * they can be resolved (for example, when using '30+x' where 'x' is a LINT variable, the
+  * numeric literal '30' must then be considered a LINT so the ADD function may be called
+  * with all inputs of the same data type.
+  * If 'x' were a SINT, then the '30' would have to be a SINT too!
+  */
+
+/* NOTE: all integer and real literal tokens will always be positive (i.e. no leading '-')
+ * due to the way the source code is parsed by iec.flex.
+ */
+void *get_sizeof_datatype_c::visit(real_c *symbol) {
+  return _encode_int(32);
+}
+
+/* NOTE: all integer and real literal tokens will always be positive (i.e. no leading '-')
+ * due to the way the source code is parsed by iec.flex.
+ */
+void *get_sizeof_datatype_c::visit(integer_c *symbol) {
+  int bitsize = 0;
+
+  if (NULL ==   symbol->value ) ERROR;
+  if ('\0' == *(symbol->value)) ERROR;
+
+#if 0
+  char *endptr;
+  /* Convert the string to an unsigned 64 bit integer */
+  /* We can use strtoull(), but we are not guaranteed that an unsigned long long int
+   * is 64 bits wide. First make sure that it is...
+   *
+   * We could also use the strtouq() instead, which converts
+   * to a quad word (64 bits). However, this requires either GCC or BSD extensions.
+   */
+  #ifdef strtoull // this ifdef does not work!!
+    /* we have long long int, use it... */
+    #define ival_MAX ULLONG_MAX
+    unsigned long long int ival = 0;
+    ival = strtoull (symbol->value, &endptr, 10 /* base */);
+  #else
+    /* use long int ... */
+    #define ival_MAX ULONG_MAX
+    unsigned long int ival = 0;
+    ival = strtoul (symbol->value, &endptr, 10 /* base */);
+  #endif
+
+  #if (ival_MAX < UINT64_MAX)
+  #error Largest strtoint() conversion function converts to an int less than 64 bits wide!
+  #endif
+
+  if (NULL ==  endptr) ERROR;
+  if ('\0' != *endptr) ERROR;
+  // TODO: return _encode_int(1024) if value takes up more than 64 bits! 
+
+  /* determine the number of bits used... */
+  for (bitsize = 0; ival > 0; ival /= 2, bitsize++);
+
+  /* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */
+  if (0 == bitsize) bitsize = 1;
+
+  return _encode_int(bitsize);
+#endif
+  /* We could first convert from string to some kind of integer, and then
+   * determine the the bitsize using integer aritmetic.
+   * However, we are then limited to the bit size of the widest available integer
+   * (usually 64 bits), which is not good at all!
+   */
+  /* Let's try to determine bitsize by converting directly from the string!! */
+  char *sval = strdup(symbol->value);
+  char *oval = sval;
+  if (NULL ==  sval) ERROR;
+  if ('\0' == *sval) ERROR;
+
+  for (bitsize = 0; *sval != '\0'; strdivby2(&sval), bitsize ++);
+
+  /* Even for (value == 0), the above loop will return bitsize == 1!, 
+   * so we don't need to handle the special case...
+   */
+  /* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */
+  // if (0 == bitsize) bitsize = 1;
+
+  free(oval);
+  return _encode_int(bitsize);
+}
+
+
+/* NOTE: all integer and real literal tokens will always be positive (i.e. no leading '-')
+ * due to the way the source code is parsed by iec.flex.
+ */
+void *get_sizeof_datatype_c::visit(binary_integer_c *symbol) {
+  const char *sval = symbol->value;
+  int bitsize = 0;
+
+  /* first 2 characters had better be "2#" ! */
+  if (NULL ==  sval) ERROR;
+  if ('\0' == *sval) ERROR;
+  if ( '2' != *sval) ERROR;
+  sval++;
+  if ('\0' == *sval) ERROR;
+  if ( '#' != *sval) ERROR;
+  sval++;
+  if ('\0' == *sval) ERROR;
+
+  /* determine the number of bits used... */
+  for (bitsize = 0; '\0' != *sval; sval++, bitsize++) {
+    /* consistency check: make sure we only have binary digits! */
+    if (('0' != *sval) && ('1' != *sval))
+      ERROR;
+  }
+
+  /* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */
+  if (0 == bitsize) bitsize = 1;
+
+  return _encode_int(bitsize);
+}
+
+
+/* NOTE: all integer and real literal tokens will always be positive (i.e. no leading '-')
+ * due to the way the source code is parsed by iec.flex.
+ */
+void *get_sizeof_datatype_c::visit(octal_integer_c *symbol) {
+  const char *sval = symbol->value;
+  int bitsize = 0;
+
+  /* first 2 characters had better be "8#" ! */
+  if (NULL ==  sval) ERROR;
+  if ('\0' == *sval) ERROR;
+  if ( '8' != *sval) ERROR;
+  sval++;
+  if ('\0' == *sval) ERROR;
+  if ( '#' != *sval) ERROR;
+  sval++;
+  if ('\0' == *sval) ERROR;
+
+  /* determine the number of bits used... */
+  for (bitsize = 0; '\0' != *sval; sval++, bitsize += 3 /* 3 bits per octal digit */) {
+    /* consistency check: make sure we only have octal digits! */
+    /* Assumes ASCII */
+    if (('0' > *sval) || ('7' < *sval))
+      ERROR;
+  }
+
+  /* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */
+  if (0 == bitsize) bitsize = 1;
+
+  return _encode_int(bitsize);
+}
+
+
+/* NOTE: all integer and real literal tokens will always be positive (i.e. no leading '-')
+ * due to the way the source code is parsed by iec.flex.
+ */
+void *get_sizeof_datatype_c::visit(hex_integer_c *symbol) {
+  const char *sval = symbol->value;
+  int bitsize = 0;
+
+  /* first 3 characters had better be "16#" ! */
+  if (NULL ==  sval) ERROR;
+  if ('\0' == *sval) ERROR;
+  if ( '1' != *sval) ERROR;
+  sval++;
+  if ('\0' == *sval) ERROR;
+  if ( '6' != *sval) ERROR;
+  sval++;
+  if ('\0' == *sval) ERROR;
+  if ( '#' != *sval) ERROR;
+  sval++;
+  if ('\0' == *sval) ERROR;
+
+  /* determine the number of bits used... */
+  for (bitsize = 0; '\0' != *sval; sval++, bitsize += 4 /* 4 bits per hex digit */) {
+    /* consistency check: make sure we only have hex digits! */
+    /* Assumes ASCII */
+    if (!(('0' <= *sval) && ('9' >= *sval)) && 
+        !(('A' <= *sval) && ('F' >= *sval)) &&
+        !(('a' <= *sval) && ('b' >= *sval)))
+      ERROR;
+  }
+
+  /* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */
+  if (0 == bitsize) bitsize = 1;
+
+  return _encode_int(bitsize);
+}
+
+
+/***********************************/
+/* B 1.3.1 - Elementary Data Types */
+/***********************************/
+// void *get_sizeof_datatype_c::visit(time_type_name_c *symbol)	{return _encode_int(0); }
+void *get_sizeof_datatype_c::visit(bool_type_name_c *symbol)	{return _encode_int(1); }
+void *get_sizeof_datatype_c::visit(sint_type_name_c *symbol)	{return _encode_int(8); }
+void *get_sizeof_datatype_c::visit(int_type_name_c *symbol)	{return _encode_int(16);}
+void *get_sizeof_datatype_c::visit(dint_type_name_c *symbol)	{return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(lint_type_name_c *symbol)	{return _encode_int(64);}
+void *get_sizeof_datatype_c::visit(usint_type_name_c *symbol)	{return _encode_int(8); }
+void *get_sizeof_datatype_c::visit(uint_type_name_c *symbol)	{return _encode_int(16);}
+void *get_sizeof_datatype_c::visit(udint_type_name_c *symbol)	{return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(ulint_type_name_c *symbol)	{return _encode_int(64);}
+void *get_sizeof_datatype_c::visit(real_type_name_c *symbol)	{return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(lreal_type_name_c *symbol)	{return _encode_int(64);}
+// void *get_sizeof_datatype_c::visit(date_type_name_c *symbol)	{return _encode_int(0); }
+// void *get_sizeof_datatype_c::visit(tod_type_name_c *symbol)	{return _encode_int(0); }
+// void *get_sizeof_datatype_c::visit(dt_type_name_c *symbol)	{return _encode_int(0); }
+void *get_sizeof_datatype_c::visit(byte_type_name_c *symbol)	{return _encode_int(8); }
+void *get_sizeof_datatype_c::visit(word_type_name_c *symbol)	{return _encode_int(16);}
+void *get_sizeof_datatype_c::visit(dword_type_name_c *symbol)	{return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(lword_type_name_c *symbol)	{return _encode_int(64);}
+// void *get_sizeof_datatype_c::visit(string_type_name_c *symbol)	{return _encode_int(0); }
+// void *get_sizeof_datatype_c::visit(wstring_type_name_c *symbol)	{return _encode_int(0); }
+/******************************************************/
+/* Extensions to the base standard as defined in      */
+/* "Safety Software Technical Specification,          */
+/*  Part 1: Concepts and Function Blocks,             */
+/*  Version 1.0 – Official Release"                   */
+/* by PLCopen - Technical Committee 5 - 2006-01-31    */
+/******************************************************/
+void *get_sizeof_datatype_c::visit(safebool_type_name_c *symbol)	{return _encode_int(1);}
+
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+// Not yet supported...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax_utils/get_sizeof_datatype.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -0,0 +1,212 @@
+/*
+ * (c) 2009 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/* Determine the size, in bits, of the data type.
+ * 
+ * NOTE: Currently, only elementary data types with well defined sizes (in the standard) are supported.
+ *       - derived data types are not supported, and these will return 0
+ *       - TIME, DATE, TIME_OF_DAY, and DATE_AND_TIME are not supported, and will return 0
+ *       - STRING and WSTRING are not supported, and the standard merely defines bit per character,
+ *              and not the maximum number of characters, so these will return 0
+ *
+ *       We also support the 'Numeric Literals' Data types.
+ *       i.e., numeric literals are considerd basic data types
+ *       as their data type is undefined (e.g. the datat type of '30'
+ *       could be 'INT' or 'SINT' or 'LINT' or 'USINT' or ...
+ *
+ *       For numeric literals, we return the minimum number of bits
+ *       required to store the value.
+ *
+ * E.g. TYPE new_int_t : INT; END_TYPE;
+ *      TYPE new_int2_t : INT = 2; END_TYPE;
+ *      TYPE new_subr_t : INT (4..5); END_TYPE;
+ *
+ *    sizeof(SINT) ->  8
+ *    sizeof(INT)  -> 16
+ *    sizeof(DINT) -> 32
+ *    sizeof(LINT) -> 64
+ *
+ *    sizeof('1')       ->  1
+ *    sizeof('015')     ->  4    # Leading zeros are ignored!
+ *    sizeof('0')       ->  1    # This is a special case! Even the value 0 needs at least 1 bit to store!
+ *    sizeof('16')      ->  5
+ *    sizeof('2#00101') ->  3
+ *    sizeof('8#334')   ->  9
+ *    sizeof('16#2A')   ->  8
+ *
+ *    sizeof('7.4')     ->  32   # all real literals return 32 bits, the size of a 'REAL'
+ *                               # TODO: study IEC 60559 for the range of values that may be
+ *                               #       stored in a REAL (basic single width floating point format)
+ *                               #       and in a LREAL (basic double width floating point format)
+ *                               #       and see if some real literals need to return 64 instead!
+ */
+
+#include "../absyntax/visitor.hh"
+
+class get_sizeof_datatype_c: public null_visitor_c {
+
+  public:
+    static int getsize(symbol_c *data_type_symbol);
+    ~get_sizeof_datatype_c(void);
+
+  private:
+    /* this class is a singleton. So we need a pointer to the single instance... */
+    static get_sizeof_datatype_c *singleton;
+
+  private:
+    /*********************/
+    /* B 1.2 - Constants */
+    /*********************/
+
+    /******************************/
+    /* B 1.2.1 - Numeric Literals */
+    /******************************/
+     /* Numeric literals without any explicit type cast have unknown data type, 
+      * so we continue considering them as their own basic data types until
+      * they can be resolved (for example, when using '30+x' where 'x' is a LINT variable, the
+      * numeric literal '30' must then be considered a LINT so the ADD function may be called
+      * with all inputs of the same data type.
+      * If 'x' were a SINT, then the '30' would have to be a SINT too!
+      */
+    void *visit(real_c *symbol);
+    void *visit(integer_c *symbol);
+    void *visit(binary_integer_c *symbol);
+    void *visit(octal_integer_c *symbol);
+    void *visit(hex_integer_c *symbol);
+
+  /***********************************/
+  /* B 1.3.1 - Elementary Data Types */
+  /***********************************/
+//     void *visit(time_type_name_c *symbol);
+    void *visit(bool_type_name_c *symbol);
+    void *visit(sint_type_name_c *symbol);
+    void *visit(int_type_name_c *symbol);
+    void *visit(dint_type_name_c *symbol);
+    void *visit(lint_type_name_c *symbol);
+    void *visit(usint_type_name_c *symbol);
+    void *visit(uint_type_name_c *symbol);
+    void *visit(udint_type_name_c *symbol);
+    void *visit(ulint_type_name_c *symbol);
+    void *visit(real_type_name_c *symbol);
+    void *visit(lreal_type_name_c *symbol);
+//     void *visit(date_type_name_c *symbol);
+//     void *visit(tod_type_name_c *symbol);
+//     void *visit(dt_type_name_c *symbol)	;
+    void *visit(byte_type_name_c *symbol);
+    void *visit(word_type_name_c *symbol);
+    void *visit(dword_type_name_c *symbol);
+    void *visit(lword_type_name_c *symbol);
+//     void *visit(string_type_name_c *symbol);
+//     void *visit(wstring_type_name_c *symbol);
+
+    /******************************************************/
+    /* Extensions to the base standard as defined in      */
+    /* "Safety Software Technical Specification,          */
+    /*  Part 1: Concepts and Function Blocks,             */
+    /*  Version 1.0 – Official Release"                   */
+    /* by PLCopen - Technical Committee 5 - 2006-01-31    */
+    /******************************************************/
+    void *visit(safebool_type_name_c *symbol);
+
+  /********************************/
+  /* B 1.3.3 - Derived data types */
+  /********************************/
+#if 0
+  /*  simple_type_name ':' simple_spec_init */
+    void *visit(simple_type_declaration_c *symbol);
+  /* simple_specification ASSIGN constant */
+    void *visit(simple_spec_init_c *symbol);
+  /*  subrange_type_name ':' subrange_spec_init */
+    void *visit(subrange_type_declaration_c *symbol);
+  /* subrange_specification ASSIGN signed_integer */
+    void *visit(subrange_spec_init_c *symbol);
+  /*  integer_type_name '(' subrange')' */
+    void *visit(subrange_specification_c *symbol);
+  /*  signed_integer DOTDOT signed_integer */
+    void *visit(subrange_c *symbol);
+
+  /*  enumerated_type_name ':' enumerated_spec_init */
+    void *visit(enumerated_type_declaration_c *symbol);
+  /* enumerated_specification ASSIGN enumerated_value */
+    void *visit(enumerated_spec_init_c *symbol);
+  /* helper symbol for enumerated_specification->enumerated_spec_init */
+  /* enumerated_value_list ',' enumerated_value */
+    void *visit(enumerated_value_list_c *symbol);
+  /* enumerated_type_name '#' identifier */
+  // SYM_REF2(enumerated_value_c, type, value)
+    void *visit(enumerated_value_c *symbol);
+  /*  identifier ':' array_spec_init */
+    void *visit(array_type_declaration_c *symbol);
+  /* array_specification [ASSIGN array_initialization} */
+  /* array_initialization may be NULL ! */
+    void *visit(array_spec_init_c *symbol);
+  /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+    void *visit(array_specification_c *symbol);
+  /* helper symbol for array_specification */
+  /* array_subrange_list ',' subrange */
+    void *visit(array_subrange_list_c *symbol);
+  /* array_initialization:  '[' array_initial_elements_list ']' */
+  /* helper symbol for array_initialization */
+  /* array_initial_elements_list ',' array_initial_elements */
+    void *visit(array_initial_elements_list_c *symbol);
+  /* integer '(' [array_initial_element] ')' */
+  /* array_initial_element may be NULL ! */
+    void *visit(array_initial_elements_c *symbol);
+  /*  structure_type_name ':' structure_specification */
+      /* NOTE: structure_specification will point to either a
+       *       initialized_structure_c
+       *       OR A
+       *       structure_element_declaration_list_c
+       */
+    void *visit(structure_type_declaration_c *symbol);
+  /* structure_type_name ASSIGN structure_initialization */
+  /* structure_initialization may be NULL ! */
+    void *visit(initialized_structure_c *symbol);
+  /* helper symbol for structure_declaration */
+  /* structure_declaration:  STRUCT structure_element_declaration_list END_STRUCT */
+  /* structure_element_declaration_list structure_element_declaration ';' */
+    void *visit(structure_element_declaration_list_c *symbol);
+  /*  structure_element_name ':' *_spec_init */
+    void *visit(structure_element_declaration_c *symbol);
+  /* helper symbol for structure_initialization */
+  /* structure_initialization: '(' structure_element_initialization_list ')' */
+  /* structure_element_initialization_list ',' structure_element_initialization */
+    void *visit(structure_element_initialization_list_c *symbol);
+  /*  structure_element_name ASSIGN value */
+    void *visit(structure_element_initialization_c *symbol);
+  /*  string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */
+  /*
+  SYM_REF4(string_type_declaration_c,	string_type_name,
+  					elementary_string_type_name,
+  					string_type_declaration_size,
+  					string_type_declaration_init) // may be == NULL!
+  */
+    void *visit(string_type_declaration_c *symbol);
+#endif
+}; // get_sizeof_datatype_c
+
+
+
+
--- a/absyntax_utils/search_base_type.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/search_base_type.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -33,6 +33,9 @@
  *    new_int_t is really an INT!!
  *    new_int2_t is also really an INT!!
  *    new_subr_t is also really an INT!!
+ *
+ * Note that a FB declaration is also considered a base type, as
+ * we may have FB instances declared of a specific FB type.
  */
 #include "absyntax_utils.hh"
 
@@ -67,6 +70,27 @@
   return this->is_enumerated;
 }
 
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+
+/******************************/
+/* B 1.2.1 - Numeric Literals */
+/******************************/
+ /* Numeric literals without any explicit type cast have unknown data type, 
+  * so we continue considering them as their own basic data types until
+  * they can be resolved (for example, when using '30+x' where 'x' is a LINT variable, the
+  * numeric literal '30' must then be considered a LINT so the ADD function may be called
+  * with all inputs of the same data type.
+  * If 'x' were a SINT, then the '30' would have to be a SINT too!
+  */
+void *search_base_type_c::visit(real_c *symbol)          	{return (void *)symbol;}
+void *search_base_type_c::visit(integer_c *symbol)       	{return (void *)symbol;}
+void *search_base_type_c::visit(binary_integer_c *symbol)	{return (void *)symbol;}
+void *search_base_type_c::visit(octal_integer_c *symbol) 	{return (void *)symbol;}
+void *search_base_type_c::visit(hex_integer_c *symbol)   	{return (void *)symbol;}
+
+
 /***********************************/
 /* B 1.3.1 - Elementary Data Types */
 /***********************************/
@@ -91,8 +115,10 @@
 void *search_base_type_c::visit(lword_type_name_c *symbol)	{return (void *)symbol;}
 void *search_base_type_c::visit(string_type_name_c *symbol)	{return (void *)symbol;}
 void *search_base_type_c::visit(wstring_type_name_c *symbol)	{return (void *)symbol;}
-void *search_base_type_c::visit(constant_int_type_name_c *symbol)    {return (void *)symbol;}
-void *search_base_type_c::visit(constant_real_type_name_c *symbol)    {return (void *)symbol;}
+/*
+void *search_base_type_c::visit(constant_int_type_name_c *symbol)	{return (void *)symbol;}
+void *search_base_type_c::visit(constant_real_type_name_c *symbol)	{return (void *)symbol;}
+*/
 /******************************************************/
 /* Extensions to the base standard as defined in      */
 /* "Safety Software Technical Specification,          */
@@ -232,3 +258,14 @@
 */
 void *search_base_type_c::visit(string_type_declaration_c *symbol)	{return symbol;}
 
+  
+
+/*****************************/
+/* B 1.5.2 - Function Blocks */
+/*****************************/
+/*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
+// SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body)
+void *search_base_type_c::visit(function_block_declaration_c *symbol) {
+  return symbol;
+}
+
--- a/absyntax_utils/search_base_type.hh	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/search_base_type.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -34,6 +34,9 @@
  *    new_int_t is really an INT!!
  *    new_int2_t is also really an INT!!
  *    new_subr_t is also really an INT!!
+ *
+ * Note that a FB declaration is also considered a base type, as
+ * we may have FB instances declared of a specific FB type.
  */
 
 
@@ -53,6 +56,27 @@
     bool type_is_enumerated(symbol_c* type_decl);
 
   public:
+    /*********************/
+    /* B 1.2 - Constants */
+    /*********************/
+
+    /******************************/
+    /* B 1.2.1 - Numeric Literals */
+    /******************************/
+     /* Numeric literals without any explicit type cast have unknown data type, 
+      * so we continue considering them as their own basic data types until
+      * they can be resolved (for example, when using '30+x' where 'x' is a LINT variable, the
+      * numeric literal '30' must then be considered a LINT so the ADD function may be called
+      * with all inputs of the same data type.
+      * If 'x' were a SINT, then the '30' would have to be a SINT too!
+      */
+    void *visit(real_c *symbol);
+    void *visit(integer_c *symbol);
+    void *visit(binary_integer_c *symbol);
+    void *visit(octal_integer_c *symbol);
+    void *visit(hex_integer_c *symbol);
+
+
   /***********************************/
   /* B 1.3.1 - Elementary Data Types */
   /***********************************/
@@ -77,8 +101,11 @@
     void *visit(lword_type_name_c *symbol);
     void *visit(string_type_name_c *symbol);
     void *visit(wstring_type_name_c *symbol);
+
+/*
     void *visit(constant_int_type_name_c *symbol);
     void *visit(constant_real_type_name_c *symbol);
+*/
 
     /******************************************************/
     /* Extensions to the base standard as defined in      */
@@ -162,6 +189,14 @@
   					string_type_declaration_init) // may be == NULL!
   */
     void *visit(string_type_declaration_c *symbol);
+
+  /*****************************/
+  /* B 1.5.2 - Function Blocks */
+  /*****************************/
+  /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
+  // SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body)
+    void *visit(function_block_declaration_c *symbol);
+
 }; // search_base_type_c
 
 
--- a/absyntax_utils/search_constant_type.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/search_constant_type.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -51,14 +51,19 @@
 /******************************/
 /* B 1.2.1 - Numeric Literals */
 /******************************/
-void *search_constant_type_c::visit(real_c *symbol) {return (void *)&constant_real_type_name;}
-void *search_constant_type_c::visit(integer_c *symbol) {return (void *)&constant_int_type_name;}
-void *search_constant_type_c::visit(binary_integer_c *symbol) {return (void *)&constant_int_type_name;}
-void *search_constant_type_c::visit(octal_integer_c *symbol) {return (void *)&constant_int_type_name;}
-void *search_constant_type_c::visit(hex_integer_c *symbol) {return (void *)&constant_int_type_name;}
+/* Numeric literals without any explicit type cast have unknown data type, 
+  * so we continue considering them as their own basic data types until
+  * they can be resolved (for example, when using '30+x' where 'x' is a LINT variable, the
+  * numeric literal '30' must then be considered a LINT so the ADD function may be called
+  * with all inputs of the same data type.
+  * If 'x' were a SINT, then the '30' would have to be a SINT too!
+  */
+void *search_constant_type_c::visit(real_c *symbol)           {return (void *)symbol;}
+void *search_constant_type_c::visit(integer_c *symbol)        {return (void *)symbol;}
+void *search_constant_type_c::visit(binary_integer_c *symbol) {return (void *)symbol;}
+void *search_constant_type_c::visit(octal_integer_c *symbol)  {return (void *)symbol;}
+void *search_constant_type_c::visit(hex_integer_c *symbol)    {return (void *)symbol;}
 
-void *search_constant_type_c::visit(numeric_literal_c *symbol)
-  {return (void *)((symbol->type!=NULL)?symbol->type:symbol->value->accept(*this));}
 void *search_constant_type_c::visit(integer_literal_c *symbol)
   {return (void *)((symbol->type!=NULL)?symbol->type:symbol->value->accept(*this));}
 void *search_constant_type_c::visit(real_literal_c *symbol)
@@ -68,6 +73,10 @@
 void *search_constant_type_c::visit(boolean_literal_c *symbol)
   {return (void *)((symbol->type!=NULL)?symbol->type:symbol->value->accept(*this));}
 
+void *search_constant_type_c::visit(boolean_true_c *symbol)   {return (void *)symbol;}
+void *search_constant_type_c::visit(boolean_false_c *symbol)  {return (void *)symbol;}
+
+
 /*******************************/
 /* B.1.2.2   Character Strings */
 /*******************************/
@@ -103,22 +112,27 @@
 lint_type_name_c     search_constant_type_c::lint_type_name;
 dint_type_name_c     search_constant_type_c::dint_type_name;
 date_type_name_c     search_constant_type_c::date_type_name;
-dword_type_name_c     search_constant_type_c::dword_type_name;
-dt_type_name_c     search_constant_type_c::dt_type_name;
-tod_type_name_c     search_constant_type_c::tod_type_name;
-udint_type_name_c     search_constant_type_c::udint_type_name;
+dword_type_name_c    search_constant_type_c::dword_type_name;
+dt_type_name_c       search_constant_type_c::dt_type_name;
+tod_type_name_c      search_constant_type_c::tod_type_name;
+udint_type_name_c    search_constant_type_c::udint_type_name;
 word_type_name_c     search_constant_type_c::word_type_name;
-wstring_type_name_c     search_constant_type_c::wstring_type_name;
-string_type_name_c     search_constant_type_c::string_type_name;
-lword_type_name_c     search_constant_type_c::lword_type_name;
+wstring_type_name_c  search_constant_type_c::wstring_type_name;
+string_type_name_c   search_constant_type_c::string_type_name;
+lword_type_name_c    search_constant_type_c::lword_type_name;
 uint_type_name_c     search_constant_type_c::uint_type_name;
-lreal_type_name_c     search_constant_type_c::lreal_type_name;
+lreal_type_name_c    search_constant_type_c::lreal_type_name;
 byte_type_name_c     search_constant_type_c::byte_type_name;
-usint_type_name_c     search_constant_type_c::usint_type_name;
-ulint_type_name_c     search_constant_type_c::ulint_type_name;
+usint_type_name_c    search_constant_type_c::usint_type_name;
+ulint_type_name_c    search_constant_type_c::ulint_type_name;
 bool_type_name_c     search_constant_type_c::bool_type_name;
 time_type_name_c     search_constant_type_c::time_type_name;
-int_type_name_c     search_constant_type_c::int_type_name;
+int_type_name_c      search_constant_type_c::int_type_name;
 
+/*
 constant_real_type_name_c     search_constant_type_c::constant_real_type_name;
 constant_int_type_name_c      search_constant_type_c::constant_int_type_name;
+*/
+/* temporarily here until we remove the st_code_gen.c and il_code_gen.c files... */
+/* It should then move to search_expression_type_c                               */
+integer_c search_constant_type_c::integer("1");
--- a/absyntax_utils/search_constant_type.hh	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/search_constant_type.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -67,8 +67,12 @@
   static time_type_name_c     time_type_name;
   static int_type_name_c      int_type_name;
 
+/*
   static constant_real_type_name_c     constant_real_type_name;
   static constant_int_type_name_c      constant_int_type_name;
+*/
+/* temporarily here until we remove the st_code_gen.c and il_code_gen.c files... */
+  static integer_c      integer;
 
   /******************************************************/
   /* Extensions to the base standard as defined in      */
@@ -98,12 +102,14 @@
     void *visit(octal_integer_c *symbol);
     void *visit(hex_integer_c *symbol);
 
-    void *visit(numeric_literal_c *symbol);
     void *visit(integer_literal_c *symbol);
     void *visit(real_literal_c *symbol);
     void *visit(bit_string_literal_c *symbol);
     void *visit(boolean_literal_c *symbol);
 
+    void *visit(boolean_true_c *symbol);
+    void *visit(boolean_false_c *symbol);
+
     /*******************************/
     /* B.1.2.2   Character Strings */
     /*******************************/
--- a/absyntax_utils/search_expression_type.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/search_expression_type.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -65,32 +65,48 @@
 /* A helper function... */
 bool search_expression_type_c::is_string_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return true;}
-  if (typeid(*type_symbol) == typeid(string_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(string_type_name_c))  {return true;}
   if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;}
   return false;
 }
 
 /* A helper function... */
+bool search_expression_type_c::is_literal_integer_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return true;}
+  if (typeid(*type_symbol) == typeid(integer_c))        {return true;}
+  if (typeid(*type_symbol) == typeid(binary_integer_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(octal_integer_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(hex_integer_c))    {return true;}
+  return false;
+}
+
+/* A helper function... */
 bool search_expression_type_c::is_integer_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return true;}
-  if (typeid(*type_symbol) == typeid(sint_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(int_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(dint_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(lint_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(sint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(int_type_name_c))   {return true;}
+  if (typeid(*type_symbol) == typeid(dint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(lint_type_name_c))  {return true;}
   if (typeid(*type_symbol) == typeid(usint_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(uint_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(uint_type_name_c))  {return true;}
   if (typeid(*type_symbol) == typeid(udint_type_name_c)) {return true;}
   if (typeid(*type_symbol) == typeid(ulint_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(constant_int_type_name_c)) {return true;}
-  return false;
-}
-
+  return is_literal_integer_type(type_symbol);
+}
+
+/* A helper function... */
+bool search_expression_type_c::is_literal_real_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return true;}
+  if (typeid(*type_symbol) == typeid(real_c)) {return true;}
+  return false;
+}
+
+/* A helper function... */
 bool search_expression_type_c::is_real_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return true;}
   if (typeid(*type_symbol) == typeid(real_type_name_c)) {return true;}
   if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(constant_real_type_name_c)) {return true;}
-  return false;
+  return is_literal_real_type(type_symbol);
 }
 
 bool search_expression_type_c::is_num_type(symbol_c *type_symbol) {
@@ -104,8 +120,7 @@
   if (typeid(*type_symbol) == typeid(word_type_name_c)) {return true;}
   if (typeid(*type_symbol) == typeid(dword_type_name_c)) {return true;}
   if (typeid(*type_symbol) == typeid(lword_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(constant_int_type_name_c)) {return true;}
-  return false;
+  return is_literal_integer_type(type_symbol);
 }
 
 bool search_expression_type_c::is_binary_type(symbol_c *type_symbol) {
@@ -117,12 +132,12 @@
 bool search_expression_type_c::is_same_type(symbol_c *first_type, symbol_c *second_type) {
   if (first_type == NULL || second_type == NULL) {return true;}
   if (typeid(*first_type) == typeid(*second_type)) {return true;}
-  if (is_integer_type(first_type) && (typeid(*second_type) == typeid(constant_int_type_name_c))) {return true;}
-  if ((typeid(*first_type) == typeid(constant_int_type_name_c) && is_integer_type(second_type))) {return true;}
-  if (is_binary_type(first_type) && (typeid(*second_type) == typeid(constant_int_type_name_c))) {return true;}
-  if ((typeid(*first_type) == typeid(constant_int_type_name_c) && is_binary_type(second_type))) {return true;}
-  if (is_real_type(first_type) && (typeid(*second_type) == typeid(constant_real_type_name_c))) {return true;}
-  if ((typeid(*first_type) == typeid(constant_real_type_name_c) && is_real_type(second_type))) {return true;}
+  if (is_integer_type(first_type) && is_literal_integer_type(second_type)) {return true;}
+  if (is_literal_integer_type(first_type) && is_integer_type(second_type)) {return true;}
+  if (is_binary_type(first_type) && is_literal_integer_type(second_type))  {return true;}
+  if (is_literal_integer_type(first_type) && is_binary_type(second_type))  {return true;}
+  if (is_real_type(first_type) && is_literal_real_type(second_type)) {return true;}
+  if (is_literal_real_type(first_type) && is_real_type(second_type)) {return true;}
   return false;
 }
 
@@ -131,18 +146,28 @@
   if (first_type == NULL) {return second_type;}
   if (second_type == NULL) {return first_type;}
   if (typeid(*first_type) == typeid(*second_type)) {return first_type;}
-  if (is_integer_type(first_type) && (typeid(*second_type) == typeid(constant_int_type_name_c))) {return first_type;}
-  if ((typeid(*first_type) == typeid(constant_int_type_name_c)) && is_integer_type(second_type)) {return second_type;}
-  if (is_binary_type(first_type) && (typeid(*second_type) == typeid(constant_int_type_name_c)))  {return first_type;}
-  if ((typeid(*first_type) == typeid(constant_int_type_name_c)) && is_binary_type(second_type)) {return second_type;}
-  if (is_real_type(first_type) && (typeid(*second_type) == typeid(constant_real_type_name_c))) {return first_type;}
-  if ((typeid(*first_type) == typeid(constant_real_type_name_c)) && is_real_type(second_type)) {return second_type;}
-  return NULL;
-}
-
+  if (is_integer_type(first_type) && is_literal_integer_type(second_type)) {return first_type;}
+  if (is_literal_integer_type(first_type) && is_integer_type(second_type)) {return second_type;}
+  if (is_binary_type(first_type) && is_literal_integer_type(second_type))  {return first_type;}
+  if (is_literal_integer_type(first_type) && is_binary_type(second_type))  {return second_type;}
+  if (is_real_type(first_type) && is_literal_real_type(second_type)) {return first_type;}
+  if (is_literal_real_type(first_type) && is_real_type(second_type)) {return second_type;}
+  return NULL;
+}
+
+
+integer_c search_expression_type_c::integer("1"); // what default value should we use here ???
 #define compute_standard_function_default search_expression_type_c::compute_standard_function_default
 #define compute_standard_function_il search_expression_type_c::compute_standard_function_il
+#define search(x) search_f(x)
+#define next() next_nf()
+//     #define search_constant_type_c::constant_int_type_name  search_expression_type_c::integer
+#define constant_int_type_name  integer
 #include "search_type_code.c"
+#undef constant_int_type_name
+//     #undef search_constant_type_c::constant_int_type_name
+#undef next
+#undef search
 #undef compute_standard_function_default
 #undef compute_standard_function_il
 
@@ -154,7 +179,7 @@
     ERROR;
   if (!is_bool_type(left_type) && !is_binary_type(left_type))
     ERROR;
-  if (typeid(*left_type) == typeid(constant_int_type_name_c)) {return (void *)right_type;}
+  if (is_literal_integer_type(left_type)) {return (void *)right_type;}
   else {return (void *)left_type;}
 }
 
@@ -164,7 +189,7 @@
     ERROR;
   if (!is_integer_type(left_type) && !is_real_type(left_type))
     ERROR;
-  if ((typeid(*left_type) == typeid(constant_int_type_name_c)) || (typeid(*left_type) == typeid(constant_real_type_name_c))) {return (void *)right_type;}
+  if (is_literal_integer_type(left_type) || is_literal_real_type(left_type)) {return (void *)right_type;}
   else {return (void *)left_type;}
   return NULL;
 }
--- a/absyntax_utils/search_expression_type.hh	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/search_expression_type.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -46,7 +46,9 @@
     bool is_bool_type(symbol_c *type_symbol);
     bool is_time_type(symbol_c *type_symbol);
     bool is_string_type(symbol_c *type_symbol);
+    bool is_literal_integer_type(symbol_c *type_symbol);
     bool is_integer_type(symbol_c *type_symbol);
+    bool is_literal_real_type(symbol_c *type_symbol);
     bool is_real_type(symbol_c *type_symbol);
     bool is_num_type(symbol_c *type_symbol);
     bool is_nbinary_type(symbol_c *type_symbol);
@@ -59,9 +61,6 @@
     #include "search_type_code.c"
     */
     void *compute_standard_function_default(function_invocation_c *st_symbol, il_formal_funct_call_c *il_symbol);
-    /*
-    void *compute_standard_function_default(function_invocation_c *st_symbol = NULL, il_formal_funct_call_c *il_symbol = NULL);
-    */
     void *compute_standard_function_il(il_function_call_c *symbol, symbol_c *param_data_type);
 
 
@@ -120,7 +119,11 @@
     void *visit(neg_expression_c *symbol);
     void *visit(not_expression_c *symbol);
     void *visit(function_invocation_c *symbol);
+
+
+    static integer_c integer;
+
 }; // search_expression_type_c
 
-/*bool_type_name_c     search_expression_type_c::bool_type_name;*/
 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax_utils/search_il_operand_type.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -0,0 +1,58 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+
+
+/* Returns the data type of an il_operand.
+ *
+ * Note that the il_operand may be a variable, in which case
+ * we return the type of the variable instance.
+ * The il_operand may also be a constant, in which case
+ * we return the data type of that constant.
+ *
+ * The variable instance may be a member of a structured variable,
+ * or an element in an array, or any combination of the two.
+ *
+ * The class constructor must be given the search scope
+ * (function, function block or program within which
+ * the possible il_operand variable instance was declared).
+ */
+
+#include "absyntax_utils.hh"
+
+symbol_c *search_il_operand_type_c::get_type(symbol_c *il_operand) {
+  symbol_c *res;
+
+  /* We first assume that it is a constant... */
+  res = search_constant_type.get_type(il_operand);
+  if (res != NULL) return res;
+
+  /* Nope, now we assume it is a variable, and determine its type... */
+  res = search_varfb_instance_type.get_type(il_operand);
+  if (NULL != res) return res;
+
+  /* not found */
+  return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax_utils/search_il_operand_type.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -0,0 +1,51 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+/* Returns the data type of an il_operand.
+ *
+ * Note that the il_operand may be a variable, in which case
+ * we return the type of the variable instance.
+ * The il_operand may also be a constant, in which case
+ * we return the data type of that constant.
+ *
+ * The variable instance may be a member of a structured variable,
+ * or an element in an array, or any combination of the two.
+ *
+ * The class constructor must be given the search scope
+ * (function, function block or program within which
+ * the possible il_operand variable instance was declared).
+ */
+
+class search_il_operand_type_c {
+
+  private:
+  search_varfb_instance_type_c::search_varfb_instance_type_c search_varfb_instance_type;
+    search_constant_type_c search_constant_type;
+
+  public:
+    search_il_operand_type_c(symbol_c *search_scope): search_varfb_instance_type(search_scope) {}
+
+  public:
+    symbol_c *get_type(symbol_c *il_operand);
+};
--- a/absyntax_utils/search_var_instance_decl.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/search_var_instance_decl.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -121,6 +121,14 @@
   return res;
 }
 
+/* ENO : BOOL */
+void *search_var_instance_decl_c::visit(eno_param_declaration_c *symbol) {
+  if (compare_identifiers(symbol->name, search_name) == 0)
+    return symbol->type;
+  return NULL;
+}
+
+
 /* VAR [CONSTANT] var_init_decl_list END_VAR */
 /* option -> may be NULL ! */
 /* helper symbol for input_declarations */
--- a/absyntax_utils/search_var_instance_decl.hh	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/search_var_instance_decl.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -102,6 +102,8 @@
     void *visit(output_declarations_c *symbol);
     /*  VAR_IN_OUT var_declaration_list END_VAR */
     void *visit(input_output_declarations_c *symbol);
+    /* ENO : BOOL */
+    void *visit(eno_param_declaration_c *symbol);
     /* VAR [CONSTANT] var_init_decl_list END_VAR */
     /* option -> may be NULL ! */
     /* helper symbol for input_declarations */
--- a/absyntax_utils/search_varfb_instance_type.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/absyntax_utils/search_varfb_instance_type.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -46,6 +46,10 @@
  */
 
 
+/*
+ * TODO: this code has a memory leak...
+ *       We call 'new' in several locations, but bever get to 'delete' the object instances...
+ */
 #include "absyntax_utils.hh"
 
 
@@ -67,7 +71,7 @@
    */
   symbol_c *var_name_part = decompose_var_instance_name->next_part();
   if (NULL == var_name_part) ERROR;
-  
+
   /* Now we try to find the variable instance declaration, to determine its type... */
   symbol_c *var_decl = search_var_instance_decl.get_decl(var_name_part);
   if (NULL == var_decl) {
--- a/main.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/main.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -81,7 +81,7 @@
 #include "stage1_2/stage1_2.hh"
 #include "absyntax_utils/absyntax_utils.hh"
 
-//int stage3(symbol_c *tree_root);
+int stage3(symbol_c *tree_root);
 int stage4(symbol_c *tree_root, const char *builddir);
 
 
@@ -172,11 +172,12 @@
 
   /* 2nd Pass */
   absyntax_utils_init(tree_root);
+  add_en_eno_param_decl_c::add_to(tree_root);
+
   /* not yet implemented... */
-  /*
   if (stage3(tree_root) < 0)
     return EXIT_FAILURE;
-  */
+  
 
   /* 3rd Pass */
   if (stage4(tree_root, builddir) < 0)
--- a/stage1_2/iec.y	Wed Sep 02 13:39:05 2009 +0200
+++ b/stage1_2/iec.y	Wed Sep 02 14:05:27 2009 +0200
@@ -167,7 +167,9 @@
 symbol_c *il_operator_c_2_identifier_c(symbol_c *il_operator);
 
 /* return if current token is a syntax element */
+/* ERROR_CHECK_BEGIN */
 bool is_current_syntax_token();
+/* ERROR_CHECK_END */
 
 /* print an error message */
 void print_err_msg(int first_line,
@@ -211,9 +213,9 @@
 
 
 
-/*****************************/
-/* Prelimenary constructs... */
-/*****************************/
+/*************************************/
+/* Prelimenary helpful constructs... */
+/*************************************/
 /* A token used to identify the very end of the input file
  * after all includes have already been processed.
  *
@@ -277,17 +279,27 @@
 
 
 
+/**********************************************************************************/
+/* B XXX - Things that are missing from the standard, but should have been there! */
+/**********************************************************************************/
+
+
 /* The pragmas... */
 %token <ID>	pragma_token
 %type <leaf>	pragma
 
 
-/* Where do these tokens belong ?? */
-/* TODO: get the syntax parser to handle these tokens... */
+/* Where do these tokens belong?? They are missing from the standard! */
+/* NOTE: There are other tokens related to these 'EN' ENO', that are also 
+ * missing from the standard. However, their location in the annex B is 
+ * relatively obvious, so they have been inserted in what seems to us their 
+ * correct place in order to ease understanding of the parser...
+ */
 %token	EN
 %token	ENO
-%type <leaf>	en_param
-%type <leaf>	eno_param
+%type <leaf>	en_identifier
+%type <leaf>	eno_identifier
+
 
 
 
@@ -669,6 +681,7 @@
 %type  <list>	input_declaration_list
 %type  <leaf>	input_declaration
 %type  <leaf>	edge_declaration
+/* en_param_declaration is not in the standard, but should be! */
 %type  <leaf>	en_param_declaration
 %type  <leaf>	var_init_decl
 %type  <leaf>	var1_init_decl
@@ -685,6 +698,7 @@
 %type  <leaf>	output_declarations
 %type  <leaf>	var_output_init_decl
 %type  <list>	var_output_init_decl_list
+/* eno_param_declaration is not in the standard, but should be! */
 %type  <leaf>	eno_param_declaration
 %type  <leaf>	input_output_declarations
 /* helper symbol for input_output_declarations */
@@ -1321,30 +1335,38 @@
 /********************************************************/
 
 
-
-
-
-/*****************************/
-/* Prelimenary constructs... */
-/*****************************/
 start:
   library	{$$ = $1;}
 ;
 
+
+/**********************************************************************************/
+/* B XXX - Things that are missing from the standard, but should have been there! */
+/**********************************************************************************/
+
+
 /* the pragmas... */
 pragma:
   pragma_token	{$$ = new pragma_c($1, locloc(@$));}
 
+
 /* EN/ENO */
-en_param:
-  EN	{$$ = new en_param_c(locloc(@$));}
-;
-
-eno_param:
-  ENO	{$$ = new eno_param_c(locloc(@$));}
-;
-
-
+/* Tese tokens are essentially used as variable names, so we handle them 
+ * similarly to these...
+ */
+en_identifier:
+  EN	{$$ = new identifier_c("EN", locloc(@$));}
+;
+
+eno_identifier:
+  ENO	{$$ = new identifier_c("ENO", locloc(@$));}
+;
+
+
+
+/*************************************/
+/* Prelimenary helpful constructs... */
+/*************************************/
 
 /* NOTE:
  *       short version:
@@ -2997,10 +3019,26 @@
 /*********************/
 /* B 1.4 - Variables */
 /*********************/
+/* NOTE: The standard is erroneous in it's definition of 'variable' because:
+ *         - The standard considers 'ENO' as a keyword...
+ *         - ...which means that it may never be parsed as an 'identifier'...
+ *         - ...and therefore may never be used as the name of a variable inside an expression.
+ *         - However, a function/FB must be able to assign the ENO parameter
+ *           it's value, doing it in an assignment statement, and therefore using the 'ENO'
+ *           character sequence as an identifier!
+ *        The solution we found was to also allow the ENO keyword to be 
+ *         used as the name of a variable. Note that this variable may be used
+ *         even though it is not explicitly declared as a function/FB variable,
+ *         as the standard requires us to define it implicitly in this case!
+ *         We could not therefore handle the ENO as a normal variable that would
+ *         go into the previously_declared_variable symbol table, as we may need to
+ *         allow it to be used as a variable even though it is not declared as such!
+ */
 variable:
   symbolic_variable
 | prev_declared_direct_variable
-| eno_param
+| eno_identifier
+	{$$ = new symbolic_variable_c($1, locloc(@$));}
 ;
 
 
@@ -3140,11 +3178,11 @@
 /******************************************/
 input_declarations:
   VAR_INPUT            input_declaration_list END_VAR
-	{$$ = new input_declarations_c(NULL, $2, locloc(@$));}
+	{$$ = new input_declarations_c(NULL, $2, new explicit_definition_c(), locloc(@$));}
 | VAR_INPUT RETAIN     input_declaration_list END_VAR
-	{$$ = new input_declarations_c(new retain_option_c(locloc(@2)), $3, locloc(@$));}
+	{$$ = new input_declarations_c(new retain_option_c(locloc(@2)), $3, new explicit_definition_c(), locloc(@$));}
 | VAR_INPUT NON_RETAIN input_declaration_list END_VAR
-	{$$ = new input_declarations_c(new non_retain_option_c(locloc(@2)), $3, locloc(@$));}
+	{$$ = new input_declarations_c(new non_retain_option_c(locloc(@2)), $3, new explicit_definition_c(), locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | VAR_INPUT END_VAR
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "no variable declared in input variable(s) declaration."); yynerrs++;}
@@ -3194,6 +3232,11 @@
 ;
 
 
+/* NOTE: The formal definition of 'input_declaration' as defined in the standard is erroneous,
+ *       as it does not allow a user defined 'EN' input parameter. However,
+ *       The semantic description of the languages clearly states that this is allowed.
+ *       We have added the 'en_param_declaration' clause to cover for this.
+ */
 input_declaration:
   var_init_decl
 | edge_declaration
@@ -3212,7 +3255,9 @@
 | var1_list BOOL F_EDGE
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and specification in edge declaration."); yynerrs++;}
 | var1_list ':' BOOL R_EDGE F_EDGE
-	{$$ = NULL; print_err_msg(locf(@5), locl(@5), "'R_EDGE' and 'F_EDGE' can't be present at the same time in edge declaration."); yynerrs++;}
+	{$$ = NULL; print_err_msg(locl(@5), locf(@5), "'R_EDGE' and 'F_EDGE' can't be present at the same time in edge declaration."); yynerrs++;}
+| var1_list ':' BOOL F_EDGE R_EDGE
+	{$$ = NULL; print_err_msg(locl(@5), locf(@5), "'R_EDGE' and 'F_EDGE' can't be present at the same time in edge declaration."); yynerrs++;}
 | var1_list ':' R_EDGE
 	{$$ = NULL; print_err_msg(locl(@2), locf(@3), "'BOOL' missing in edge declaration."); yynerrs++;}
 | var1_list ':' F_EDGE
@@ -3220,21 +3265,28 @@
 /* ERROR_CHECK_END */
 ;
 
+
+/* NOTE: The formal definition of the standard is erroneous, as it simply does not
+ *       consider the EN and ENO keywords!
+ *       The semantic description of the languages clearly states that these may be
+ *       used in several ways. One of them is to declare an EN input parameter.
+ *       We have added the 'en_param_declaration' clause to cover for this.
+ */
 en_param_declaration:
-  en_param ':' BOOL ASSIGN boolean_literal
-  {$$ = new en_param_declaration_c(locloc(@$));}
-| en_param ':' BOOL ASSIGN integer
-  {$$ = new en_param_declaration_c(locloc(@$));}
-/* ERROR_CHECK_BEGIN */
-| en_param BOOL ASSIGN boolean_literal
+  en_identifier ':' BOOL ASSIGN boolean_literal
+  {$$ = new en_param_declaration_c($1, new bool_type_name_c(locloc(@$)), $5, new explicit_definition_c(), locloc(@$));}
+| en_identifier ':' BOOL ASSIGN integer
+  {$$ = new en_param_declaration_c($1, new bool_type_name_c(locloc(@$)), $5, new explicit_definition_c(), locloc(@$));}
+/* ERROR_CHECK_BEGIN */
+| en_identifier BOOL ASSIGN boolean_literal
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and specification in EN declaration."); yynerrs++;}
-| en_param BOOL ASSIGN integer
+| en_identifier BOOL ASSIGN integer
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and specification in EN declaration."); yynerrs++;}
-| en_param ':' ASSIGN boolean_literal
+| en_identifier ':' ASSIGN boolean_literal
   {$$ = NULL; print_err_msg(locl(@2), locf(@3), "'BOOL' missing in EN declaration."); yynerrs++;}
-| en_param ':' ASSIGN integer
+| en_identifier ':' ASSIGN integer
 	{$$ = NULL; print_err_msg(locl(@2), locf(@3), "'BOOL' missing in EN declaration."); yynerrs++;}
-| en_param ':' BOOL ASSIGN error
+| en_identifier ':' BOOL ASSIGN error
 	{$$ = NULL;
 	 if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in EN declaration.");}
 	 else {print_err_msg(locf(@3), locl(@3), "invalid specification in EN declaration."); yyclearin;}
@@ -3402,11 +3454,11 @@
 
 output_declarations:
   VAR_OUTPUT var_output_init_decl_list END_VAR
-	{$$ = new output_declarations_c(NULL, $2, locloc(@$));}
+	{$$ = new output_declarations_c(NULL, $2, new explicit_definition_c(), locloc(@$));}
 | VAR_OUTPUT RETAIN var_output_init_decl_list END_VAR
-	{$$ = new output_declarations_c(new retain_option_c(locloc(@2)), $3, locloc(@$));}
+	{$$ = new output_declarations_c(new retain_option_c(locloc(@2)), $3, new explicit_definition_c(), locloc(@$));}
 | VAR_OUTPUT NON_RETAIN var_output_init_decl_list END_VAR
-	{$$ = new output_declarations_c(new non_retain_option_c(locloc(@2)), $3, locloc(@$));}
+	{$$ = new output_declarations_c(new non_retain_option_c(locloc(@2)), $3, new explicit_definition_c(), locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | VAR_OUTPUT END_VAR
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "no variable declared in output variable(s) declaration."); yynerrs++;}
@@ -3435,6 +3487,12 @@
 /* ERROR_CHECK_END */
 ;
 
+
+/* NOTE: The formal definition of 'var_output_init_decl' as defined in the standard is erroneous,
+ *       as it does not allow a user defined 'ENO' output parameter. However,
+ *       The semantic description of the languages clearly states that this is allowed.
+ *       We have added the 'eno_param_declaration' clause to cover for this.
+ */
 var_output_init_decl:
   var_init_decl
 | eno_param_declaration
@@ -3453,13 +3511,23 @@
 /* ERROR_CHECK_END */
 ;
 
+
+/* NOTE: The formal definition of the standard is erroneous, as it simply does not
+ *       consider the EN and ENO keywords!
+ *       The semantic description of the languages clearly states that these may be
+ *       used in several ways. One of them is to declare an ENO output parameter.
+ *       We have added the 'eno_param_declaration' clause to cover for this.
+ */
 eno_param_declaration:
-  eno_param ':' BOOL
-  {$$ = new eno_param_declaration_c(locloc(@$));}
-/* ERROR_CHECK_BEGIN */
-| en_param BOOL
-	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and specification in EN0 declaration."); yynerrs++;}
-| en_param ':' error
+  eno_identifier ':' BOOL
+  /* NOTE We do _NOT_ include this variable in the previously_declared_variable symbol table!
+   *      Please read the comment above the definition of 'variable' for the reason for this.
+   */
+  {$$ = new eno_param_declaration_c($1, new bool_type_name_c(locloc(@$)), new explicit_definition_c(), locloc(@$));}
+/* ERROR_CHECK_BEGIN */
+| en_identifier BOOL
+	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and specification in ENO declaration."); yynerrs++;}
+| en_identifier ':' error
 	{$$ = NULL;
 	 if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in ENO declaration.");}
 	 else {print_err_msg(locf(@3), locl(@3), "invalid specification in ENO declaration."); yyclearin;}
@@ -6509,7 +6577,7 @@
 /*  variable_name ASSIGN */
   any_identifier ASSIGN
 	{$$ = new il_assign_operator_c($1, locloc(@$));}
-| en_param ASSIGN
+| en_identifier ASSIGN
 	{$$ = new il_assign_operator_c($1, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | error ASSIGN
@@ -6523,12 +6591,12 @@
 /*  any_identifier SENDTO */
   sendto_identifier SENDTO
 	{$$ = new il_assign_out_operator_c(NULL, $1, locloc(@$));}
-| eno_param SENDTO
+| eno_identifier SENDTO
 	{$$ = new il_assign_out_operator_c(NULL, $1, locloc(@$));}
 /*| NOT variable_name SENDTO */
 | NOT sendto_identifier SENDTO
 	{$$ = new il_assign_out_operator_c(new not_paramassign_c(locloc(@1)), $2, locloc(@$));}
-| NOT eno_param SENDTO
+| NOT eno_identifier SENDTO
 	{$$ = new il_assign_out_operator_c(new not_paramassign_c(locloc(@1)), $2, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | error SENDTO
@@ -6864,9 +6932,9 @@
 function_invocation:
 /*  function_name '(' [param_assignment_list] ')' */
   function_name_no_NOT_clashes '(' param_assignment_formal_list ')'
-	{$$ = new function_invocation_c($1, $3, locloc(@$));}
+	{$$ = new function_invocation_c($1, $3, NULL, locloc(@$));}
 | function_name_no_NOT_clashes '(' param_assignment_nonformal_list ')'
-	{$$ = new function_invocation_c($1, $3, locloc(@$));}
+	{$$ = new function_invocation_c($1, NULL, $3, locloc(@$));}
 /* ERROR_CHECK_BEGIN */ 
 | function_name_no_NOT_clashes param_assignment_formal_list ')'
   {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'(' missing after function name in ST expression."); yynerrs++;}
@@ -6952,11 +7020,11 @@
 
 fb_invocation:
   prev_declared_fb_name '(' ')'
-	{$$ = new fb_invocation_c($1, NULL, locloc(@$));	}
+	{$$ = new fb_invocation_c($1, NULL, NULL, locloc(@$));	}
 | prev_declared_fb_name '(' param_assignment_formal_list ')'
-	{$$ = new fb_invocation_c($1, $3, locloc(@$));}
+	{$$ = new fb_invocation_c($1, $3, NULL, locloc(@$));}
 | prev_declared_fb_name '(' param_assignment_nonformal_list ')'
-	{$$ = new fb_invocation_c($1, $3, locloc(@$));}
+	{$$ = new fb_invocation_c($1, NULL, $3, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | prev_declared_fb_name ')'
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "'(' missing after function block name in ST statement."); yynerrs++;}
@@ -7048,19 +7116,19 @@
 param_assignment_formal:
   any_identifier ASSIGN expression
 	{$$ = new input_variable_param_assignment_c($1, $3, locloc(@$));}
-| en_param ASSIGN expression
+| en_identifier ASSIGN expression
 	{$$ = new input_variable_param_assignment_c($1, $3, locloc(@$));}
 /*| variable_name SENDTO variable */
 /*| any_identifier SENDTO variable */
 | sendto_identifier SENDTO variable
 	{$$ = new output_variable_param_assignment_c(NULL, $1, $3, locloc(@$));}
-| eno_param SENDTO variable
+| eno_identifier SENDTO variable
 	{$$ = new output_variable_param_assignment_c(NULL, $1, $3, locloc(@$));}
 /*| NOT variable_name SENDTO variable */
 /*| NOT any_identifier SENDTO variable*/
 | NOT sendto_identifier SENDTO variable
 	{$$ = new output_variable_param_assignment_c(new not_paramassign_c(locloc(@$)), $2, $4, locloc(@$));}
-| NOT eno_param SENDTO variable
+| NOT eno_identifier SENDTO variable
 	{$$ = new output_variable_param_assignment_c(new not_paramassign_c(locloc(@$)), $2, $4, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | any_identifier ASSIGN error
@@ -7069,7 +7137,7 @@
 	 else {print_err_msg(locf(@3), locl(@3), "invalid expression in ST formal parameter assignment."); yyclearin;}
 	 yyerrok;
 	}
-| en_param ASSIGN error
+| en_identifier ASSIGN error
   {$$ = NULL;
 	 if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined in ST formal parameter assignment.");}
 	 else {print_err_msg(locf(@3), locl(@3), "invalid expression in ST formal parameter assignment."); yyclearin;}
@@ -7081,7 +7149,7 @@
 	 else {print_err_msg(locf(@3), locl(@3), "invalid expression in ST formal parameter out assignment."); yyclearin;}
 	 yyerrok;
 	}
-| eno_param SENDTO error
+| eno_identifier SENDTO error
   {$$ = NULL;
 	 if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined in ST formal parameter out assignment.");}
 	 else {print_err_msg(locf(@3), locl(@3), "invalid expression in ST formal parameter out assignment."); yyclearin;}
@@ -7097,7 +7165,7 @@
 	 else {print_err_msg(locf(@4), locl(@4), "invalid expression in ST formal parameter out negated assignment."); yyclearin;}
 	 yyerrok;
 	}
-| NOT eno_param SENDTO error
+| NOT eno_identifier SENDTO error
   {$$ = NULL;
 	 if (is_current_syntax_token()) {print_err_msg(locl(@3), locf(@4), "no expression defined in ST formal parameter out negated assignment.");}
 	 else {print_err_msg(locf(@4), locl(@4), "invalid expression in ST formal parameter out negated assignment."); yyclearin;}
@@ -7358,7 +7426,9 @@
  * If we don't, then the correct use of any previosuly declared 
  * variable would result in an incorrect syntax error
 */
-control_variable: prev_declared_variable_name {$$ = $1;};
+control_variable: 
+  prev_declared_variable_name 
+	{$$ = new symbolic_variable_c($1,locloc(@$));};
 // control_variable: identifier {$$ = $1;};
 
 /* Integrated directly into for_statement */
@@ -7481,35 +7551,38 @@
 }
 
 
+/* ERROR_CHECK_BEGIN */
 bool is_current_syntax_token() {
-	switch (yychar) {
-  	case ';':
-  	case ',':
-  	case ')':
-  	case ']':
-  	case '+':
-  	case '*':
-  	case '-':
-  	case '/':
-  	case '<':
-  	case '>':
-  	case '=':
-  	case '&':
-  	case OR:
-  	case XOR:
-  	case AND:
-  	case AND2:
-  	case OPER_NE:
-  	case OPER_LE:
-  	case OPER_GE:
-  	case MOD:
-  	case OPER_EXP:
-  	case NOT:
-  		return true;
- 		default:
- 			return false;
- 	}
+  switch (yychar) {
+    case ';':
+    case ',':
+    case ')':
+    case ']':
+    case '+':
+    case '*':
+    case '-':
+    case '/':
+    case '<':
+    case '>':
+    case '=':
+    case '&':
+    case OR:
+    case XOR:
+    case AND:
+    case AND2:
+    case OPER_NE:
+    case OPER_LE:
+    case OPER_GE:
+    case MOD:
+    case OPER_EXP:
+    case NOT:
+      return true;
+    default:
+     return false;
+  }
 }
+/* ERROR_CHECK_END */
+
 
 void print_err_msg(int first_line,
                    int first_column,
@@ -7544,64 +7617,64 @@
   const char *name = NULL;
   identifier_c *res;
 
-  op_2_str(NOT, "NOT");
-
-  op_2_str(AND, "AND");
-  op_2_str(OR, "OR");
-  op_2_str(XOR, "XOR");
-  op_2_str(ADD, "ADD");
-  op_2_str(SUB, "SUB");
-  op_2_str(MUL, "MUL");
-  op_2_str(DIV, "DIV");
-  op_2_str(MOD, "MOD");
-  op_2_str(GT, "GT");
-  op_2_str(GE, "GE");
-  op_2_str(EQ, "EQ");
-  op_2_str(LT, "LT");
-  op_2_str(LE, "LE");
-  op_2_str(NE, "NE");
-
-  op_2_str(LD, "LD");
-  op_2_str(LDN, "LDN");
-  op_2_str(ST, "ST");
-  op_2_str(STN, "STN");
-
-  op_2_str(S, "S");
-  op_2_str(R, "R");
-  op_2_str(S1, "S1");
-  op_2_str(R1, "R1");
-
-  op_2_str(CLK, "CLK");
-  op_2_str(CU, "CU");
-  op_2_str(CD, "CD");
-  op_2_str(PV, "PV");
-  op_2_str(IN, "IN");
-  op_2_str(PT, "PT");
-
-  op_2_str(ANDN, "ANDN");
-  op_2_str(ORN, "ORN");
-  op_2_str(XORN, "XORN");
-
-  op_2_str(ADD, "ADD");
-  op_2_str(SUB, "SUB");
-  op_2_str(MUL, "MUL");
-  op_2_str(DIV, "DIV");
-
-  op_2_str(GT, "GT");
-  op_2_str(GE, "GE");
-  op_2_str(EQ, "EQ");
-  op_2_str(LT, "LT");
-  op_2_str(LE, "LE");
-  op_2_str(NE, "NE");
-
-  op_2_str(CAL, "CAL");
-  op_2_str(CALC, "CALC");
+  op_2_str(NOT,   "NOT");
+
+  op_2_str(AND,   "AND");
+  op_2_str(OR,    "OR");
+  op_2_str(XOR,   "XOR");
+  op_2_str(ADD,   "ADD");
+  op_2_str(SUB,   "SUB");
+  op_2_str(MUL,   "MUL");
+  op_2_str(DIV,   "DIV");
+  op_2_str(MOD,   "MOD");
+  op_2_str(GT,    "GT");
+  op_2_str(GE,    "GE");
+  op_2_str(EQ,    "EQ");
+  op_2_str(LT,    "LT");
+  op_2_str(LE,    "LE");
+  op_2_str(NE,    "NE");
+
+  op_2_str(LD,    "LD");
+  op_2_str(LDN,   "LDN");
+  op_2_str(ST,    "ST");
+  op_2_str(STN,   "STN");
+
+  op_2_str(S,     "S");
+  op_2_str(R,     "R");
+  op_2_str(S1,    "S1");
+  op_2_str(R1,    "R1");
+
+  op_2_str(CLK,   "CLK");
+  op_2_str(CU,    "CU");
+  op_2_str(CD,    "CD");
+  op_2_str(PV,    "PV");
+  op_2_str(IN,    "IN");
+  op_2_str(PT,    "PT");
+
+  op_2_str(ANDN,  "ANDN");
+  op_2_str(ORN,   "ORN");
+  op_2_str(XORN,  "XORN");
+
+  op_2_str(ADD,   "ADD");
+  op_2_str(SUB,   "SUB");
+  op_2_str(MUL,   "MUL");
+  op_2_str(DIV,   "DIV");
+
+  op_2_str(GT,    "GT");
+  op_2_str(GE,    "GE");
+  op_2_str(EQ,    "EQ");
+  op_2_str(LT,    "LT");
+  op_2_str(LE,    "LE");
+  op_2_str(NE,    "NE");
+
+  op_2_str(CAL,   "CAL");
+  op_2_str(CALC,  "CALC");
   op_2_str(CALCN, "CALCN");
-  op_2_str(RET, "RET");
-  op_2_str(RETC, "RETC");
+  op_2_str(RET,   "RET");
+  op_2_str(RETC,  "RETC");
   op_2_str(RETCN, "RETCN");
-  op_2_str(JMP, "JMP");
-  op_2_str(JMPC, "JMPC");
+  op_2_str(JMP,   "JMP");
+  op_2_str(JMPC,  "JMPC");
   op_2_str(JMPCN, "JMPCN");
 
   if (name == NULL)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/Makefile	Wed Sep 02 14:05:27 2009 +0200
@@ -0,0 +1,28 @@
+# include the system specific Makefile
+include ../Makefile.$(shell uname)
+
+
+
+
+STAGE3_FILES  = stage3.o
+STAGE3_FILES += visit_expression_type.o
+
+default: all
+
+all: $(STAGE3_FILES)
+
+
+
+clean:
+	rm -f *.o Makefile.depend
+
+
+CXXFLAGS += -I. -I../*
+
+
+
+Makefile.depend depend:
+	$(CXX) -MM -MG -I. *.cc > Makefile.depend
+	#| perl -pe 's/:/ Makefile.depend:/' > Makefile.depend
+
+include Makefile.depend
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/stage3.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -0,0 +1,37 @@
+/*
+ * (c) 20099 Catarina da Costa Boucinha
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2009-04-24)
+ *
+ */
+
+#include "stage3.hh"
+
+int type_safety(symbol_c *tree_root){
+	visit_expression_type_c visit_expression_type(tree_root);
+
+	(*tree_root).accept(visit_expression_type);
+
+	return 0;
+}
+
+int stage3(symbol_c *tree_root){
+	return type_safety(tree_root);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/stage3.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -0,0 +1,42 @@
+/*
+ * (c) 2009 Catarina da Costa Boucinha
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2009-04-24)
+ *
+ */
+
+
+// #include <stdio.h>  /* required for NULL */
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <typeinfo>
+#include <list>
+#include <strings.h>
+
+#include "../util/symtable.hh"
+#include "../util/dsymtable.hh"
+#include "../absyntax/visitor.hh"
+
+#include "visit_expression_type.hh"
+
+
+int stage3(symbol_c *tree_root);
+int type_safety(symbol_c *tree_root);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/visit_expression_type.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -0,0 +1,1676 @@
+/*
+ * (c) 2009 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/* Verify whether the semantic rules of data type compatibility are being followed.
+ *
+ * For example:
+ */
+
+#include "visit_expression_type.hh"
+#include <typeinfo>
+#include <list>
+#include <string>
+#include <string.h>
+#include <strings.h>
+
+
+
+#define FIRST_(symbol1, symbol2) (((symbol1)->first_line   < (symbol2)->first_line)   ? (symbol1) :    \
+                                  ((symbol1)->first_line   > (symbol2)->first_line)   ? (symbol2) :    \
+                                  ((symbol1)->first_column < (symbol2)->first_column) ? (symbol1) :    \
+                                  ((symbol1)->first_column > (symbol2)->first_column) ? (symbol2) :    \
+                                  (symbol1))
+
+#define  LAST_(symbol1, symbol2) (((symbol1)->last_line    < (symbol2)->last_line)    ? (symbol2) :    \
+                                  ((symbol1)->last_line    > (symbol2)->last_line)    ? (symbol1) :    \
+                                  ((symbol1)->last_column  < (symbol2)->last_column)  ? (symbol2) :    \
+                                  ((symbol1)->last_column  > (symbol2)->last_column)  ? (symbol1) :    \
+                                  (symbol1))
+
+#define STAGE3_ERROR(symbol1, symbol2, msg) {                                          \
+    printf("semantic error between (%d:%d) and (%d:%d): %s\n",                         \
+           FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column, \
+           LAST_(symbol1,symbol2) ->last_line,  LAST_(symbol1,symbol2) ->last_column,  \
+           msg);                                                                       \
+    il_error = true;                                                                   \
+  }
+
+
+
+
+
+void *visit_expression_type_c::visit(program_declaration_c *symbol) {
+  search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+  symbol->var_declarations->accept(*this);
+  printf("checking semantics in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
+  il_parenthesis_level = 0;
+  il_error = false;
+  il_default_variable_type = NULL;
+  symbol->function_block_body->accept(*this);
+  il_default_variable_type = NULL;
+  delete search_varfb_instance_type;
+  return NULL;
+}
+
+void *visit_expression_type_c::visit(function_declaration_c *symbol) {
+  search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+  symbol->var_declarations_list->accept(*this);
+  printf("checking semantics in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
+  il_parenthesis_level = 0;
+  il_error = false;
+  il_default_variable_type = NULL;
+  symbol->function_body->accept(*this);
+  il_default_variable_type = NULL;
+  delete search_varfb_instance_type;
+  return NULL;
+}
+
+void *visit_expression_type_c::visit(function_block_declaration_c *symbol) {
+  search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+  symbol->var_declarations->accept(*this);
+  printf("checking semantics in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
+  il_parenthesis_level = 0;
+  il_error = false;
+  il_default_variable_type = NULL;
+  symbol->fblock_body->accept(*this);
+  il_default_variable_type = NULL;
+  delete search_varfb_instance_type;
+  return NULL;
+}
+
+
+
+
+
+
+
+
+
+visit_expression_type_c::visit_expression_type_c(symbol_c *search_scope) {
+}
+
+visit_expression_type_c::~visit_expression_type_c(void) {
+}
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_ANY_ELEMENTARY_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {ERROR;}
+  return is_ANY_MAGNITUDE_type(type_symbol)
+      || is_ANY_BIT_type(type_symbol)
+      || is_ANY_STRING_type(type_symbol)
+      || is_ANY_DATE_type(type_symbol);
+}
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_ANY_MAGNITUDE_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {ERROR;}
+  if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;}
+  return is_ANY_NUM_type(type_symbol);
+}
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_ANY_NUM_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {ERROR;}
+  return is_ANY_REAL_type(type_symbol) || is_ANY_INT_type(type_symbol);
+}
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_ANY_DATE_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {ERROR;}
+  if (typeid(*type_symbol) == typeid(date_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(tod_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(dt_type_name_c)) {return true;}
+  return false;
+}
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_ANY_STRING_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {ERROR;}
+  if (typeid(*type_symbol) == typeid(string_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;}
+  return false;
+}
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_ANY_INT_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {ERROR;}
+  if (typeid(*type_symbol) == typeid(sint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(int_type_name_c))   {return true;}
+  if (typeid(*type_symbol) == typeid(dint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(lint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(usint_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(uint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(udint_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(ulint_type_name_c)) {return true;}
+  if (is_literal_integer_type(type_symbol))              {return true;}
+  return false;
+}
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_ANY_REAL_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {ERROR;}
+  if (typeid(*type_symbol) == typeid(real_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;}
+  if (is_literal_real_type(type_symbol))                 {return true;}
+  return false;
+}
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_ANY_BIT_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {ERROR;}
+  if (typeid(*type_symbol) == typeid(bool_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(byte_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(word_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(dword_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(lword_type_name_c)) {return true;}
+  if (is_literal_integer_type(type_symbol))              {return true;}
+  return false;
+}
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_BOOL_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {ERROR;}
+  if (typeid(*type_symbol) == typeid(bool_type_name_c))  {return true;}
+  if (is_literal_bool_type(type_symbol))                 {return true;}
+  return false;
+}
+
+
+#define sizeoftype(symbol) get_sizeof_datatype_c::getsize(symbol)
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_literal_integer_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return true;}
+  if (typeid(*type_symbol) == typeid(integer_c))        {return true;}
+  if (typeid(*type_symbol) == typeid(binary_integer_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(octal_integer_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(hex_integer_c))    {return true;}
+  return false;
+}
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_literal_real_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return true;}
+  if (typeid(*type_symbol) == typeid(real_c)) {return true;}
+  return false;
+}
+
+
+/* A helper function... */
+bool visit_expression_type_c::is_literal_bool_type(symbol_c *type_symbol) {
+  bool_type_name_c bool_t;
+
+  if (type_symbol == NULL) {return true;}
+  if (typeid(*type_symbol) == typeid(boolean_true_c))    {return true;}
+  if (typeid(*type_symbol) == typeid(boolean_false_c))   {return true;}
+  if (is_literal_integer_type(type_symbol))
+    if (sizeoftype(&bool_t) >= sizeoftype(type_symbol))  {return true;}
+  return false;
+}
+
+
+/* Determine the common data type between two data types.
+ * If no common data type found, return NULL.
+ *
+ * If data types are identical, return the first (actually any would do...).
+ * If any of the data types is a literal, we confirm that 
+ *   the literal uses less bits than the fixed size data type.
+ *   e.g. BYTE and 1024 returns NULL
+ *        BYTE and 255  returns BYTE
+ *
+ * If two literals, then return the literal that requires more bits...
+ */
+symbol_c *visit_expression_type_c::common_type__(symbol_c *first_type, symbol_c *second_type) {
+  if (first_type == NULL && second_type == NULL) {ERROR;}
+  if (first_type == NULL)  {return second_type;}
+  if (second_type == NULL) {return first_type;}
+
+  if (is_literal_integer_type(first_type) && is_literal_integer_type(second_type))
+    {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);}
+
+  if (is_literal_real_type(first_type) && is_literal_real_type(second_type))
+    {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);}
+
+  if (is_literal_bool_type(first_type) && is_literal_bool_type(second_type))
+    {return first_type;}
+
+  /* This check can only be made after the is_literal_XXXX checks */
+  /* When two literals of the same type, with identical typeid's are checked,
+   * we must return the one that occupies more bits...
+   */
+  if (typeid(*first_type) == typeid(*second_type)) {return first_type;}
+
+  if (is_BOOL_type(first_type)      && is_literal_bool_type(second_type))     {return first_type;}
+  if (is_BOOL_type(second_type)     && is_literal_bool_type(first_type))      {return second_type;}
+
+  if (is_ANY_BIT_type(first_type)     && is_literal_integer_type(second_type))
+    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
+  if (is_ANY_BIT_type(second_type)    && is_literal_integer_type(first_type))
+    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+  if (is_ANY_INT_type(first_type)   && is_literal_integer_type(second_type))
+    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
+  if (is_ANY_INT_type(second_type)  && is_literal_integer_type(first_type))
+    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+  if (is_ANY_REAL_type(first_type)  && is_literal_real_type(second_type))
+    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
+  if (is_ANY_REAL_type(second_type) && is_literal_real_type(first_type))
+    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+  /* no common type */
+  return NULL;
+}
+
+/* Determine the common data type between two data types.
+ * Unlike the common_type__() function, we stop the compiler with an ERROR
+ *  if no common data type is found.
+ */
+symbol_c *visit_expression_type_c::common_type(symbol_c *first_type, symbol_c *second_type) {
+  symbol_c *res = common_type__(first_type, second_type);
+  if (NULL == res) ERROR;
+  return res;
+}
+
+
+/* Return TRUE if there is a common data type, otherwise return FALSE
+ */
+bool visit_expression_type_c::is_compatible_type(symbol_c *first_type, symbol_c *second_type) {
+  if (first_type == NULL || second_type == NULL) {ERROR;}
+  return (NULL != common_type__(first_type, second_type));
+}
+
+
+
+#define is_num_type      is_ANY_NUM_type
+#define is_integer_type  is_ANY_INT_type
+#define is_real_type     is_ANY_REAL_type
+#define is_binary_type   is_ANY_BIT_type
+ /* actually the ROR, ROL, SHL, and SHR function also accept boolean type! */
+#define is_nbinary_type  is_ANY_BIT_type  
+#define compute_standard_function_default visit_expression_type_c::compute_standard_function_default
+#define compute_standard_function_il visit_expression_type_c::compute_standard_function_il
+#define search_expression_type_c visit_expression_type_c
+#define search(x) search_f(x)
+#define next() next_nf()
+//     #define search_constant_type_c::constant_int_type_name  search_expression_type_c::integer
+#define constant_int_type_name  integer
+#define is_same_type is_compatible_type
+#include "../absyntax_utils/search_type_code.c"
+#undef is_same_type
+#undef constant_int_type_name
+//     #undef search_constant_type_c::constant_int_type_name
+#undef next
+#undef search
+#undef compute_standard_function_default
+#undef compute_standard_function_il
+#undef search_expression_type_c
+#undef is_real_type
+#undef is_binary_type
+#undef is_nbinary_type
+#undef is_integer_type
+#undef is_num_type
+
+
+
+
+
+
+/* A helper function... */
+symbol_c *visit_expression_type_c::compute_boolean_expression(symbol_c *left_type, symbol_c *right_type,
+                                                              is_data_type_t is_data_type) {
+  bool error = false;
+
+  if (!(this->*is_data_type)(left_type)) {
+    STAGE3_ERROR(left_type, left_type, "invalid data type of first operand.");
+    error = true;
+  }
+  if (!(this->*is_data_type)(right_type)) {
+    STAGE3_ERROR(right_type, right_type, "invalid data type of second operand.");
+    error = true;
+  }
+  if (!is_compatible_type(left_type, right_type)) {
+    STAGE3_ERROR(left_type, right_type, "type mismatch between operands.");
+    error = true;
+  }
+
+  if (error)
+    return NULL;
+  else
+    return common_type(left_type, right_type);
+}
+
+
+/* A helper function... */
+symbol_c *visit_expression_type_c::compute_numeric_expression(symbol_c *left_type, symbol_c *right_type,
+                                                              is_data_type_t is_data_type) {
+  if (!(this->*is_data_type)(left_type))
+    STAGE3_ERROR(left_type, right_type, "Both parts of the equation must be the same type.");
+  if (!(this->*is_data_type)(right_type))
+    STAGE3_ERROR(left_type, right_type, "Both parts of the equation must be the same type.");
+  if (!is_compatible_type(left_type, right_type))
+    STAGE3_ERROR(left_type, right_type, "Both parts of the equation must be the same type.");
+
+  if (is_literal_integer_type(left_type) || is_literal_real_type(left_type)) {
+    return right_type;
+  } else {
+    return left_type;
+  }
+
+  /* humour the compiler... */
+  return NULL;
+}
+
+
+
+
+
+
+/* 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) {
+  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);
+
+  /* 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 */
+    do {
+      param_name = fp_iterator.next();
+      if(param_name == NULL) break;
+      /*  The EN and ENO parameters are default parameters.
+       *  In the non-formal invocation of a function there can be no assignment of
+       * values to these parameters. Therefore, we ignore the parameters declared
+       * in the function.
+       */
+    } 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.
+     */
+    if(param_name != NULL) {
+      param_type = fp_iterator.param_type();
+      if(!is_compatible_type(il_default_variable_type,param_type)) 
+        STAGE3_ERROR(f_call, f_call, "In function/FB call, first parameter has invalid data type.");
+    }
+  } // 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 current parameter 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.");;
+
+    /* Iterate to the next parameter of the function being called.
+     * Get the name of that parameter, and ignore if EN or ENO.
+     */
+    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;}
+    } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
+
+    if(param_name != NULL) {
+      /* Get the parameter type */
+      param_type = fp_iterator.param_type();
+      /* If the declared parameter and the parameter from the function call do no have the same type */
+      if(!is_compatible_type(call_param_type,param_type)) STAGE3_ERROR(call_param_value, call_param_value, "Type mismatch in function/FB call parameter.");
+    }
+  }
+}
+
+void visit_expression_type_c::compute_input_operatores(symbol_c *symbol, const char *input_operator){
+  symbol_c *call_param_type;
+  symbol_c *fb_decl = il_operand_type;
+    /* The following should never occur. The function block must be defined, 
+     * and the FB type being called MUST be in the symtable... 
+     * This was all already checked at stage 2!
+     */
+  if (NULL == fb_decl){ 
+    STAGE3_ERROR(symbol, symbol, "Parameter operator needs an instance of a function block operand.");
+    ERROR;
+  }
+
+   /* Iterating through the formal parameters of the function call */
+  identifier_c call_param_name(input_operator);
+
+  /* Obtaining the type of the value being passed in the function call */
+  call_param_type = il_default_variable_type;
+  if (call_param_type == NULL) {
+    STAGE3_ERROR(&call_param_name, &call_param_name, "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.
+     */
+    ERROR;
+  }
+  call_param_type = base_type(call_param_type);
+  if (call_param_type == NULL) STAGE3_ERROR(&call_param_name, &call_param_name, "Could not determine data type of value being passed in function/FB call.");
+  
+
+  check_formal_parameter(&call_param_name, call_param_type, fb_decl);
+//   return NULL;
+}
+
+void visit_expression_type_c::check_formal_parameter(symbol_c *call_param_name, symbol_c *call_param_type, symbol_c *f_decl) {
+  symbol_c *param_type;
+  identifier_c *param_name;
+  function_param_iterator_c       fp_iterator(f_decl);
+
+  /* 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.");
+  } else {
+    /* Get the parameter type */
+    param_type = fp_iterator.param_type();
+    /* If the declared parameter and the parameter from the function call have the same type */
+//     if(!is_compatible_type(call_param_type, param_type)) STAGE3_ERROR(call_param_name, call_param_value, "Type mismatch function/FB call parameter.");
+    if(!is_compatible_type(call_param_type, param_type)) STAGE3_ERROR(call_param_name, call_param_name, "Type mismatch function/FB call parameter.");
+  }
+}
+
+
+/* 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) {
+  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);
+
+  /* Iterating through the formal parameters of the function call */
+  while((call_param_name = fcp_iterator.next_f()) != NULL) {
+        
+    /* Obtaining the value being passed in the function call */
+    call_param_value = fcp_iterator.get_current_value();
+    /* the following should never occur. If it does, then we have a bug in our code... */
+    if (NULL == call_param_value) ERROR;
+
+    /* 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.");
+    }   
+
+    /* 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.");
+      /* The data value being passed is possibly any enumerated type value.
+       * We do not yet handle semantic verification of enumerated types.
+       */
+      ERROR;
+    }
+    call_param_type = base_type(call_param_type);
+    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.");
+
+    /* 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.");
+    } else {
+      /* Get the parameter type */
+      param_type = fp_iterator.param_type();
+      /* If the declared parameter and the parameter from the function call have the same type */
+      if(!is_compatible_type(call_param_type, param_type)) STAGE3_ERROR(call_param_name, call_param_value, "Type mismatch function/FB call parameter.");
+    }
+  }
+}
+
+
+
+
+/* a helper function... */
+symbol_c *visit_expression_type_c::base_type(symbol_c *symbol) {
+  return (symbol_c *)symbol->accept(search_base_type);
+}
+
+
+/* a helper function... */
+void *visit_expression_type_c::verify_null(symbol_c *symbol){
+  if(il_default_variable_type == NULL){
+    STAGE3_ERROR(symbol, symbol, "Il default variable can't be NULL.");
+  }
+  if(il_operand_type == NULL){
+    STAGE3_ERROR(symbol, symbol, "function requires an operand.");
+  }
+  return NULL;
+}
+
+
+
+
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+
+void *visit_expression_type_c::visit(symbolic_variable_c *symbol) {
+  return search_varfb_instance_type->get_type(symbol);
+}
+
+/********************************************/
+/* B 1.4.1 - Directly Represented Variables */
+/********************************************/
+void *visit_expression_type_c::visit(direct_variable_c *symbol) {
+  switch (symbol->value[2]) {
+    case 'X': // bit - 1 bit
+      return (void *)&bool_type_name;
+    case 'B': // byte - 8 bits
+      return (void *)&byte_type_name;
+    case 'W': // word - 16 bits
+      return (void *)&word_type_name;
+    case 'D': // double word - 32 bits
+      return (void *)&dword_type_name;
+    case 'L': // long word - 64 bits
+      return (void *)&lword_type_name;
+    default:  // if none of the above, then the empty string was used <=> boolean 
+      return (void *)&bool_type_name;
+   }
+}
+
+/*************************************/
+/* B 1.4.2 - Multi-element variables */
+/*************************************/
+void *visit_expression_type_c::visit(array_variable_c *symbol) {
+  return search_varfb_instance_type->get_type(symbol);
+}
+
+void *visit_expression_type_c::visit(structured_variable_c *symbol) {
+  return search_varfb_instance_type->get_type(symbol);
+}
+
+
+
+/****************************************/
+/* B.2 - Language IL (Instruction List) */
+/****************************************/
+/***********************************/
+/* B 2.1 Instructions and Operands */
+/***********************************/
+/*| instruction_list il_instruction */
+/* The visitor of the base class search_visitor_c will handle calling each instruction in the list.
+ * We do not need to do anything here...
+ */
+// void *visit_expression_type_c::visit(instruction_list_c *symbol)
+
+/* | label ':' [il_incomplete_instruction] eol_list */
+//SYM_REF2(il_instruction_c, label, il_instruction)
+// void *visit_expression_type_c::visit(il_instruction_c *symbol);
+
+
+/* | il_simple_operator [il_operand] */
+// SYM_REF2(il_simple_operation_c, il_simple_operator, il_operand)
+void *visit_expression_type_c::visit(il_simple_operation_c *symbol) {
+  if (il_error)
+    return NULL;
+
+  /* determine the data type of the operand */
+  if (symbol->il_operand != NULL){
+    il_operand_type = base_type((symbol_c *)symbol->il_operand->accept(*this));
+  } else {
+    il_operand_type = NULL;
+  }
+  /* recursive call to see whether data types are compatible */
+  symbol->il_simple_operator->accept(*this);
+
+  il_operand_type = NULL;
+  return NULL;
+}
+
+// | function_name [il_operand_list] */
+//SYM_REF2(il_function_call_c, function_name, il_operand_list)
+void *visit_expression_type_c::visit(il_function_call_c *symbol) {
+  if (il_error)
+    return 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)
+    
+    #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;
+  }
+  return NULL;
+}
+
+
+/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
+// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
+void *visit_expression_type_c::visit(il_expression_c *symbol) {
+  if (il_error)
+    return NULL;
+
+  symbol_c *il_default_variable_type_back = il_default_variable_type;
+
+  il_parenthesis_level++;
+
+  if(symbol->il_operand != NULL) {
+     il_default_variable_type = base_type((symbol_c *)symbol->il_operand->accept(*this));
+  } else {
+     il_default_variable_type = NULL;
+  }
+
+  if(symbol->simple_instr_list != NULL) {
+    symbol->simple_instr_list->accept(*this);
+  }
+
+  il_parenthesis_level--;
+  if (il_parenthesis_level < 0) ERROR;
+
+  il_operand_type = il_default_variable_type;
+  il_default_variable_type = il_default_variable_type_back;
+
+  /* Now check the if the data type semantics of operation are correct,
+   * but only if no previous error has been found...
+   */
+  if (il_error)
+    return NULL;
+  symbol->il_expr_operator->accept(*this);
+
+  return NULL;
+}
+
+
+#if 0
+/*  il_jump_operator label */
+SYM_REF2(il_jump_operation_c, il_jump_operator, label)
+void *visit_expression_type_c::visit(il_jump_operation_c *symbol);
+#endif
+
+
+/*   il_call_operator prev_declared_fb_name
+ * | il_call_operator prev_declared_fb_name '(' ')'
+ * | il_call_operator prev_declared_fb_name '(' eol_list ')'
+ * | il_call_operator prev_declared_fb_name '(' il_operand_list ')'
+ * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')'
+ */
+/* SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list) */
+void *visit_expression_type_c::visit(il_fb_call_c *symbol) {
+  if (il_error)
+    return NULL;
+
+  /* first check whether the il_default_variable is of the correct type
+   * for the CAL / CALC / CALCN operator being used...
+   */
+  symbol->il_call_operator->accept(*this);
+
+  /* Now check the FB call itself... */
+
+  /* First we find the declaration of the FB type of the FB instance being called... */
+  /* e.g.  Function_block foo_fb_type
+   *         ...
+   *       End_Function_Block
+   *
+   *       Program test
+   *         var fb1 : foo_fb_type; end_var
+   *         fb1(...)
+   *       End_Program
+   *
+   *    search_varfb_instance_type->get_type( identifier_c("fb1") )
+   *    in the scope of Program 'test'
+   *    will return the fb declaration of foo_fb_type !!
+   */
+#if 0
+  symbol_c *fb_decl_symbol = search_varfb_instance_type->get_type(symbol->fb_name);
+    /* The following should never occur. The function block must be defined, 
+     * and the FB type being called MUST be in the symtable... 
+     * This was all already checked at stage 2!
+     */
+  if (NULL == fb_decl_symbol) ERROR;
+
+  function_block_declaration_c *fb_decl = dynamic_cast<function_block_declaration_c *>(fb_decl_symbol);
+    /* should never occur. ... */
+  if (NULL == fb_decl) ERROR;
+#endif
+  symbol_c *fb_decl = search_varfb_instance_type->get_type(symbol->fb_name);
+    /* The following should never occur. The function block must be defined, 
+     * and the FB type being called MUST be in the symtable... 
+     * This was all already checked at stage 2!
+     */
+  if (NULL == fb_decl) ERROR;
+
+  /* now check the semantics of the fb call... */
+  /* If the syntax parser is working correctly, exactly one of the 
+   * following two symbols will be NULL, while the other is != NULL.
+   */
+  if (NULL != symbol->il_operand_list)  check_nonformal_call(symbol, fb_decl);
+  if (NULL != symbol->il_param_list)    check_formal_call   (symbol, fb_decl);
+
+  return NULL;
+}
+
+
+
+/* | function_name '(' eol_list [il_param_list] ')' */
+/* SYM_REF2(il_formal_funct_call_c, function_name, il_param_list) */
+void *visit_expression_type_c::visit(il_formal_funct_call_c *symbol) {
+  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_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;
+
+    /* 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;
+  }
+  return NULL;
+}
+
+
+#if 0
+/* | il_operand_list ',' il_operand */
+SYM_LIST(il_operand_list_c)
+void *visit_expression_type_c::visit(il_operand_list_c *symbol);
+
+/* | simple_instr_list il_simple_instruction */
+SYM_LIST(simple_instr_list_c)
+void *visit_expression_type_c::visit(simple_instr_list_c *symbol);
+
+/* | il_initial_param_list il_param_instruction */
+SYM_LIST(il_param_list_c)
+void *visit_expression_type_c::visit(il_param_list_c *symbol);
+
+/*  il_assign_operator il_operand
+ * | il_assign_operator '(' eol_list simple_instr_list ')'
+ */
+SYM_REF3(il_param_assignment_c, il_assign_operator, il_operand, simple_instr_list)
+void *visit_expression_type_c::visit(il_param_assignment_c *symbol);
+/*  il_assign_out_operator variable */
+SYM_REF2(il_param_out_assignment_c, il_assign_out_operator, variable)
+void *visit_expression_type_c::visit(il_param_out_assignment_c *symbol);
+
+#endif
+
+
+/*******************/
+/* B 2.2 Operators */
+/*******************/
+
+//SYM_REF0(LD_operator_c)
+void *visit_expression_type_c::visit(LD_operator_c *symbol) {
+  if (0 == il_parenthesis_level)
+    il_error = false;
+
+  if(il_operand_type == NULL)
+      STAGE3_ERROR(symbol, symbol, "LD operator requires an operand.");
+  il_default_variable_type = il_operand_type;
+  return NULL;
+}
+
+// SYM_REF0(LDN_operator_c)
+void *visit_expression_type_c::visit(LDN_operator_c *symbol) {
+  if(il_operand_type == NULL)
+      STAGE3_ERROR(symbol, symbol, "LDN operator requires an operand.");
+  if(!is_ANY_BIT_type(il_operand_type))
+      STAGE3_ERROR(symbol, symbol, "invalid data type of LDN operand, should be of type ANY_BIT.");
+  il_default_variable_type = il_operand_type;
+  return NULL;
+}
+
+// SYM_REF0(ST_operator_c)
+void *visit_expression_type_c::visit(ST_operator_c *symbol) {
+  verify_null(symbol);
+  if(!is_compatible_type(il_default_variable_type, il_operand_type))
+    STAGE3_ERROR(symbol, symbol, "Type mismatch in ST operation.");
+  /* TODO: check whether il_operand_type is an LVALUE !! */
+  /* data type of il_default_variable_type is unchanged... */
+  // il_default_variable_type = il_default_variable_type;
+  return NULL;
+}
+
+// SYM_REF0(STN_operator_c)
+ void *visit_expression_type_c::visit(STN_operator_c *symbol) {
+  verify_null(symbol);
+  if(!is_compatible_type(il_default_variable_type, il_operand_type))
+    STAGE3_ERROR(symbol, symbol, "Type mismatch in ST operation.");
+  /* TODO: check whether il_operand_type is an LVALUE !! */
+  if(!is_ANY_BIT_type(il_default_variable_type))
+      STAGE3_ERROR(symbol, symbol, "invalid data type of il_default_variable for STN operand, should be of type ANY_BIT.");
+  if(!is_ANY_BIT_type(il_operand_type))
+      STAGE3_ERROR(symbol, symbol, "invalid data type of STN operand, should be of type ANY_BIT.");
+  /* data type of il_default_variable_type is unchanged... */
+  // il_default_variable_type = il_default_variable_type;
+  return NULL;
+}
+
+//SYM_REF0(NOT_operator_c)
+void *visit_expression_type_c::visit(NOT_operator_c *symbol) {
+  if(il_operand_type != NULL){
+    STAGE3_ERROR(symbol, symbol, "NOT operator may not have an operand.");
+    return NULL;
+  }
+  if(il_default_variable_type == NULL) {
+    STAGE3_ERROR(symbol, symbol, "Il default variable should not be NULL.");
+    return NULL;
+  }
+  if(!is_ANY_BIT_type(il_default_variable_type)) {
+    STAGE3_ERROR(symbol, symbol, "Il default variable should be of type ANY_BIT.");
+    return NULL;
+  }
+  /* data type of il_default_variable_type is unchanged... */
+  // il_default_variable_type = il_default_variable_type;
+  return NULL;
+}
+
+// SYM_REF0(S_operator_c)
+void *visit_expression_type_c::visit(S_operator_c *symbol) {
+  verify_null(symbol);
+  if (!is_BOOL_type(il_default_variable_type)) {STAGE3_ERROR(symbol, symbol, "IL default variable should be BOOL type.");}
+  if (!is_BOOL_type(il_operand_type)) {STAGE3_ERROR(symbol, symbol, "operator S requires operand of type BOOL.");}
+  /* TODO: check whether il_operand_type is an LVALUE !! */
+  /* data type of il_default_variable_type is unchanged... */
+  // il_default_variable_type = il_default_variable_type;
+  return NULL;
+}
+
+// SYM_REF0(R_operator_c)
+void *visit_expression_type_c::visit(R_operator_c *symbol) {
+  verify_null(symbol);
+  if (!is_BOOL_type(il_default_variable_type)) {STAGE3_ERROR(symbol, symbol, "IL default variable should be BOOL type.");}
+  if (!is_BOOL_type(il_operand_type)) {STAGE3_ERROR(symbol, symbol, "operator R requires operand of type BOOL.");}
+  /* TODO: check whether il_operand_type is an LVALUE !! */
+  /* data type of il_default_variable_type is unchanged... */
+  // il_default_variable_type = il_default_variable_type;
+  return NULL;
+}
+
+
+// SYM_REF0(S1_operator_c)
+void *visit_expression_type_c::visit(S1_operator_c *symbol){
+  compute_input_operatores(symbol, "S1");
+  return NULL;
+}
+
+// SYM_REF0(R1_operator_c)
+void *visit_expression_type_c::visit(R1_operator_c *symbol) {
+  compute_input_operatores(symbol, "R1");
+  return NULL;
+}
+
+// SYM_REF0(CLK_operator_c)
+void *visit_expression_type_c::visit(CLK_operator_c *symbol) {
+  compute_input_operatores(symbol, "CLK");
+  return NULL;
+}
+
+// SYM_REF0(CU_operator_c)
+void *visit_expression_type_c::visit(CU_operator_c *symbol) {
+  compute_input_operatores(symbol, "CU");
+  return NULL;
+}
+
+// SYM_REF0(CD_operator_c)
+void *visit_expression_type_c::visit(CD_operator_c *symbol) {
+  compute_input_operatores(symbol, "CD");
+  return NULL;
+}
+
+// SYM_REF0(PV_operator_c)
+void *visit_expression_type_c::visit(PV_operator_c *symbol) {
+  compute_input_operatores(symbol, "PV");
+  return NULL;
+}
+
+// SYM_REF0(IN_operator_c)
+void *visit_expression_type_c::visit(IN_operator_c *symbol) {
+  compute_input_operatores(symbol, "IN");
+  return NULL;
+}
+
+// SYM_REF0(PT_operator_c)
+void *visit_expression_type_c::visit(PT_operator_c *symbol) {
+  compute_input_operatores(symbol, "PT");
+  return NULL;
+}
+
+//SYM_REF0(AND_operator_c)
+void *visit_expression_type_c::visit(AND_operator_c *symbol) {
+  verify_null(symbol);
+  il_default_variable_type = compute_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  return NULL;
+}
+
+//SYM_REF0(OR_operator_c)
+void *visit_expression_type_c::visit(OR_operator_c *symbol) {
+  verify_null(symbol);
+  il_default_variable_type = compute_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  return NULL;
+}
+
+//SYM_REF0(XOR_operator_c)
+void *visit_expression_type_c::visit(XOR_operator_c *symbol) {
+  verify_null(symbol);
+  il_default_variable_type = compute_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  return NULL;
+}
+
+// SYM_REF0(ANDN_operator_c)
+void *visit_expression_type_c::visit(ANDN_operator_c *symbol) {
+  verify_null(symbol);
+  il_default_variable_type = compute_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  return NULL;
+}
+
+// SYM_REF0(ORN_operator_c)
+void *visit_expression_type_c::visit(ORN_operator_c *symbol) {
+  verify_null(symbol);
+  il_default_variable_type = compute_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  return NULL;
+}
+
+// SYM_REF0(XORN_operator_c)
+void *visit_expression_type_c::visit(XORN_operator_c *symbol) {
+  verify_null(symbol);
+  il_default_variable_type = compute_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  return NULL;
+}
+
+// SYM_REF0(ADD_operator_c)
+void *visit_expression_type_c::visit(ADD_operator_c *symbol) {
+  verify_null(symbol);
+  symbol_c *left_type  = il_default_variable_type;
+  symbol_c *right_type = il_operand_type;
+  if      (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) 
+    il_default_variable_type = &time_type_name;
+  else if (typeid(*left_type) == typeid(tod_type_name_c)  && typeid(*right_type) == typeid(time_type_name_c)) 
+    il_default_variable_type = &tod_type_name;
+  else if (typeid(*left_type) == typeid(dt_type_name_c)   && typeid(*right_type) == typeid(time_type_name_c)) 
+    il_default_variable_type = &dt_type_name;
+  else il_default_variable_type = compute_numeric_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_MAGNITUDE_type);
+  return NULL;
+}
+
+// SYM_REF0(SUB_operator_c)
+void *visit_expression_type_c::visit(SUB_operator_c *symbol) {
+  verify_null(symbol);
+  symbol_c *left_type = il_default_variable_type;
+  symbol_c *right_type = il_operand_type;;
+  if      (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c))
+    il_default_variable_type = &time_type_name;
+  else if (typeid(*left_type) == typeid(date_type_name_c) && typeid(*right_type) == typeid(date_type_name_c))
+    il_default_variable_type = &time_type_name;
+  else if (typeid(*left_type) == typeid(tod_type_name_c)  && typeid(*right_type) == typeid(time_type_name_c))
+    il_default_variable_type = &tod_type_name;
+  else if (typeid(*left_type) == typeid(tod_type_name_c)  && typeid(*right_type) == typeid(tod_type_name_c))
+    il_default_variable_type = &time_type_name;
+  else if (typeid(*left_type) == typeid(dt_type_name_c)   && typeid(*right_type) == typeid(time_type_name_c))
+    il_default_variable_type = &dt_type_name;
+  else if (typeid(*left_type) == typeid(dt_type_name_c)   && typeid(*right_type) == typeid(dt_type_name_c))
+    il_default_variable_type = &time_type_name;
+  else il_default_variable_type = compute_numeric_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_MAGNITUDE_type);
+  return NULL;
+}
+
+// SYM_REF0(MUL_operator_c)
+void *visit_expression_type_c::visit(MUL_operator_c *symbol) {
+  verify_null(symbol);
+  symbol_c *left_type = il_default_variable_type;
+  symbol_c *right_type = il_operand_type;
+  if (typeid(*left_type) == typeid(time_type_name_c) && is_ANY_NUM_type(right_type))
+    il_default_variable_type = &time_type_name;
+  else il_default_variable_type = compute_numeric_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_NUM_type);
+  return NULL;
+}
+
+// SYM_REF0(DIV_operator_c)
+void *visit_expression_type_c::visit(DIV_operator_c *symbol) {
+  verify_null(symbol);
+  symbol_c *left_type = il_default_variable_type;
+  symbol_c *right_type = il_operand_type;
+  if (typeid(*left_type) == typeid(time_type_name_c) && is_ANY_NUM_type(right_type))
+    il_default_variable_type = &time_type_name;
+  else il_default_variable_type = compute_numeric_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_NUM_type);
+  return NULL;
+}
+
+// SYM_REF0(MOD_operator_c)
+void *visit_expression_type_c::visit(MOD_operator_c *symbol) {
+  verify_null(symbol);
+  il_default_variable_type = compute_numeric_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_INT_type); 
+  return NULL;
+}
+
+// SYM_REF0(GT_operator_c)
+void *visit_expression_type_c::visit(GT_operator_c *symbol) {
+  verify_null(symbol);
+  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  il_default_variable_type = &search_expression_type_c::bool_type_name;
+  return NULL;
+}
+
+//SYM_REF0(GE_operator_c)
+void *visit_expression_type_c::visit(GE_operator_c *symbol) {
+  verify_null(symbol);
+  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  il_default_variable_type = &search_expression_type_c::bool_type_name;
+  return NULL;
+}
+
+//SYM_REF0(EQ_operator_c)
+void *visit_expression_type_c::visit(EQ_operator_c *symbol) {
+  verify_null(symbol);
+  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  il_default_variable_type = &search_expression_type_c::bool_type_name;
+  return NULL;
+}
+
+//SYM_REF0(LT_operator_c)
+void *visit_expression_type_c::visit(LT_operator_c *symbol) {
+  verify_null(symbol);
+  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  il_default_variable_type = &search_expression_type_c::bool_type_name;
+  return NULL;
+}
+
+//SYM_REF0(LE_operator_c)
+void *visit_expression_type_c::visit(LE_operator_c *symbol) {
+  verify_null(symbol);
+  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  il_default_variable_type = &search_expression_type_c::bool_type_name;
+  return NULL;
+}
+
+//SYM_REF0(NE_operator_c)
+void *visit_expression_type_c::visit(NE_operator_c *symbol) {
+  verify_null(symbol);
+  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  il_default_variable_type = &search_expression_type_c::bool_type_name;
+  return NULL;
+}
+
+// SYM_REF0(CAL_operator_c)
+void *visit_expression_type_c::visit(CAL_operator_c *symbol) {
+  return NULL;
+}
+
+// SYM_REF0(CALC_operator_c)
+void *visit_expression_type_c::visit(CALC_operator_c *symbol) {
+  if(il_default_variable_type == NULL)
+    STAGE3_ERROR(symbol, symbol, "CALC: il default variable should not be NULL.");
+  if (!is_BOOL_type(il_default_variable_type))
+    STAGE3_ERROR(symbol, symbol, "CALC operator requires il_default_variable to be of type BOOL.");
+  return NULL;
+}
+
+// SYM_REF0(CALCN_operator_c)
+void *visit_expression_type_c::visit(CALCN_operator_c *symbol) {
+  if(il_default_variable_type == NULL)
+    STAGE3_ERROR(symbol, symbol, "CALCN: il_default_variable should not be NULL.");
+  if (!is_BOOL_type(il_default_variable_type))
+    STAGE3_ERROR(symbol, symbol, "CALCN operator requires il_default_variable to be of type BOOL.");
+  return NULL;
+}
+
+// SYM_REF0(RET_operator_c)
+void *visit_expression_type_c::visit(RET_operator_c *symbol) {
+  return NULL;
+}
+
+// SYM_REF0(RETC_operator_c)
+void *visit_expression_type_c::visit(RETC_operator_c *symbol) {
+  if(il_default_variable_type == NULL)
+    STAGE3_ERROR(symbol, symbol, "RETC: il default variable should not be NULL.");
+  if (!is_BOOL_type(il_default_variable_type))
+    STAGE3_ERROR(symbol, symbol, "RETC operator requires il_default_variable to be of type BOOL.");
+  return NULL;
+}
+
+// SYM_REF0(RETCN_operator_c)
+void *visit_expression_type_c::visit(RETCN_operator_c *symbol) {
+  if(il_default_variable_type == NULL)
+    STAGE3_ERROR(symbol, symbol, "RETCN: il_default_variable should not be NULL.");
+  if (!is_BOOL_type(il_default_variable_type))
+    STAGE3_ERROR(symbol, symbol, "RETCN operator requires il_default_variable to be of type BOOL.");
+  return NULL;
+}
+
+// SYM_REF0(JMP_operator_c)
+void *visit_expression_type_c::visit(JMP_operator_c *symbol){
+  return NULL;
+}
+
+// SYM_REF0(JMPC_operator_c)
+void *visit_expression_type_c::visit(JMPC_operator_c *symbol) {
+  if(il_default_variable_type == NULL)
+    STAGE3_ERROR(symbol, symbol, "JMPC: il default variable should not be NULL.");
+  if (!is_BOOL_type(il_default_variable_type))
+    STAGE3_ERROR(symbol, symbol, "JMPC operator requires il_default_variable to be of type BOOL.");
+  return NULL;
+}
+
+// SYM_REF0(JMPCN_operator_c)
+void *visit_expression_type_c::visit(JMPCN_operator_c *symbol) {
+  if(il_default_variable_type == NULL)
+    STAGE3_ERROR(symbol, symbol, "JMPCN: il_default_variable should not be NULL.");
+  if (!is_BOOL_type(il_default_variable_type))
+    STAGE3_ERROR(symbol, symbol, "JMPCN operator requires il_default_variable to be of type BOOL.");
+  return NULL;
+}
+
+/* Symbol class handled together with function call checks */
+/*  any_identifier ASSIGN */
+// SYM_REF1(il_assign_operator_c, variable_name)
+// void *visit_expression_type_c::visit(il_assign_operator_c *symbol, variable_name);
+
+/* Symbol class handled together with function call checks */
+/*| [NOT] any_identifier SENDTO */
+// SYM_REF2(il_assign_out_operator_c, option, variable_name)
+// void *visit_expression_type_c::visit(il_assign_operator_c *symbol, option, variable_name);
+
+
+
+
+
+/***************************************/
+/* B.3 - Language ST (Structured Text) */
+/***************************************/
+/***********************/
+/* B 3.1 - Expressions */
+/***********************/
+
+void *visit_expression_type_c::visit(or_expression_c *symbol) {
+  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  return compute_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_type);
+}
+
+
+void *visit_expression_type_c::visit(xor_expression_c *symbol) {
+  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  return compute_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_type);
+}
+
+
+void *visit_expression_type_c::visit(and_expression_c *symbol) {
+  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  return compute_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_type);
+}
+
+
+void *visit_expression_type_c::visit(equ_expression_c *symbol) {
+  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  compute_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  return &search_expression_type_c::bool_type_name;
+}
+
+
+void *visit_expression_type_c::visit(notequ_expression_c *symbol)  {
+  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  compute_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  return &search_expression_type_c::bool_type_name;
+}
+
+
+void *visit_expression_type_c::visit(lt_expression_c *symbol) {
+  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  compute_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  return &search_expression_type_c::bool_type_name;
+}
+
+
+void *visit_expression_type_c::visit(gt_expression_c *symbol) {
+  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  compute_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  return &search_expression_type_c::bool_type_name;
+}
+
+
+void *visit_expression_type_c::visit(le_expression_c *symbol) {
+  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  compute_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  return &search_expression_type_c::bool_type_name;
+}
+
+
+void *visit_expression_type_c::visit(ge_expression_c *symbol) {
+  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  compute_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  return &search_expression_type_c::bool_type_name;
+}
+
+
+void *visit_expression_type_c::visit(add_expression_c *symbol) {
+  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&time_type_name;}
+  if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&tod_type_name;}
+  if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&dt_type_name;}
+  return compute_numeric_expression(left_type, right_type, &visit_expression_type_c::is_ANY_MAGNITUDE_type);
+}
+
+
+void *visit_expression_type_c::visit(sub_expression_c *symbol) {
+  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&time_type_name;}
+  if (typeid(*left_type) == typeid(date_type_name_c) && typeid(*right_type) == typeid(date_type_name_c)) {return (void *)&time_type_name;}
+  if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&tod_type_name;}
+  if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(tod_type_name_c)) {return (void *)&time_type_name;}
+  if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&dt_type_name;}
+  if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(dt_type_name_c)) {return (void *)&time_type_name;}
+  return compute_numeric_expression(left_type, right_type, &visit_expression_type_c::is_ANY_MAGNITUDE_type);
+}
+
+
+void *visit_expression_type_c::visit(mul_expression_c *symbol) {
+  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  if (typeid(*left_type) == typeid(time_type_name_c) && is_ANY_NUM_type(right_type)) {return (void *)&time_type_name;}
+  return compute_numeric_expression(left_type, right_type, &visit_expression_type_c::is_ANY_NUM_type);
+}
+
+
+void *visit_expression_type_c::visit(div_expression_c *symbol) {
+  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  if (typeid(*left_type) == typeid(time_type_name_c) && is_ANY_NUM_type(right_type)){return (void *)&time_type_name;}
+  return compute_numeric_expression(left_type, right_type, &visit_expression_type_c::is_ANY_NUM_type);
+}
+
+
+void *visit_expression_type_c::visit(mod_expression_c *symbol) {
+  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  return compute_numeric_expression(left_type, right_type, &visit_expression_type_c::is_ANY_INT_type);
+}
+
+
+void *visit_expression_type_c::visit(power_expression_c *symbol) {
+  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+  if (!is_ANY_REAL_type(left_type))
+    STAGE3_ERROR(symbol->l_exp, symbol->l_exp, "first operand of ** operator has invalid data type, should be of type ANY_REAL.");
+  if (!is_ANY_NUM_type(right_type))
+    STAGE3_ERROR(symbol->r_exp, symbol->r_exp, "second operand of ** operator has invalid data type, should be of type ANY_NUM.");
+
+  return (void *)left_type;
+}
+
+
+void *visit_expression_type_c::visit(neg_expression_c *symbol) {
+  symbol_c *exp_type = base_type((symbol_c *)symbol->exp->accept(*this));
+  if (!is_ANY_MAGNITUDE_type(exp_type))
+    STAGE3_ERROR(symbol, symbol, "operand of negate expression '-' has invalid data type, should be of type ANY_MAGNITUDE.");
+
+  return exp_type;
+}
+
+
+void *visit_expression_type_c::visit(not_expression_c *symbol) {
+  symbol_c *type = base_type((symbol_c *)symbol->exp->accept(*this));
+  return compute_boolean_expression(type, type, &visit_expression_type_c::is_ANY_BIT_type);
+}
+
+
+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);
+}
+
+/********************/
+/* B 3.2 Statements */
+/********************/
+// SYM_LIST(statement_list_c)
+/* The visitor of the base class search_visitor_c will handle calling each instruction in the list.
+ * We do not need to do anything here...
+ */
+// void *visit_expression_type_c::visit(statement_list_c *symbol)
+
+
+/*********************************/
+/* B 3.2.1 Assignment Statements */
+/*********************************/
+
+void *visit_expression_type_c::visit(assignment_statement_c *symbol) {
+  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
+  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
+
+  if (!is_compatible_type(left_type, right_type))  {
+     STAGE3_ERROR(symbol, symbol, "data type mismatch in assignment statement!\n");
+  }
+  return NULL;
+}
+
+
+
+/*****************************************/
+/* B 3.2.2 Subprogram Control Statements */
+/*****************************************/
+
+/*  RETURN */
+// SYM_REF0(return_statement_c)
+
+
+/* fb_name '(' [param_assignment_list] ')' */
+/* param_assignment_list -> may be NULL ! */
+// SYM_REF3(fb_invocation_c, fb_name, formal_param_list, nonformal_param_list)
+void *visit_expression_type_c::visit(fb_invocation_c *symbol) {
+  symbol_c *fb_decl = search_varfb_instance_type->get_type(symbol->fb_name);
+    /* The following should never occur. The function block must be defined, 
+     * and the FB type being called MUST be in the symtable... 
+     * This was all already checked at stage 2!
+     */
+  if (NULL == fb_decl) ERROR;
+
+  /* now check the semantics of the fb 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, fb_decl);
+  if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, fb_decl);
+
+  return NULL;
+}
+
+
+#if 0
+/* helper symbol for fb_invocation */
+/* param_assignment_list ',' param_assignment */
+SYM_LIST(param_assignment_list_c)
+
+/*  variable_name ASSIGN expression */
+SYM_REF2(input_variable_param_assignment_c, variable_name, expression)
+
+/* [NOT] variable_name '=>' variable */
+SYM_REF3(output_variable_param_assignment_c, not_param, variable_name, variable)
+
+/* helper CLASS for output_variable_param_assignment */
+SYM_REF0(not_paramassign_c)
+#endif
+
+/********************************/
+/* B 3.2.3 Selection Statements */
+/********************************/
+
+/* IF expression THEN statement_list elseif_statement_list ELSE statement_list END_IF */
+// SYM_REF4(if_statement_c, expression, statement_list, elseif_statement_list, else_statement_list)
+void *visit_expression_type_c::visit(if_statement_c *symbol) {
+  symbol_c *expr_type = base_type((symbol_c*)symbol->expression->accept(*this));
+  if (!is_BOOL_type(expr_type)) STAGE3_ERROR(symbol,symbol,"IF conditional expression is not of boolean type.");
+  if (NULL != symbol->statement_list)
+    symbol->statement_list->accept(*this); 
+  if (NULL != symbol->elseif_statement_list)  
+    symbol->elseif_statement_list->accept(*this);
+  if (NULL != symbol->else_statement_list)  
+    symbol->else_statement_list->accept(*this);  
+  return NULL;
+}
+
+/* helper symbol for if_statement */
+// SYM_LIST(elseif_statement_list_c)
+// void *visit_expression_type_c::visit(elseif_statement_list_c *symbol) { }
+
+/* helper symbol for elseif_statement_list */
+/* ELSIF expression THEN statement_list    */
+// SYM_REF2(elseif_statement_c, expression, statement_list)
+void *visit_expression_type_c::visit(elseif_statement_c *symbol) {
+  symbol_c *elseif_expr_type = base_type((symbol_c*)symbol->expression->accept(*this));
+  if(!is_BOOL_type(elseif_expr_type)) STAGE3_ERROR(symbol,symbol,"ELSIF conditional expression is not of boolean type.");
+  if (NULL != symbol->statement_list)
+    symbol->statement_list->accept(*this); 
+  return NULL;
+}
+
+
+/* CASE expression OF case_element_list ELSE statement_list END_CASE */
+// SYM_REF3(case_statement_c, expression, case_element_list, statement_list)
+void *visit_expression_type_c::visit(case_statement_c *symbol) {
+  case_expression_type = base_type((symbol_c*)symbol->expression->accept(*this));
+  if (NULL != case_expression_type) {
+    if (NULL != symbol->case_element_list)
+      symbol->case_element_list->accept(*this);
+  }
+  if (NULL != symbol->statement_list)
+    symbol->statement_list->accept(*this);
+  return NULL;
+}
+
+#if 0
+/* helper symbol for case_statement */
+// SYM_LIST(case_element_list_c)
+// void *visit_expression_type_c::visit(case_element_list_c *symbol);
+
+/*  case_list ':' statement_list */
+// SYM_REF2(case_element_c, case_list, statement_list)
+void *visit_expression_type_c::visit(case_element_c *symbol);  
+#endif
+
+// SYM_LIST(case_list_c)
+void *visit_expression_type_c::visit(case_list_c *symbol) {
+  symbol_c *element_type;
+  for(int i = 0; i < symbol->n; i++) {
+    element_type = (symbol_c *)symbol->elements[i]->accept(*this);
+    if (NULL == element_type) {
+      STAGE3_ERROR(symbol->elements[i], symbol->elements[i], "Case list element has undefined data type.");
+    } else {
+      element_type = base_type(element_type);
+      if (NULL != element_type){
+        if (!is_compatible_type(case_expression_type, element_type))
+          STAGE3_ERROR(symbol->elements[i], symbol->elements[i], "Invalid data type of case list element.");
+      }
+    }
+  }
+  return NULL;
+}
+
+/********************************/
+/* B 3.2.4 Iteration Statements */
+/********************************/
+
+/*  FOR control_variable ASSIGN expression TO expression [BY expression] DO statement_list END_FOR */
+// SYM_REF5(for_statement_c, control_variable, beg_expression, end_expression, by_expression, statement_list)
+void *visit_expression_type_c::visit(for_statement_c *symbol) {
+  symbol_c *var_type = (symbol_c*)symbol->control_variable->accept(*this);
+  if (NULL == var_type) ERROR;
+  var_type = base_type(var_type);
+  if (NULL == var_type) ERROR;
+  // ASSIGN
+  symbol_c *beg_expr_type = base_type((symbol_c*)symbol->beg_expression->accept(*this));
+  if (NULL != beg_expr_type) { 
+    if(!is_compatible_type(var_type,beg_expr_type)) 
+      STAGE3_ERROR(symbol, symbol, "Data type mismatch between control variable and initial value.");
+  }
+  // TO
+  symbol_c *end_expr_type = base_type((symbol_c*)symbol->end_expression->accept(*this));
+  if (NULL != end_expr_type) { 
+    if(!is_compatible_type(var_type,end_expr_type)) 
+      STAGE3_ERROR(symbol, symbol, "Data type mismatch between control variable and final value.");
+  }
+  // BY
+  if(symbol->by_expression != NULL) {
+    symbol_c *by_expr_type = base_type((symbol_c*)symbol->by_expression->accept(*this));
+    if (NULL != end_expr_type) {   
+      if(!is_compatible_type(var_type,by_expr_type)) 
+        STAGE3_ERROR(symbol, symbol, "Data type mismatch between control variable and BY value.");
+    }
+  }
+  // DO
+  if (NULL != symbol->statement_list)
+    symbol->statement_list->accept(*this); 
+  return NULL;
+}
+
+
+/*  WHILE expression DO statement_list END_WHILE */
+// SYM_REF2(while_statement_c, expression, statement_list)
+void *visit_expression_type_c::visit(while_statement_c *symbol) {
+  symbol_c *expr_type = base_type((symbol_c*)symbol->expression->accept(*this));
+  if (NULL != expr_type) {
+    if(!is_BOOL_type(expr_type)) 
+      STAGE3_ERROR(symbol,symbol,"WHILE conditional expression is not of boolean type.");
+  }
+ 
+  if (NULL != symbol->statement_list)
+    symbol->statement_list->accept(*this); 
+  return NULL;
+}
+
+/*  REPEAT statement_list UNTIL expression END_REPEAT */
+// SYM_REF2(repeat_statement_c, statement_list, expression)
+void *visit_expression_type_c::visit(repeat_statement_c *symbol) {
+  if (NULL != symbol->statement_list)
+    symbol->statement_list->accept(*this); 
+ 
+  symbol_c *expr_type = base_type((symbol_c*)symbol->expression->accept(*this));
+  if (NULL != expr_type) {
+    if(!is_BOOL_type(expr_type)) 
+      STAGE3_ERROR(symbol,symbol,"REPEAT conditional expression is not of boolean type.");
+  }
+  return NULL;
+}
+
+/*  EXIT */
+// SYM_REF0(exit_statement_c)
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/visit_expression_type.hh	Wed Sep 02 14:05:27 2009 +0200
@@ -0,0 +1,294 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+/* Verify whether the semantic rules of data type compatibility are being followed.
+ *
+ * For example:
+ */
+
+#include "../absyntax_utils/absyntax_utils.hh"
+
+class visit_expression_type_c: public search_constant_type_c {
+
+  private:
+    search_varfb_instance_type_c *search_varfb_instance_type;
+    search_base_type_c search_base_type;
+
+    /* When calling a function block, we must first find it's type,
+     * by searching through the declarations of the variables currently
+     * in scope.
+     * This class does just that...
+     * A new bject instance is instantiated whenever we start checking semantics
+     * for a function block type declaration, or a program declaration.
+     * This object instance will then later be called while the
+     * function block's or the program's body is being handled.
+     *
+     * Note that functions cannot contain calls to function blocks,
+     * so we do not create an object instance when handling
+     * a function declaration.
+     */
+//     search_var_instance_decl_c *search_var_instance_decl;
+    
+     /* This variable was created to pass information from
+      * visit_expression_type_c::visit(case_statement_c *symbol) function to
+      * visit_expression_type_c::visit(case_list_c *symbol) function.
+      */
+      symbol_c *case_expression_type;
+  
+    /* In IL code, once we find a type mismatch error, it is best to
+     * ignore any further errors until the end of the logicl operation,
+     * i.e. until the next LD.
+     * However, we cannot clear the il_error flag on all LD operations,
+     * as these may also be used within parenthesis. LD operations
+     * within parenthesis may not clear the error flag.
+     * We therefore need a counter to know how deep inside a parenthesis 
+     * structure we are.
+     */
+    int  il_parenthesis_level;
+    bool il_error;
+
+    symbol_c *il_default_variable_type;
+    symbol_c *il_operand_type;
+
+
+  public:
+    visit_expression_type_c(symbol_c *search_scope);
+    virtual ~visit_expression_type_c(void);
+
+    /* A helper function... */
+    bool is_ANY_ELEMENTARY_type(symbol_c *type_symbol);
+    bool is_ANY_MAGNITUDE_type(symbol_c *type_symbol);
+    bool is_ANY_DATE_type(symbol_c *type_symbol);
+    bool is_ANY_STRING_type(symbol_c *type_symbol);
+    bool is_ANY_INT_type(symbol_c *type_symbol);
+    bool is_ANY_REAL_type(symbol_c *type_symbol);
+    bool is_ANY_NUM_type(symbol_c *type_symbol);
+    bool is_ANY_BIT_type(symbol_c *type_symbol);
+    bool is_BOOL_type(symbol_c *type_symbol);
+
+    bool is_literal_integer_type(symbol_c *type_symbol);
+    bool is_literal_real_type(symbol_c *type_symbol);
+    bool is_literal_bool_type(symbol_c *type_symbol);
+
+    /* Determine the common data type between two data types.
+     * If no common data type found, return NULL.
+     *
+     * If data types are identical, return the first (any would do...).
+     * If any of the datat types is a literal, we confirm that 
+     *   the literal uses less bits than the fixed size data type.
+     *   e.g. BYTE and 1024 returns NULL
+     *        BYTE and 255  returns BYTE
+     *
+     * If two literals, then return the literal that requires more bits...
+     */
+    symbol_c *common_type__(symbol_c *first_type, symbol_c *second_type);
+    /* Determine the common data type between two data types.
+     * Unlike the common_type__() function, we stop the compiler with an ERROR
+     *  if no common data type is found.
+     */
+    symbol_c *common_type(symbol_c *first_type, symbol_c *second_type);
+    /* Return TRUE if there is a common data type, otherwise return FALSE */
+    bool is_compatible_type(symbol_c *first_type, symbol_c *second_type);
+
+    void compute_input_operatores(symbol_c *symbol, const char *input_operator);
+    void check_formal_parameter(symbol_c *call_param_name, symbol_c *call_param_type, symbol_c *f_decl);
+
+    /* 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);
+    /* 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);
+
+
+    void *compute_standard_function_default(function_invocation_c *st_symbol, il_formal_funct_call_c *il_symbol);
+    void *compute_standard_function_il(il_function_call_c *symbol, symbol_c *param_data_type);
+
+
+    /* A helper function... */
+    typedef bool (visit_expression_type_c::*is_data_type_t)(symbol_c *type_symbol);  /* a pointer to a function! */
+    symbol_c *compute_boolean_expression(symbol_c *left_exp, symbol_c *right_exp, is_data_type_t is_data_type);
+    symbol_c *compute_numeric_expression(symbol_c *left_exp, symbol_c *right_exp, is_data_type_t is_data_type);
+
+    /* a helper function... */
+    symbol_c *base_type(symbol_c *symbol);
+
+    /* a helper function... */
+    void *verify_null(symbol_c *symbol);
+
+
+
+
+    /*********************/
+    /* B 1.4 - Variables */
+    /*********************/
+    void *visit(symbolic_variable_c *symbol);
+
+    /********************************************/
+    /* B 1.4.1 - Directly Represented Variables */
+    /********************************************/
+    void *visit(direct_variable_c *symbol);
+
+    /*************************************/
+    /* B 1.4.2 - Multi-element variables */
+    /*************************************/
+ 
+    void *visit(array_variable_c *symbol);
+    void *visit(structured_variable_c *symbol);
+
+    /****************************************/
+    /* B.2 - Language IL (Instruction List) */
+    /****************************************/
+    /***********************************/
+    /* B 2.1 Instructions and Operands */
+    /***********************************/
+    // void *visit(instruction_list_c *symbol);
+    void *visit(il_simple_operation_c *symbol);
+    void *visit(il_function_call_c *symbol);
+    void *visit(il_expression_c *symbol);
+//     void *visit(il_jump_operation_c *symbol);
+    void *visit(il_fb_call_c *symbol);
+    void *visit(il_formal_funct_call_c *symbol);
+    /*
+    void *visit(il_operand_list_c *symbol);
+    void *visit(simple_instr_list_c *symbol);
+    void *visit(il_param_list_c *symbol);
+    void *visit(il_param_assignment_c *symbol);
+    void *visit(il_param_out_assignment_c *symbol);
+    */
+
+    /*******************/
+    /* B 2.2 Operators */
+    /*******************/
+    void *visit(LD_operator_c *symbol);
+    void *visit(LDN_operator_c *symbol);
+    void *visit(ST_operator_c *symbol);
+    void *visit(STN_operator_c *symbol);
+    void *visit(NOT_operator_c *symbol);
+    void *visit(S_operator_c *symbol);
+    void *visit(R_operator_c *symbol);
+    void *visit(S1_operator_c *symbol);
+    void *visit(R1_operator_c *symbol);
+    void *visit(CLK_operator_c *symbol);
+    void *visit(CU_operator_c *symbol);
+    void *visit(CD_operator_c *symbol);
+    void *visit(PV_operator_c *symbol);
+    void *visit(IN_operator_c *symbol);
+    void *visit(PT_operator_c *symbol);
+    void *visit(AND_operator_c *symbol);
+    void *visit(OR_operator_c *symbol);
+    void *visit(XOR_operator_c *symbol);
+    void *visit(ANDN_operator_c *symbol);
+    void *visit(ORN_operator_c *symbol);
+    void *visit(XORN_operator_c *symbol);
+    void *visit(ADD_operator_c *symbol);
+    void *visit(SUB_operator_c *symbol);
+    void *visit(MUL_operator_c *symbol);
+    void *visit(DIV_operator_c *symbol);
+    void *visit(MOD_operator_c *symbol);
+    void *visit(GT_operator_c *symbol);
+    void *visit(GE_operator_c *symbol);
+    void *visit(EQ_operator_c *symbol);
+    void *visit(LT_operator_c *symbol);
+    void *visit(LE_operator_c *symbol);
+    void *visit(NE_operator_c *symbol);
+    void *visit(CAL_operator_c *symbol);
+    void *visit(CALC_operator_c *symbol);
+    void *visit(CALCN_operator_c *symbol);
+    void *visit(RET_operator_c *symbol);
+    void *visit(RETC_operator_c *symbol);
+    void *visit(RETCN_operator_c *symbol);
+    void *visit(JMP_operator_c *symbol);
+    void *visit(JMPC_operator_c *symbol);
+    void *visit(JMPCN_operator_c *symbol);
+    /* Symbol class handled together with function call checks */
+    // void *visit(il_assign_operator_c *symbol, variable_name);
+    /* Symbol class handled together with function call checks */
+    // void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+
+
+    /***************************************/
+    /* B.3 - Language ST (Structured Text) */
+    /***************************************/
+    /***********************/
+    /* B 3.1 - Expressions */
+    /***********************/
+    void *visit(or_expression_c *symbol);
+    void *visit(xor_expression_c *symbol);
+    void *visit(and_expression_c *symbol);
+    void *visit(equ_expression_c *symbol);
+    void *visit(notequ_expression_c *symbol);
+    void *visit(lt_expression_c *symbol);
+    void *visit(gt_expression_c *symbol);
+    void *visit(le_expression_c *symbol);
+    void *visit(ge_expression_c *symbol);    
+    void *visit(add_expression_c *symbol);
+    void *visit(sub_expression_c *symbol);
+    void *visit(mul_expression_c *symbol);
+    void *visit(div_expression_c *symbol);
+    void *visit(mod_expression_c *symbol);
+    void *visit(power_expression_c *symbol);
+    void *visit(neg_expression_c *symbol);
+    void *visit(not_expression_c *symbol);
+    void *visit(function_invocation_c *symbol);
+
+    /*********************************/
+    /* B 3.2.1 Assignment Statements */
+    /*********************************/
+    void *visit(assignment_statement_c *symbol);
+
+    /*****************************************/
+    /* B 3.2.2 Subprogram Control Statements */
+    /*****************************************/
+    void *visit(fb_invocation_c *symbol);
+
+    /********************************/
+    /* B 3.2.3 Selection Statements */
+    /********************************/
+ 
+    void *visit(if_statement_c *symbol);    
+//     void *visit(elseif_statement_list_c *symbol);
+    void *visit(elseif_statement_c *symbol);
+    void *visit(case_statement_c *symbol);
+//     void *visit(case_element_list_c *symbol);
+//     void *visit(case_element_c *symbol);   
+   void *visit(case_list_c *symbol);
+    
+    /********************************/
+    /* B 3.2.4 Iteration Statements */
+    /********************************/
+    
+    void *visit(for_statement_c *symbol);
+    void *visit(while_statement_c *symbol);
+    void *visit(repeat_statement_c *symbol);
+    
+
+//TODO: delete this functions. Why are they needed?
+void *visit(program_declaration_c *symbol);
+void *visit(function_declaration_c *symbol);
+void *visit(function_block_declaration_c *symbol);
+
+}; // visit_expression_type_c
+
--- a/stage4/generate_c/generate_c.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/stage4/generate_c/generate_c.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -149,8 +149,6 @@
 #define TEMP_VAR VAR_LEADER "TMP_"
 #define SOURCE_VAR VAR_LEADER "SRC_"
 
-#include "generate_c_tempvardecl.cc"
-
 #include "generate_c_st.cc"
 #include "generate_c_il.cc"
 
@@ -498,13 +496,13 @@
   /* (A.3) Function parameters */
   s4o.indent_right();
   vardecl = new generate_c_vardecl_c(&s4o,
-  				      generate_c_vardecl_c::finterface_vf,
-  				      generate_c_vardecl_c::input_vt |
-				        generate_c_vardecl_c::output_vt |
-				        generate_c_vardecl_c::inoutput_vt |
-                generate_c_vardecl_c::eneno_vt);
+                                     generate_c_vardecl_c::finterface_vf,
+                                     generate_c_vardecl_c::input_vt    |
+                                     generate_c_vardecl_c::output_vt   |
+                                     generate_c_vardecl_c::inoutput_vt |
+                                     generate_c_vardecl_c::en_vt       |
+                                     generate_c_vardecl_c::eno_vt);
   vardecl->print(symbol->var_declarations_list);
-  vardecl->print_eneno();
   delete vardecl;
   
   s4o.indent_left();
@@ -515,11 +513,12 @@
   /* (B.1) Variables declared in ST source code */
   s4o.indent_right();
   
-  vardecl = new generate_c_vardecl_c(&s4o, 
-                generate_c_vardecl_c::localinit_vf, 
-                generate_c_vardecl_c::output_vt |
+  vardecl = new generate_c_vardecl_c(&s4o,
+                generate_c_vardecl_c::localinit_vf,
+                generate_c_vardecl_c::output_vt   |
                 generate_c_vardecl_c::inoutput_vt |
-                generate_c_vardecl_c::private_vt);
+                generate_c_vardecl_c::private_vt  |
+                generate_c_vardecl_c::eno_vt);
   vardecl->print(symbol->var_declarations_list);
   delete vardecl;
 
@@ -541,9 +540,9 @@
   s4o.print(s4o.indent_spaces + "// Control execution\n");
   s4o.print(s4o.indent_spaces + "if (!EN) {\n");
   s4o.indent_right();
-  s4o.print(s4o.indent_spaces + "if (ENO != NULL) {\n");
+  s4o.print(s4o.indent_spaces + "if (__ENO != NULL) {\n");
   s4o.indent_right();
-  s4o.print(s4o.indent_spaces + "*ENO = __BOOL_LITERAL(FALSE);\n");
+  s4o.print(s4o.indent_spaces + "*__ENO = __BOOL_LITERAL(FALSE);\n");
   s4o.indent_left();
   s4o.print(s4o.indent_spaces + "}\n");
   s4o.print(s4o.indent_spaces + "return ");
@@ -551,24 +550,16 @@
   s4o.print(";\n");
   s4o.indent_left();
   s4o.print(s4o.indent_spaces + "}\n");
-  s4o.print(s4o.indent_spaces + "else {\n");
-  s4o.indent_right();
-  s4o.print(s4o.indent_spaces + "if (ENO != NULL) {\n");
-  s4o.indent_right();
-  s4o.print(s4o.indent_spaces + "*ENO = __BOOL_LITERAL(TRUE);\n");
-  s4o.indent_left();
-  s4o.print(s4o.indent_spaces + "}\n");
-  s4o.indent_left();
-  s4o.print(s4o.indent_spaces + "}\n");
-  
+
   /* (C) Function body */
   generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol);
   symbol->function_body->accept(generate_c_code);
   
   vardecl = new generate_c_vardecl_c(&s4o,
                 generate_c_vardecl_c::foutputassign_vf,
-                generate_c_vardecl_c::output_vt |
-                generate_c_vardecl_c::inoutput_vt);
+                generate_c_vardecl_c::output_vt   |
+                generate_c_vardecl_c::inoutput_vt |
+                generate_c_vardecl_c::eno_vt);
   vardecl->print(symbol->var_declarations_list);
   delete vardecl;
   
@@ -610,23 +601,23 @@
   /* (A.2) Public variables: i.e. the function parameters... */
   s4o_incl.print(s4o_incl.indent_spaces + "// FB Interface - IN, OUT, IN_OUT variables\n");
   vardecl = new generate_c_vardecl_c(&s4o_incl,
-  				      generate_c_vardecl_c::local_vf,
-  				      generate_c_vardecl_c::input_vt |
-  				      generate_c_vardecl_c::output_vt |
-  				      generate_c_vardecl_c::inoutput_vt |
-                generate_c_vardecl_c::eneno_vt);
+                                     generate_c_vardecl_c::local_vf,
+                                     generate_c_vardecl_c::input_vt    |
+                                     generate_c_vardecl_c::output_vt   |
+                                     generate_c_vardecl_c::inoutput_vt |
+                                     generate_c_vardecl_c::en_vt       |
+                                     generate_c_vardecl_c::eno_vt);
   vardecl->print(symbol->var_declarations);
-  vardecl->print_eneno();
   delete vardecl;
   s4o_incl.print("\n");
   /* (A.3) Private internal variables */
   s4o_incl.print(s4o_incl.indent_spaces + "// FB private variables - TEMP, private and located variables\n");
   vardecl = new generate_c_vardecl_c(&s4o_incl,
-  				      generate_c_vardecl_c::local_vf,
-				        generate_c_vardecl_c::temp_vt |
-  				      generate_c_vardecl_c::private_vt |
-  				      generate_c_vardecl_c::located_vt |
-  				      generate_c_vardecl_c::external_vt);
+                                     generate_c_vardecl_c::local_vf,
+                                     generate_c_vardecl_c::temp_vt    |
+                                     generate_c_vardecl_c::private_vt |
+                                     generate_c_vardecl_c::located_vt |
+                                     generate_c_vardecl_c::external_vt);
   vardecl->print(symbol->var_declarations);
   delete vardecl;
   
@@ -660,25 +651,16 @@
   /* (B.2) Member initializations... */
   s4o.print(s4o.indent_spaces);
   vardecl = new generate_c_vardecl_c(&s4o,
-  				      generate_c_vardecl_c::constructorinit_vf,
-  				      generate_c_vardecl_c::input_vt |
-  				      generate_c_vardecl_c::output_vt |
-  				      generate_c_vardecl_c::inoutput_vt |
-  				      generate_c_vardecl_c::private_vt |
-				        generate_c_vardecl_c::located_vt |
-				        generate_c_vardecl_c::external_vt |
-                generate_c_vardecl_c::eneno_vt);
+                                     generate_c_vardecl_c::constructorinit_vf,
+                                     generate_c_vardecl_c::input_vt    |
+                                     generate_c_vardecl_c::output_vt   |
+                                     generate_c_vardecl_c::inoutput_vt |
+                                     generate_c_vardecl_c::private_vt  |
+                                     generate_c_vardecl_c::located_vt  |
+                                     generate_c_vardecl_c::external_vt |
+                                     generate_c_vardecl_c::en_vt       |
+                                     generate_c_vardecl_c::eno_vt);
   vardecl->print(symbol->var_declarations, NULL, FB_FUNCTION_PARAM"->");
-  if (!vardecl->is_en_declared()) {
-    s4o.print("\n" + s4o.indent_spaces);
-    s4o.print(FB_FUNCTION_PARAM);
-    s4o.print("->EN = __BOOL_LITERAL(TRUE);");
-  }
-  if (!vardecl->is_eno_declared()) {
-    s4o.print("\n" + s4o.indent_spaces);
-    s4o.print(FB_FUNCTION_PARAM);
-    s4o.print("->ENO = __BOOL_LITERAL(TRUE);");
-  }
   delete vardecl;
   s4o.print("\n");
   /* (B.3) Generate private internal variables for SFC */
@@ -737,8 +719,8 @@
   /* function body */
   s4o.print(s4o.indent_spaces + "// Initialise TEMP variables\n");
   vardecl = new generate_c_vardecl_c(&s4o,
-  				      generate_c_vardecl_c::init_vf,
-				      generate_c_vardecl_c::temp_vt);
+                                     generate_c_vardecl_c::init_vf,
+                                     generate_c_vardecl_c::temp_vt);
   vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
   delete vardecl;
   s4o.print("\n");
@@ -801,10 +783,10 @@
   /* (A.2) Public variables: i.e. the program parameters... */
   s4o_incl.print(s4o_incl.indent_spaces + "// PROGRAM Interface - IN, OUT, IN_OUT variables\n");
   vardecl = new generate_c_vardecl_c(&s4o_incl,
-  				      generate_c_vardecl_c::local_vf,
-  				      generate_c_vardecl_c::input_vt |
-  				      generate_c_vardecl_c::output_vt |
-  				      generate_c_vardecl_c::inoutput_vt);
+                                     generate_c_vardecl_c::local_vf,
+                                     generate_c_vardecl_c::input_vt  |
+                                     generate_c_vardecl_c::output_vt |
+                                     generate_c_vardecl_c::inoutput_vt);
   vardecl->print(symbol->var_declarations);
   delete vardecl;
   s4o_incl.print("\n");
@@ -812,7 +794,7 @@
   s4o_incl.print(s4o_incl.indent_spaces + "// PROGRAM private variables - TEMP, private and located variables\n");
   vardecl = new generate_c_vardecl_c(&s4o_incl,
                 generate_c_vardecl_c::local_vf,
-                generate_c_vardecl_c::temp_vt |
+                generate_c_vardecl_c::temp_vt    |
                 generate_c_vardecl_c::private_vt |
                 generate_c_vardecl_c::located_vt |
                 generate_c_vardecl_c::external_vt);
@@ -847,13 +829,13 @@
   /* (B.2) Member initializations... */
   s4o.print(s4o.indent_spaces);
   vardecl = new generate_c_vardecl_c(&s4o,
-  				      generate_c_vardecl_c::constructorinit_vf,
-  				      generate_c_vardecl_c::input_vt |
-  				      generate_c_vardecl_c::output_vt |
-  				      generate_c_vardecl_c::inoutput_vt |
-  				      generate_c_vardecl_c::private_vt |
-  				      generate_c_vardecl_c::located_vt |
-				      generate_c_vardecl_c::external_vt);
+                                     generate_c_vardecl_c::constructorinit_vf,
+                                     generate_c_vardecl_c::input_vt    |
+                                     generate_c_vardecl_c::output_vt   |
+                                     generate_c_vardecl_c::inoutput_vt |
+                                     generate_c_vardecl_c::private_vt  |
+                                     generate_c_vardecl_c::located_vt  |
+                                     generate_c_vardecl_c::external_vt);
   vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
   delete vardecl;
   s4o.print("\n");
@@ -894,8 +876,8 @@
   /* function body */
   s4o.print(s4o.indent_spaces + "// Initialise TEMP variables\n");
   vardecl = new generate_c_vardecl_c(&s4o,
-  				      generate_c_vardecl_c::init_vf,
-				      generate_c_vardecl_c::temp_vt);
+                                     generate_c_vardecl_c::init_vf,
+                                     generate_c_vardecl_c::temp_vt);
   vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
   delete vardecl;
   s4o.print("\n");
@@ -987,8 +969,8 @@
   
   /* (A.2) Global variables */
   vardecl = new generate_c_vardecl_c(&s4o,
-  				      generate_c_vardecl_c::local_vf,
-  				      generate_c_vardecl_c::global_vt);
+                                     generate_c_vardecl_c::local_vf,
+                                     generate_c_vardecl_c::global_vt);
   vardecl->print(symbol);
   delete vardecl;
   s4o.print("\n");
@@ -1008,8 +990,8 @@
   /* (B.3) Global variables initializations... */
   s4o.print(s4o.indent_spaces);
   vardecl = new generate_c_vardecl_c(&s4o,
-  				      generate_c_vardecl_c::constructorinit_vf,
-  				      generate_c_vardecl_c::global_vt);
+                                     generate_c_vardecl_c::constructorinit_vf,
+                                     generate_c_vardecl_c::global_vt);
   vardecl->print(symbol);
   delete vardecl;
   s4o.print("\n");
@@ -1125,7 +1107,7 @@
   public:
     generate_c_resources_c(stage4out_c *s4o_ptr, symbol_c *config_scope, symbol_c *resource_scope, unsigned long time)
       : generate_c_typedecl_c(s4o_ptr) {
-      search_config_instance = new search_var_instance_decl_c(config_scope);
+      search_config_instance   = new search_var_instance_decl_c(config_scope);
       search_resource_instance = new search_var_instance_decl_c(resource_scope);
       common_ticktime = time;
       current_resource_name = NULL;
@@ -1181,7 +1163,7 @@
 /* task_configuration_list program_configuration_list */
 // SYM_REF2(single_resource_declaration_c, task_configuration_list, program_configuration_list)
     void *visit(single_resource_declaration_c *symbol) {
-    	bool single_resource = current_resource_name == NULL;
+      bool single_resource = current_resource_name == NULL;
       if (single_resource)
         current_resource_name = new identifier_c("RESOURCE");
       generate_c_vardecl_c *vardecl;
@@ -1204,9 +1186,9 @@
       /* (A.2) Global variables... */
       if (current_global_vars != NULL) {
         vardecl = new generate_c_vardecl_c(&s4o,
-                      generate_c_vardecl_c::local_vf,
-                      generate_c_vardecl_c::global_vt,
-                      current_resource_name);
+                                           generate_c_vardecl_c::local_vf,
+                                           generate_c_vardecl_c::global_vt,
+                                           current_resource_name);
         vardecl->print(current_global_vars);
         delete vardecl;
         s4o.print("\n");
@@ -1238,8 +1220,8 @@
       if (current_global_vars != NULL) {
         s4o.print(s4o.indent_spaces);
         vardecl = new generate_c_vardecl_c(&s4o,
-                      generate_c_vardecl_c::constructorinit_vf,
-                      generate_c_vardecl_c::global_vt);
+                                           generate_c_vardecl_c::constructorinit_vf,
+                                           generate_c_vardecl_c::global_vt);
         vardecl->print(current_global_vars);
         delete vardecl;
       }
@@ -1475,10 +1457,10 @@
         
         s4o.print(s4o.indent_spaces + "{extern ");
         var_decl->accept(*this);
-        s4o.print(" ");
+        s4o.print(" *");
         symbol->prog_data_source->accept(*this);
         s4o.print("; ");
-        s4o.print(current_program_name);
+        s4o.printupper(current_program_name);
         s4o.print(".");
         symbol->symbolic_variable->accept(*this);
         s4o.print(" = ");
@@ -1508,20 +1490,19 @@
         else
           vartype = search_resource_instance->get_vartype();
         
-        s4o.print(s4o.indent_spaces);
         s4o.print(s4o.indent_spaces + "{extern ");
         var_decl->accept(*this);
-        s4o.print(" ");
+        s4o.print(" *");
         symbol->data_sink->accept(*this);
         s4o.print("; ");
         if (vartype || search_var_instance_decl_c::global_vt)
           s4o.print("*");
         symbol->data_sink->accept(*this);
         s4o.print(" = ");
-        s4o.print(current_program_name);
+        s4o.printupper(current_program_name);
         s4o.print(".");
         symbol->symbolic_variable->accept(*this);
-        s4o.print("};\n");
+        s4o.print(";};\n");
       }
       return NULL;
     }
@@ -1668,18 +1649,18 @@
     }
 
     void *visit(resource_declaration_c *symbol) {
-    	symbol->resource_name->accept(*this);
-    	stage4out_c resources_s4o(current_builddir, current_name, "c");
+      symbol->resource_name->accept(*this);
+      stage4out_c resources_s4o(current_builddir, current_name, "c");
       generate_c_resources_c generate_c_resources(&resources_s4o, current_configuration, symbol, common_ticktime);
-    	symbol->accept(generate_c_resources);
-    	return NULL;
+      symbol->accept(generate_c_resources);
+      return NULL;
     }
 
     void *visit(single_resource_declaration_c *symbol) {
-    	stage4out_c resources_s4o(current_builddir, "RESOURCE", "c");
+      stage4out_c resources_s4o(current_builddir, "RESOURCE", "c");
       generate_c_resources_c generate_c_resources(&resources_s4o, current_configuration, symbol, common_ticktime);
-    	symbol->accept(generate_c_resources);
-    	return NULL;
+      symbol->accept(generate_c_resources);
+      return NULL;
     }
     
 };
--- a/stage4/generate_c/generate_c_base.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/stage4/generate_c/generate_c_base.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -255,7 +255,6 @@
     void *visit(octal_integer_c *symbol) {s4o.print("0"); return print_striped_token(symbol, 2);}
     void *visit(hex_integer_c *symbol) {s4o.print("0x"); return print_striped_token(symbol, 3);}
 
-    void *visit(numeric_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
     void *visit(integer_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
     void *visit(real_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
     void *visit(bit_string_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
--- a/stage4/generate_c/generate_c_il.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/stage4/generate_c/generate_c_il.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -54,34 +54,6 @@
  * the possible il_operand variable instance was declared).
  */
 
-class search_il_operand_type_c {
-
-  private:
-    search_varfb_instance_type_c search_varfb_instance_type;
-    search_constant_type_c search_constant_type;
-
-  public:
-    search_il_operand_type_c(symbol_c *search_scope): search_varfb_instance_type(search_scope) {}
-
-  public:
-    symbol_c *get_type(symbol_c *il_operand) {
-      symbol_c *res;
-
-      /* We first assume that it is a constant... */
-      res = search_constant_type.get_type(il_operand);
-      if (res != NULL) return res;
-
-      /* Nope, now we assume it is a variable, and determine its type... */
-      res = search_varfb_instance_type.get_type(il_operand);
-      if (NULL != res) return res;
-
-      /* not found */
-      return NULL;
-    }
-};
-
-
-
 /***********************************************************************/
 /***********************************************************************/
 /***********************************************************************/
@@ -176,7 +148,6 @@
      * This object instance will then later be called while the
      * remaining il code is being handled.
      */
-    //search_il_operand_type_c *search_il_operand_type;
     search_expression_type_c *search_expression_type;
 
     /* The initial value that should be given to the IL default variable
@@ -244,38 +215,6 @@
     il_default_variable_c default_variable_name;
     il_default_variable_c default_variable_back_name;
 
-    /* Some function calls in the body of functions or function blocks
-     * may leave some parameters to their default values, and
-     * ignore some output parameters of the function being called.
-     * Our conversion of ST functions to C++ does not contemplate that,
-     * i.e. each called function must get all it's input and output
-     * parameters set correctly.
-     * For input parameters we merely need to call the function with
-     * the apropriate default value, but for output parameters
-     * we must create temporary variables to hold the output value.
-     *
-     * We declare all the temporary output variables at the begining of
-     * the body of each function or function block, and use them as
-     * in function calls later on as they become necessary...
-     * Note that we cannot create these variables just before a function
-     * call, as the function call itself may be integrated within an
-     * expression, or another function call!
-     *
-     * The variables are declared in the exact same order in which they
-     * will be used later on during the function calls, which allows us
-     * to simply re-create the name that was used for the temporary variable
-     * instead of keeping it in some list.
-     * The names are recreated by the temp_var_name_factory, after reset()
-     * has been called!
-     *
-     * This function will genertae code similar to...
-     *
-     *     INT __TMP_0 = 23;
-     *     REAL __TMP_1 = 45.5;
-     *     ...
-     */
-    temp_var_name_c temp_var_name_factory;
-
     /* When calling a function block, we must first find it's type,
      * by searching through the declarations of the variables currently
      * in scope.
@@ -303,7 +242,6 @@
       default_variable_name(IL_DEFVAR, NULL),
       default_variable_back_name(IL_DEFVAR_BACK, NULL)
     {
-      //search_il_operand_type  = new search_il_operand_type_c(scope);
       search_expression_type = new search_expression_type_c(scope);
       search_fb_instance_decl = new search_fb_instance_decl_c(scope);
       search_varfb_instance_type = new search_varfb_instance_type_c(scope);
@@ -316,14 +254,11 @@
 
     virtual ~generate_c_il_c(void) {
       delete search_fb_instance_decl;
-      //delete search_il_operand_type;
       delete search_expression_type;
       delete search_varfb_instance_type;
     }
 
     void generate(instruction_list_c *il) {
-      generate_c_tempvardecl_c generate_c_tempvardecl(&s4o);
-      generate_c_tempvardecl.generate(il, &temp_var_name_factory);
       il->accept(*this);
     }
 
@@ -384,13 +319,14 @@
       if (NULL == sv) ERROR;
       identifier_c *id = dynamic_cast<identifier_c *>(sv->var_name);
       if (NULL == id) ERROR;
-
+      
       identifier_c param(param_name);
 
       //SYM_REF3(il_param_assignment_c, il_assign_operator, il_operand, simple_instr_list)
-      il_param_assignment_c il_param_assignment(&param, &this->default_variable_name, NULL);
+      il_assign_operator_c il_assign_operator(&param);
+      il_param_assignment_c il_param_assignment(&il_assign_operator, &this->default_variable_name, NULL);
       // SYM_LIST(il_param_list_c)
-      il_param_list_c il_param_list;
+      il_param_list_c il_param_list;   
       il_param_list.add_element(&il_param_assignment);
       CAL_operator_c CAL_operator;
       // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list)
@@ -461,6 +397,9 @@
 
 private:
 
+#if 0
+I NEED TO FIX THIS!!!
+TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
 void *visit(eno_param_c *symbol) {
   if (this->is_variable_prefix_null()) {
     s4o.print("*");
@@ -471,6 +410,9 @@
   s4o.print("ENO");
   return NULL;
 }
+TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
+#endif
+
 
 /*********************/
 /* B 1.4 - Variables */
@@ -632,7 +574,15 @@
     if (symbol->il_operand_list != NULL)
       nb_param += ((list_c *)symbol->il_operand_list)->n;
 
+    #define search(x) search_f(x)
+    #define next() next_nf()
+//     #define search_constant_type_c::constant_int_type_name  search_expression_type_c::integer
+    #define constant_int_type_name  integer
     #include "il_code_gen.c"
+    #undef constant_int_type_name
+//     #undef search_constant_type_c::constant_int_type_name
+    #undef next
+    #undef  search
 
   }
   else {
@@ -673,11 +623,11 @@
        * the following line...
        */
       if (param_value == NULL)
-        param_value = function_call_param_iterator.search(param_name);
+        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();
+        param_value = function_call_param_iterator.next_nf();
       
       if (param_value == NULL && param_direction == function_param_iterator_c::direction_in) {
         /* No value given for parameter, so we must use the default... */
@@ -844,11 +794,11 @@
     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(param_name);
+    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();
+      param_value = function_call_param_iterator.next_nf();
 
     symbol_c *param_type = fp_iterator.param_type();
     if (param_type == NULL) ERROR;
@@ -889,18 +839,18 @@
     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(param_name);
+    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();
+      param_value = function_call_param_iterator.next_nf();
 
     /* now output the value assignment */
     if (param_value != NULL)
       if ((param_direction == function_param_iterator_c::direction_out) ||
           (param_direction == function_param_iterator_c::direction_inout)) {
         symbol_c *param_type = search_varfb_instance_type->get_type(param_value, false);
-        
+
         s4o.print(";\n"+ s4o.indent_spaces);
         param_value->accept(*this);
         s4o.print(" = ");
@@ -955,7 +905,7 @@
     
     identifier_c en_param_name("EN");
     /* Get the value from EN param */
-    symbol_c *EN_param_value = function_call_param_iterator.search(&en_param_name);
+    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
@@ -964,12 +914,20 @@
     
     identifier_c eno_param_name("EN0");
     /* Get the value from ENO param */
-    symbol_c *ENO_param_value = function_call_param_iterator.search(&eno_param_name);
+    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_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
     
+    #define search(x) search_f(x)
+    #define next() next_nf()
+//     #define search_constant_type_c::constant_int_type_name  search_expression_type_c::integer
+    #define constant_int_type_name  integer
     #include "st_code_gen.c"
+    #undef constant_int_type_name
+//     #undef search_constant_type_c::constant_int_type_name
+    #undef next
+    #undef  search
     
   }
   else {
@@ -998,7 +956,7 @@
   
       /* Get the value from a foo(<param_name> = <param_value>) style call */
       if (param_value == NULL)
-        param_value = function_call_param_iterator.search(param_name);
+        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
@@ -1009,7 +967,7 @@
        * the following line...
        */
       if (param_value == NULL)
-        param_value = function_call_param_iterator.next();
+        param_value = function_call_param_iterator.next_nf();
       
       if (param_value == NULL) {
         /* No value given for parameter, so we must use the default... */
--- a/stage4/generate_c/generate_c_st.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/stage4/generate_c/generate_c_st.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -92,58 +92,13 @@
     }
 
 
-  private:
-    /* Some function calls in the body of functions or function blocks
-     * may leave some parameters to their default values, and
-     * ignore some output parameters of the function being called.
-     * Our conversion of ST functions to C++ does not contemplate that,
-     * i.e. each called function must get all it's input and output
-     * parameters set correctly.
-     * For input parameters we merely need to call the function with
-     * the apropriate default value, but for output parameters
-     * we must create temporary variables to hold the output value.
-     *
-     * We declare all the temporary output variables at the begining of
-     * the body of each function or function block, and use them as
-     * in function calls later on as they become necessary...
-     * Note that we cannot create these variables just before a function
-     * call, as the function call itself may be integrated within an
-     * expression, or another function call!
-     *
-     * The variables are declared in the exact same order in which they
-     * will be used later on during the function calls, which allows us
-     * to simply re-create the name that was used for the temporary variable
-     * instead of keeping it in some list.
-     * The names are recreated by the temp_var_name_factory, after reset()
-     * has been called!
-     *
-     * This function will genertae code similar to...
-     *
-     *     INT __TMP_0 = 23;
-     *     REAL __TMP_1 = 45.5;
-     *     ...
-     */
-    temp_var_name_c temp_var_name_factory;
-
   public:
     void generate(statement_list_c *stl) {
-      generate_c_tempvardecl_c generate_c_tempvardecl(&s4o);
-      generate_c_tempvardecl.generate(stl, &temp_var_name_factory);
       stl->accept(*this);
     }
 
   private:
 
-void *visit(eno_param_c *symbol) {
-  if (this->is_variable_prefix_null()) {
-    s4o.print("*");
-  }
-  else {
-    this->print_variable_prefix();
-  }
-  s4o.print("ENO");
-  return NULL;
-}
 
 /*********************/
 /* B 1.4 - Variables */
@@ -446,45 +401,57 @@
 }
 
 void *visit(function_invocation_c *symbol) {
-  function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
-  
   symbol_c* function_type_prefix = NULL;
   symbol_c* function_name = NULL;
   symbol_c* function_type_suffix = NULL;
   std::list<FUNCTION_PARAM> param_list;
   FUNCTION_PARAM *param;
-  
+
+  symbol_c *parameter_assignment_list = NULL;
+  if (NULL != symbol->   formal_param_list) parameter_assignment_list = symbol->   formal_param_list;
+  if (NULL != symbol->nonformal_param_list) parameter_assignment_list = symbol->nonformal_param_list;
+  if (NULL == parameter_assignment_list) ERROR;
+
+  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);
-    
+
     function_call_param_iterator_c function_call_param_iterator(symbol);
 
-    int nb_param = ((list_c *)symbol->parameter_assignment_list)->n;
-    
+    int nb_param = ((list_c *)parameter_assignment_list)->n;
+
     identifier_c en_param_name("EN");
     /* Get the value from EN param */
-    symbol_c *EN_param_value = function_call_param_iterator.search(&en_param_name);
+    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_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in)
-    
+
     identifier_c eno_param_name("ENO");
     /* Get the value from ENO param */
-    symbol_c *ENO_param_value = function_call_param_iterator.search(&eno_param_name);
+    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_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
-    
+
+    #define search(x) search_f(x)
+    #define next() next_nf()
+//     #define search_constant_type_c::constant_int_type_name  search_expression_type_c::integer
+    #define constant_int_type_name  integer
     #include "st_code_gen.c"
-    
+    #undef constant_int_type_name
+//     #undef search_constant_type_c::constant_int_type_name
+    #undef next
+    #undef  search
+
   }
   else {
     /* loop through each function parameter, find the value we should pass
@@ -501,11 +468,11 @@
       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(param_name);
+      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();
+        param_value = function_call_param_iterator.next_nf();
       
       if (param_value == NULL && param_direction == function_param_iterator_c::direction_in) {
         /* No value given for parameter, so we must use the default... */
@@ -636,11 +603,11 @@
     /*fprintf(stderr, "param : %s\n", param_name->value);*/
     
     /* Get the value from a foo(<param_name> = <param_value>) style call */
-    symbol_c *param_value = function_call_param_iterator.search(param_name);
+    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();
+      param_value = function_call_param_iterator.next_nf();
 
     symbol_c *param_type = fp_iterator.param_type();
     if (param_type == NULL) ERROR;
@@ -683,11 +650,11 @@
     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(param_name);
+    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();
+      param_value = function_call_param_iterator.next_nf();
 
     /* now output the value assignment */
     if (param_value != NULL)
--- a/stage4/generate_c/generate_c_tempvardecl.cc	Wed Sep 02 13:39:05 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-/*
- * (c) 2003 Mario de Sousa
- *
- * Offered to the public under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * This code is made available on the understanding that it will not be
- * used in safety-critical situations without a full and competent review.
- */
-
-/*
- * An IEC 61131-3 IL and ST compiler.
- *
- * Based on the
- * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
- *
- */
-
-
-/*
- * Declare temporary variables to be later used as output parameters
- * in function calls for which not all output parameters were
- * defined in the original (st or il) source code.
- *
- * This is part of the 4th stage that generates
- * a c++ source program equivalent to the IL and ST
- * code.
- */
-
-
-
-
-class temp_var_name_c {
-  private:
-    int counter;
-
-  public:
-    void reset(void) {counter = 0;}
-    temp_var_name_c(void) {reset();}
-
-  public:
-    std::string *new_name(void) {
-      std::string *new_str = new std::string(TEMP_VAR);
-      /* yikes!!! How to convert an int to a string elegantly???
-       * Right now I (Mario) can only think of snprintf()
-       * C++ must have a more elegant method!
-       */
-      int int_str_size = snprintf(NULL, 0, "%d", counter);
-      if (int_str_size <= 0) ERROR;
-      char *int_str = (char *)malloc(int_str_size+1);
-      if (snprintf(int_str, int_str_size+1, "%d", counter++) >= int_str_size+1) ERROR;
-      *new_str += int_str;
-      free(int_str);
-      return new_str;
-    }
-
-};
-
-
-
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-
-
-
-/* Some function calls in the body of functions or function blocks
- * may leave some parameters to their default values, and
- * ignore some output parameters of the function being called.
- * Our conversion of ST functions to C++ does not contemplate that,
- * i.e. each called function must get all it's input and output
- * parameters set correctly.
- * For input parameters we merely need to call the function with
- * the apropriate default value, but for output parameters
- * we must create temporary variables to hold the output value.
- *
- * We declare all the temporary output variables at the begining of
- * the body of each function or function block, and use them as
- * in function calls later on as they become necessary...
- * Note that we cannot create these variables just before a function
- * call, as the function call itself may be integrated within an
- * expression, or another function call!
- *
- * The variables are declared in the exact same order in which they
- * will be used later on during the function calls, which allows us
- * to simply re-create the name that was used for the temporary variable
- * instead of keeping it in some list.
- * The names are recreated by the temp_var_name_factory, after reset()
- * has been called!
- *
- * This function will genertae code similar to...
- *
- *     INT __TMP_0 = 23;
- *     REAL __TMP_1 = 45.5;
- *     ...
- */
-
-class generate_c_tempvardecl_c: generate_c_typedecl_c {
-  public:
-    generate_c_tempvardecl_c(stage4out_c *s4o_ptr): generate_c_typedecl_c(s4o_ptr) {}
-
-    void generate(symbol_c *body, temp_var_name_c *temp_var_name_factory) {
-      temp_var_name_factory->reset();
-      function_call_iterator_c fcall_iterator(body);
-      for(symbol_c *finvocation = NULL; (finvocation = fcall_iterator.next()) != NULL;) {
-        /* get the name of the next function that gets called */
-        identifier_c *fcalled_name = fcall_iterator.fname();
-        /* get that function's declaration... */
-        function_declaration_c *fdecl = function_symtable.find_value(fcalled_name);
-        if (fdecl == function_symtable.end_value()) {
-          function_type_t function_type = get_function_type(fcalled_name);
-          if (function_type == function_none) ERROR;
-          return;
-        }
-        /* create iterator to iterate through each of the called function's parameters... */
-        function_param_iterator_c fp_iterator(fdecl);
-
-        /* iterate through each of the called function's parameters... */
-        identifier_c *param_name = NULL;
-        function_call_param_iterator_c function_call_param_iterator(finvocation);
-        for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
-
-          function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
-          if (param_direction == function_param_iterator_c::direction_in)
-            /* ignore input only parameters...
-             * we do not need to create temporary variables for these!
-             */
-            continue;
-
-          /* Get the value from a foo(<param_name> = <param_value>) style call */
-          symbol_c *param_value = function_call_param_iterator.search(param_name);
-
-          /* Get the value from a foo(<param_value>) style call */
-          if (param_value == NULL)
-            param_value = function_call_param_iterator.next();
-
-          if (param_value != NULL)
-            /* ignore output parameters to which a variable is passed...
-             * we do not need to create temporary variables for these!
-             */
-            continue;
-
-          symbol_c *param_type = fp_iterator.param_type();
-
-          /* get the parameter's default value */
-          param_value = fp_iterator.default_value();
-
-          /* If no default value specified in function declaration,
-           * get the default value of this variable's type
-           */
-          if (param_value == NULL)
-            param_value = (symbol_c *)param_type->accept(*type_initial_value_c::instance());
-          if (param_value == NULL) ERROR;
-
-          /* now declare a temporary variable, with the correct default value... */
-          s4o.print(s4o.indent_spaces);
-          param_type->accept(*this);
-          s4o.print(" ");
-
-          std::string *temp_var_name = temp_var_name_factory->new_name();
-          s4o.print(*temp_var_name);
-          delete temp_var_name;
-
-          s4o.print(" = ");
-          param_value->accept(*this);
-          s4o.print(";\n");
-        }
-      }
-      temp_var_name_factory->reset();
-      s4o.print("\n");
-    }
-};
--- a/stage4/generate_c/generate_c_vardecl.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/stage4/generate_c/generate_c_vardecl.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -741,9 +741,8 @@
     static const unsigned int program_vt  = 0x0100;  // PROGRAM (inside a configuration!)
 						     //    Programs declared inside a resource will not be declared
 						     //    unless program_vt is acompanied by resource_vt
-
-    static const unsigned int eneno_vt  = 0x0200;  // EN/ENO declaration
-    
+    static const unsigned int en_vt       = 0x0200;  // EN  declaration
+    static const unsigned int eno_vt      = 0x0400;  // ENO declaration
     static const unsigned int resource_vt = 0x8000;  // RESOURCE (inside a configuration!)
                                                      //    This, just of itself, will not print out any declarations!!
 						     //    It must be acompanied by either program_vt and/or global_vt
@@ -802,11 +801,11 @@
     typedef enum {finterface_vf,
                   foutputassign_vf,
                   local_vf,
-		              localinit_vf,
-		              init_vf,
-		              constructorinit_vf,
-		              globalinit_vf
-		             } varformat_t;
+                  localinit_vf,
+                  init_vf,
+                  constructorinit_vf,
+                  globalinit_vf
+                 } varformat_t;
 
 
   private:
@@ -832,10 +831,6 @@
      * specific global variable declaration (with #define...)*/
     symbol_c *resource_name;
 
-    /* Store if En and ENO parameters have been defined by user */
-    bool en_declared;
-    bool eno_declared;
-
     /* Holds the references to the type and initial value
      * of the variables currently being declared.
      * Please read the comment under var1_init_decl_c for further
@@ -878,8 +873,9 @@
     symbol_c *globalnamespace;
 
     /* Actually produce the output where variables are declared... */
-    /* Note that located variables are the exception, they
-     * being declared in the located_var_decl_c visitor...
+    /* Note that located variables and EN/ENO are the exception, they
+     * being declared in the located_var_decl_c,
+     * en_param_declaration_c and eno_param_declaration_c visitors...
      */
     void *declare_variables(symbol_c *symbol, bool is_fb = false) {
       list_c *list = dynamic_cast<list_c *>(symbol);
@@ -986,20 +982,10 @@
       globalnamespace         = NULL;
       nv = NULL;
       resource_name = res_name;
-      en_declared = false;
-      eno_declared = false;
     }
 
     ~generate_c_vardecl_c(void) {}
 
-    bool is_en_declared(void) {
-      return en_declared;
-    }
-    
-    bool is_eno_declared(void) {
-      return eno_declared;
-    }
-
     void print(symbol_c *symbol, symbol_c *scope = NULL, const char *variable_prefix = NULL) {
       this->set_variable_prefix(variable_prefix);
       if (globalinit_vf == wanted_varformat)
@@ -1022,24 +1008,6 @@
       globalnamespace = NULL;
     }
 
-    void print_eneno(void) {
-      if (!en_declared) {
-        if (wanted_varformat == finterface_vf) {
-          if (finterface_var_count > 0)
-            s4o.print(",\n" + s4o.indent_spaces);
-          s4o.print("BOOL EN");
-        }
-        else
-          s4o.print(s4o.indent_spaces + "BOOL EN;\n");
-      }
-      if (!eno_declared) {
-        if (wanted_varformat == finterface_vf)
-          s4o.print(",\n" + s4o.indent_spaces + "BOOL *ENO");
-        else
-          s4o.print(s4o.indent_spaces + "BOOL ENO;\n");
-      }
-    }
-
   protected:
 /***************************/
 /* B 0 - Programming Model */
@@ -1157,24 +1125,108 @@
 
 void *visit(en_param_declaration_c *symbol) {
   TRACE("en_declaration_c");
-  if (en_declared) ERROR;
   if (wanted_varformat == finterface_vf) {
     finterface_var_count++;
   }  
-  if ((current_vartype & eneno_vt) != 0) {
+  if ((wanted_vartype & en_vt) != 0) {
     if (wanted_varformat == finterface_vf) {
       s4o.print(nv->get());
-      s4o.print("\n" + s4o.indent_spaces + "BOOL EN");
-    }
+      s4o.print("\n" + s4o.indent_spaces);
+      symbol->type->accept(*this);
+      s4o.print(" ");
+      symbol->name->accept(*this);
+    }
+
+    if ((wanted_varformat == local_vf) ||
+        (wanted_varformat == init_vf) ||
+        (wanted_varformat == localinit_vf)) {
+      s4o.print(s4o.indent_spaces);
+      if (wanted_varformat != init_vf) {
+        symbol->type->accept(*this);
+        s4o.print(" ");
+      }
+      print_variable_prefix();
+      symbol->name->accept(*this);
+      if (wanted_varformat != local_vf) {
+        s4o.print(" = ");
+        symbol->value->accept(*this);
+        s4o.print(";");
+      }
+      s4o.print(";\n");
+    }
+
     if (wanted_varformat == constructorinit_vf) {
+      /* NOTE: I (Mario) think this is dead code - never gets executed. Must confirm it before deleting it... */
       s4o.print(nv->get());
       this->print_variable_prefix();
-      s4o.print("ENO = __BOOL_LITERAL(TRUE);");
+      // s4o.print("EN = __BOOL_LITERAL(TRUE);");
+      symbol->name->accept(*this);
+      s4o.print(" = ");
+      symbol->value->accept(*this);
+      s4o.print(";");
     }
   }
-  en_declared = true;
-  return NULL;
-}
+  return NULL;
+}
+
+
+void *visit(eno_param_declaration_c *symbol) {
+  TRACE("eno_declaration_c");
+  if (wanted_varformat == finterface_vf) {
+    finterface_var_count++;
+  }
+  if ((wanted_vartype & eno_vt) != 0) {
+    if (wanted_varformat == finterface_vf) {
+      s4o.print(nv->get());
+      // s4o.print("\n" + s4o.indent_spaces + "BOOL *ENO");
+      s4o.print("\n" + s4o.indent_spaces);
+      symbol->type->accept(*this);
+      s4o.print(" *__");
+      symbol->name->accept(*this);
+    }
+
+    if ((wanted_varformat == local_vf) ||
+        (wanted_varformat == init_vf) ||
+        (wanted_varformat == localinit_vf)) {
+      s4o.print(s4o.indent_spaces);
+      if (wanted_varformat != init_vf) {
+        symbol->type->accept(*this);
+        s4o.print(" ");
+      }
+      print_variable_prefix();
+      symbol->name->accept(*this);
+      if (wanted_varformat != local_vf) {
+        s4o.print(" = __BOOL_LITERAL(TRUE);");
+      }
+      s4o.print(";\n");
+    }
+
+    if (wanted_varformat == foutputassign_vf) {
+      s4o.print(s4o.indent_spaces + "if (__");
+      symbol->name->accept(*this);
+      s4o.print(" != NULL) {\n");
+      s4o.indent_right();
+      s4o.print(s4o.indent_spaces + "*__");
+      symbol->name->accept(*this);
+      s4o.print(" = ");
+      symbol->name->accept(*this);
+      s4o.print(";\n");
+      s4o.indent_left();
+      s4o.print(s4o.indent_spaces + "}\n");
+    }
+
+    if (wanted_varformat == constructorinit_vf) {
+      /* NOTE: I (Mario) think this is dead code - never gets executed. Must confirm it before deleting it... */
+      s4o.print(nv->get());
+      this->print_variable_prefix();
+      // s4o.print("ENO = __BOOL_LITERAL(TRUE);");
+      symbol->name->accept(*this);
+      s4o.print(" = __BOOL_LITERAL(TRUE);");
+    }
+  }
+  return NULL;
+}
+
 
 void *visit(raising_edge_option_c *symbol) {
   // TO DO ...
@@ -1298,26 +1350,6 @@
   return NULL;
 }
 
-void *visit(eno_param_declaration_c *symbol) {
-  TRACE("eno_declaration_c");
-  if (eno_declared) ERROR;
-  if (wanted_varformat == finterface_vf) {
-    finterface_var_count++;
-  }
-  if ((current_vartype & eneno_vt) != 0) {
-    if (wanted_varformat == finterface_vf) {
-      s4o.print(nv->get());
-      s4o.print("\n" + s4o.indent_spaces + "BOOL *EN0");
-    }
-    if (wanted_varformat == constructorinit_vf) {
-      s4o.print(nv->get());
-      this->print_variable_prefix();
-      s4o.print("ENO = __BOOL_LITERAL(TRUE);");
-    }
-  }
-  eno_declared = true;
-  return NULL;
-}
 
 /*  VAR_IN_OUT var_declaration_list END_VAR */
 void *visit(input_output_declarations_c *symbol) {
@@ -2213,7 +2245,9 @@
    * to it, and then output the c equivalent...
    */
   function_param_iterator_c fp_iterator(p_decl);
+#if 0
   function_call_param_iterator_c function_call_param_iterator(symbol);
+#endif
   identifier_c *param_name;
   nv->push("", ", ");
   for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
@@ -2251,17 +2285,6 @@
         param_value->accept(*this);
 #endif
 	break;
-#if 0
-        if (param_value == NULL) {
-	  /* no parameter value given, so we pass a previously declared temporary variable. */
-          std::string *temp_var_name = temp_var_name_factory.new_name();
-          s4o.print(*temp_var_name);
-          delete temp_var_name;
-	} else {
-          param_value->accept(*this);
-	}
-#endif
-	break;
     } /* switch */
   } /* for(...) */
 
--- a/stage4/generate_iec/generate_iec.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/stage4/generate_iec/generate_iec.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -43,6 +43,7 @@
 #include <string>
 #include <iostream>
 #include <sstream>
+#include <typeinfo>
 #include "generate_iec.hh"
 
 #include "../stage4.hh"
@@ -122,6 +123,7 @@
   public:
 
 /*  EN/ENO */
+#if 0
 void *visit(en_param_c *symbol) {
   s4o.print("EN");
   return NULL;
@@ -131,6 +133,17 @@
   s4o.print("ENO");
   return NULL;
 }
+void *visit(en_param_c *symbol) {
+  return symbol->param_name->accept(*this);
+}
+
+void *visit(eno_param_c *symbol) {
+  return symbol->param_name->accept(*this);
+}
+#endif
+
+
+
 
 /***************************/
 /* 2.1.6 Pragmas */
@@ -161,7 +174,6 @@
 void *visit(octal_integer_c *symbol) {return print_token(symbol);}
 void *visit(hex_integer_c *symbol) {return print_token(symbol);}
 
-void *visit(numeric_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
 void *visit(integer_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
 void *visit(real_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
 void *visit(bit_string_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
@@ -314,9 +326,10 @@
 void *visit(dword_type_name_c *symbol) {s4o.print("DWORD"); return NULL;}
 void *visit(string_type_name_c *symbol) {s4o.print("STRING"); return NULL;}
 void *visit(wstring_type_name_c *symbol) {s4o.print("WSTRING"); return NULL;}
+/*
 void *visit(constant_int_type_name_c *symbol) {return NULL;}
 void *visit(constant_real_type_name_c *symbol) {return NULL;}
-
+*/
 
 /********************************/
 /* B 1.3.3 - Derived data types */
@@ -589,14 +602,16 @@
 /* VAR_INPUT [RETAIN | NON_RETAIN] input_declaration_list END_VAR */
 /* option -> the RETAIN/NON_RETAIN/<NULL> directive... */
 void *visit(input_declarations_c *symbol) {
-  s4o.print(s4o.indent_spaces); s4o.print("VAR_INPUT ");
-  if (symbol->option != NULL)
-    symbol->option->accept(*this);
-  s4o.print("\n");
-  s4o.indent_right();
-  symbol->input_declaration_list->accept(*this);
-  s4o.indent_left();
-  s4o.print(s4o.indent_spaces); s4o.print("END_VAR\n");
+  if (typeid(*(symbol->method)) == typeid(explicit_definition_c)) {
+    s4o.print(s4o.indent_spaces); s4o.print("VAR_INPUT ");
+    if (symbol->option != NULL)
+      symbol->option->accept(*this);
+    s4o.print("\n");
+    s4o.indent_right();
+    symbol->input_declaration_list->accept(*this);
+    s4o.indent_left();
+    s4o.print(s4o.indent_spaces); s4o.print("END_VAR\n");
+  }
   return NULL;
 }
 
@@ -614,8 +629,29 @@
   return NULL;
 }
 
+/* dummy classes only used as flags! */
+void *visit(explicit_definition_c *symbol) {return NULL;}
+void *visit(implicit_definition_c *symbol) {return NULL;}
+
+/* EN : BOOL := 1 */
 void *visit(en_param_declaration_c *symbol) {
-  s4o.print("EN : BOOL := 1");
+  if (typeid(*(symbol->method)) == typeid(explicit_definition_c)) {
+    symbol->name->accept(*this);
+    s4o.print(" : ");
+    symbol->type->accept(*this);
+    s4o.print(" := ");
+    symbol->value->accept(*this);
+  }
+  return NULL;
+}
+
+/* ENO : BOOL */
+void *visit(eno_param_declaration_c *symbol) {
+  if (typeid(*(symbol->method)) == typeid(explicit_definition_c)) {
+    symbol->name->accept(*this);
+    s4o.print(" : ");
+    symbol->type->accept(*this);
+  }
   return NULL;
 }
 
@@ -682,19 +718,16 @@
 /* VAR_OUTPUT [RETAIN | NON_RETAIN] var_init_decl_list END_VAR */
 /* option -> may be NULL ! */
 void *visit(output_declarations_c *symbol) {
-  s4o.print(s4o.indent_spaces); s4o.print("VAR_OUTPUT ");
-  if (symbol->option != NULL)
-    symbol->option->accept(*this);
-  s4o.print("\n");
-  s4o.indent_right();
-  symbol->var_init_decl_list->accept(*this);
-  s4o.indent_left();
-  s4o.print(s4o.indent_spaces); s4o.print("END_VAR\n");
-  return NULL;
-}
-
-void *visit(eno_param_declaration_c *symbol) {
-  s4o.print("EN0 : BOOL");
+  if (typeid(*(symbol->method)) == typeid(explicit_definition_c)) {
+    s4o.print(s4o.indent_spaces); s4o.print("VAR_OUTPUT ");
+    if (symbol->option != NULL)
+      symbol->option->accept(*this);
+    s4o.print("\n");
+    s4o.indent_right();
+    symbol->var_init_decl_list->accept(*this);
+    s4o.indent_left();
+    s4o.print(s4o.indent_spaces); s4o.print("END_VAR\n");
+  }
   return NULL;
 }
 
@@ -1689,7 +1722,13 @@
 void *visit(function_invocation_c *symbol) {
   symbol->function_name->accept(*this);
   s4o.print("(");
-  symbol->parameter_assignment_list->accept(*this);
+
+  /* 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) symbol->   formal_param_list->accept(*this);
+  if (symbol->nonformal_param_list != NULL) symbol->nonformal_param_list->accept(*this);
+
   s4o.print(")");
   return NULL;
 }
@@ -1726,8 +1765,13 @@
 void *visit(fb_invocation_c *symbol) {
   symbol->fb_name->accept(*this);
   s4o.print("(");
-  if (symbol->param_assignment_list != NULL)
-    symbol->param_assignment_list->accept(*this);
+  /* If the syntax parser is working correctly, at most one of the 
+   * following two symbols will be NULL, while the other is != NULL.
+   * The two may be NULL simultaneously!
+   */
+  if (symbol->   formal_param_list != NULL) symbol->   formal_param_list->accept(*this);
+  if (symbol->nonformal_param_list != NULL) symbol->nonformal_param_list->accept(*this);
+
   s4o.print(")");
   return NULL;
 }
--- a/stage4/stage4.cc	Wed Sep 02 13:39:05 2009 +0200
+++ b/stage4/stage4.cc	Wed Sep 02 14:05:27 2009 +0200
@@ -157,6 +157,8 @@
 #endif
   return NULL;
 }
+
+
 void *stage4out_c::printlocation(std::string str) {
   return printlocation(str.c_str());
 }