stage4/generate_c/generate_c.cc
changeset 1021 21a97cdb317d
parent 1007 afb3974f8fb3
parent 1016 91bef6704b44
child 1039 52f63e622604
child 1041 56ebe2a31b5b
--- a/stage4/generate_c/generate_c.cc	Fri May 06 11:48:02 2016 +0300
+++ b/stage4/generate_c/generate_c.cc	Tue Jun 28 16:35:47 2016 +0300
@@ -859,53 +859,83 @@
     
       /* (B.2) Temporary variable for function's return value */
       /* It will have the same name as the function itself! */
-      s4o.print(s4o.indent_spaces);
-      symbol->type_name->accept(print_base); /* return type */
-      s4o.print(" ");
-      symbol->derived_function_name->accept(print_base);
-      s4o.print(" = ");
-      {
-        /* get the default value of this variable's type */
-        symbol_c *default_value = type_initial_value_c::get(symbol->type_name);
-        if (default_value == NULL) ERROR;
-        initialization_analyzer_c initialization_analyzer(default_value);
-        switch (initialization_analyzer.get_initialization_type()) {
-          case initialization_analyzer_c::struct_it:
-            {
-              generate_c_structure_initialization_c *structure_initialization = new generate_c_structure_initialization_c(&s4o);
-              structure_initialization->init_structure_default(symbol->type_name);
-              structure_initialization->init_structure_values(default_value);
-              delete structure_initialization;
-            }
-            break;
-          case initialization_analyzer_c::array_it:
-            {
-              generate_c_array_initialization_c *array_initialization = new generate_c_array_initialization_c(&s4o);
-              array_initialization->init_array_size(symbol->type_name);
-              array_initialization->init_array_values(default_value);
-              delete array_initialization;
-            }
-            break;
-          default:
-            default_value->accept(print_base);
-            break;
+      /* NOTE: matiec supports a non-standard syntax, in which functions do not return a value
+       *       (declared as returning the special non-standard datatype VOID)
+       *       e.g.:   FUNCTION foo: VOID
+       *                ...
+       *               END_FUNCTION
+       *       
+       *       These functions cannot return any value, so they do not need a variable to
+       *       store the return value.
+       *       Note that any attemot to sto a value in the implicit variable
+       *       e.g.:   FUNCTION foo: VOID
+       *                ...
+       *                 foo := 42;
+       *               END_FUNCTION
+       *       will always return a datatype incompatilibiyt error in stage 3 of matiec, 
+       *       so it is safe for stage 4 to assume that this return variable will never be needed
+       *       if the function's return type is VOID.
+       */
+      if (!get_datatype_info_c::is_VOID(symbol->type_name->datatype)) { // only print return variable if return datatype is not VOID
+        s4o.print(s4o.indent_spaces);
+        symbol->type_name->accept(print_base); /* return type */
+        s4o.print(" ");
+        symbol->derived_function_name->accept(print_base);
+        s4o.print(" = ");
+        {
+          /* get the default value of this variable's type */
+          symbol_c *default_value = type_initial_value_c::get(symbol->type_name);
+          if (default_value == NULL) ERROR;
+          initialization_analyzer_c initialization_analyzer(default_value);
+          switch (initialization_analyzer.get_initialization_type()) {
+            case initialization_analyzer_c::struct_it:
+              {
+                generate_c_structure_initialization_c *structure_initialization = new generate_c_structure_initialization_c(&s4o);
+                structure_initialization->init_structure_default(symbol->type_name);
+                structure_initialization->init_structure_values(default_value);
+                delete structure_initialization;
+              }
+              break;
+            case initialization_analyzer_c::array_it:
+              {
+                generate_c_array_initialization_c *array_initialization = new generate_c_array_initialization_c(&s4o);
+                array_initialization->init_array_size(symbol->type_name);
+                array_initialization->init_array_values(default_value);
+                delete array_initialization;
+              }
+              break;
+            default:
+              default_value->accept(print_base);
+              break;
+          }
         }
       }
       s4o.print(";\n\n");
       
-      s4o.print(s4o.indent_spaces + "// Control execution\n");
-      s4o.print(s4o.indent_spaces + "if (!EN) {\n");
-      s4o.indent_right();
-      s4o.print(s4o.indent_spaces + "if (__ENO != NULL) {\n");
-      s4o.indent_right();
-      s4o.print(s4o.indent_spaces + "*__ENO = __BOOL_LITERAL(FALSE);\n");
-      s4o.indent_left();
-      s4o.print(s4o.indent_spaces + "}\n");
-      s4o.print(s4o.indent_spaces + "return ");
-      symbol->derived_function_name->accept(print_base);
-      s4o.print(";\n");
-      s4o.indent_left();
-      s4o.print(s4o.indent_spaces + "}\n");
+      
+      // Only generate the code that controls the execution of the function's body if the
+      // function contains a declaration of both the EN and ENO variables
+      search_var_instance_decl_c search_var(symbol);
+      identifier_c  en_var("EN");
+      identifier_c eno_var("ENO");
+      if (   (search_var.get_vartype(& en_var) == search_var_instance_decl_c::input_vt)
+          && (search_var.get_vartype(&eno_var) == search_var_instance_decl_c::output_vt)) {
+        s4o.print(s4o.indent_spaces + "// Control execution\n");
+        s4o.print(s4o.indent_spaces + "if (!EN) {\n");
+        s4o.indent_right();
+        s4o.print(s4o.indent_spaces + "if (__ENO != NULL) {\n");
+        s4o.indent_right();
+        s4o.print(s4o.indent_spaces + "*__ENO = __BOOL_LITERAL(FALSE);\n");
+        s4o.indent_left();
+        s4o.print(s4o.indent_spaces + "}\n");
+        if (!get_datatype_info_c::is_VOID(symbol->type_name->datatype)) { // only print return variable if return datatype is not VOID
+          s4o.print(s4o.indent_spaces + "return ");
+          symbol->derived_function_name->accept(print_base);
+          s4o.print(";\n");
+        }
+        s4o.indent_left();
+        s4o.print(s4o.indent_spaces + "}\n");
+      }
     
       /* (C) Function body */
       generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->derived_function_name, symbol);
@@ -921,9 +951,12 @@
       vardecl->print(symbol->var_declarations_list);
       delete vardecl;
       
-      s4o.print(s4o.indent_spaces + "return ");
-      symbol->derived_function_name->accept(print_base);
-      s4o.print(";\n");
+      if (!get_datatype_info_c::is_VOID(symbol->type_name->datatype)) { // only print 'return <fname>' if return datatype is not VOID
+        s4o.print(s4o.indent_spaces + "return ");
+        symbol->derived_function_name->accept(print_base);
+        s4o.print(";\n");
+      }
+
       s4o.indent_left();
       s4o.print(s4o.indent_spaces + "}\n\n\n");
     
@@ -1071,31 +1104,40 @@
       } else {
         s4o.print(" {\n");
         s4o.indent_right();
-      
-        s4o.print(s4o.indent_spaces + "// Control execution\n");
-        s4o.print(s4o.indent_spaces + "if (!");
-        s4o.print(GET_VAR);
-        s4o.print("(");
-        s4o.print(FB_FUNCTION_PARAM);
-        s4o.print("->EN)) {\n");
-        s4o.indent_right();
-        s4o.print(s4o.indent_spaces);
-        s4o.print(SET_VAR);
-        s4o.print("(");
-        s4o.print(FB_FUNCTION_PARAM);
-        s4o.print("->,ENO,,__BOOL_LITERAL(FALSE));\n");
-        s4o.print(s4o.indent_spaces + "return;\n");
-        s4o.indent_left();
-        s4o.print(s4o.indent_spaces + "}\n");
-        s4o.print(s4o.indent_spaces + "else {\n");
-        s4o.indent_right();
-        s4o.print(s4o.indent_spaces);
-        s4o.print(SET_VAR);
-        s4o.print("(");
-        s4o.print(FB_FUNCTION_PARAM);
-        s4o.print("->,ENO,,__BOOL_LITERAL(TRUE));\n");
-        s4o.indent_left();
-        s4o.print(s4o.indent_spaces + "}\n");
+
+        // Only generate the code that controls the execution of the function's body if the
+        // function contains a declaration of both the EN and ENO variables
+        search_var_instance_decl_c search_var(symbol);
+        identifier_c  en_var("EN");
+        identifier_c eno_var("ENO");
+        if (   (search_var.get_vartype(& en_var) == search_var_instance_decl_c::input_vt)
+            && (search_var.get_vartype(&eno_var) == search_var_instance_decl_c::output_vt)) {
+
+          s4o.print(s4o.indent_spaces + "// Control execution\n");
+          s4o.print(s4o.indent_spaces + "if (!");
+          s4o.print(GET_VAR);
+          s4o.print("(");
+          s4o.print(FB_FUNCTION_PARAM);
+          s4o.print("->EN)) {\n");
+          s4o.indent_right();
+          s4o.print(s4o.indent_spaces);
+          s4o.print(SET_VAR);
+          s4o.print("(");
+          s4o.print(FB_FUNCTION_PARAM);
+          s4o.print("->,ENO,,__BOOL_LITERAL(FALSE));\n");
+          s4o.print(s4o.indent_spaces + "return;\n");
+          s4o.indent_left();
+          s4o.print(s4o.indent_spaces + "}\n");
+          s4o.print(s4o.indent_spaces + "else {\n");
+          s4o.indent_right();
+          s4o.print(s4o.indent_spaces);
+          s4o.print(SET_VAR);
+          s4o.print("(");
+          s4o.print(FB_FUNCTION_PARAM);
+          s4o.print("->,ENO,,__BOOL_LITERAL(TRUE));\n");
+          s4o.indent_left();
+          s4o.print(s4o.indent_spaces + "}\n");
+        }
       
         /* (C.4) Initialize TEMP variables */
         /* function body */
@@ -1380,6 +1422,15 @@
   s4o.print("/*     FILE GENERATED BY iec2c             */\n");
   s4o.print("/* Editing this file is not recommended... */\n");
   s4o.print("/*******************************************/\n\n");
+  
+  if (runtime_options.disable_implicit_en_eno) {
+    // If we are not generating the EN and ENO parameters for functions and FB,
+    //   then make sure we use the standard library version compiled without these parameters too!
+    s4o.print("#ifndef DISABLE_EN_ENO_PARAMETERS\n");
+    s4o.print("#define DISABLE_EN_ENO_PARAMETERS\n");
+    s4o.print("#endif\n");
+  }
+  
   s4o.print("#include \"iec_std_lib.h\"\n\n");
   s4o.print("#include \"accessor.h\"\n\n"); 
   s4o.print("#include \"POUS.h\"\n\n");
@@ -1685,6 +1736,15 @@
       s4o.print("/*     FILE GENERATED BY iec2c             */\n");
       s4o.print("/* Editing this file is not recommended... */\n");
       s4o.print("/*******************************************/\n\n");
+  
+      if (runtime_options.disable_implicit_en_eno) {
+        // If we are not generating the EN and ENO parameters for functions and FB,
+        //   then make sure we use the standard library version compiled without these parameters too!
+        s4o.print("#ifndef DISABLE_EN_ENO_PARAMETERS\n");
+        s4o.print("#define DISABLE_EN_ENO_PARAMETERS\n");
+        s4o.print("#endif\n");
+      }
+      
       s4o.print("#include \"iec_std_lib.h\"\n\n");
       
       /* (A) resource declaration... */
@@ -2118,7 +2178,17 @@
 /* B 0 - Programming Model */
 /***************************/
     void *visit(library_c *symbol) {
-      pous_incl_s4o.print("#ifndef __POUS_H\n#define __POUS_H\n\n#include \"accessor.h\"\n#include \"iec_std_lib.h\"\n\n");
+      pous_incl_s4o.print("#ifndef __POUS_H\n#define __POUS_H\n\n");
+      
+      if (runtime_options.disable_implicit_en_eno) {
+        // If we are not generating the EN and ENO parameters for functions and FB,
+        //   then make sure we use the standard library version compiled without these parameters too!
+        pous_incl_s4o.print("#ifndef DISABLE_EN_ENO_PARAMETERS\n");
+        pous_incl_s4o.print("#define DISABLE_EN_ENO_PARAMETERS\n");
+        pous_incl_s4o.print("#endif\n");
+      }
+      
+      pous_incl_s4o.print("#include \"accessor.h\"\n#include \"iec_std_lib.h\"\n\n");
 
       for(int i = 0; i < symbol->n; i++) {
         symbol->elements[i]->accept(*this);