diff -r 59435d4c5e0c -r 21a97cdb317d stage4/generate_c/generate_c.cc --- 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 ' 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);