# HG changeset patch # User Catarina Boucinha # Date 1251385606 -3600 # Node ID da1a8186f86f8942b5158ce18b9d5da6663bf214 # Parent e657008f43d03d6d36547b3160c7b055240e7047 Initial (very rough) version of semantic checker (stage3) diff -r e657008f43d0 -r da1a8186f86f Makefile --- a/Makefile Thu Jul 02 11:26:25 2009 +0100 +++ b/Makefile Thu Aug 27 16:06:46 2009 +0100 @@ -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 @@ - diff -r e657008f43d0 -r da1a8186f86f absyntax/absyntax.def --- a/absyntax/absyntax.def Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax/absyntax.def Thu Aug 27 16:06:46 2009 +0100 @@ -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/ 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 */ diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/Makefile --- a/absyntax_utils/Makefile Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/Makefile Thu Aug 27 16:06:46 2009 +0100 @@ -19,6 +19,8 @@ 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 diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/absyntax_utils.hh --- a/absyntax_utils/absyntax_utils.hh Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/absyntax_utils.hh Thu Aug 27 16:06:46 2009 +0100 @@ -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" diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/add_en_eno_param_decl.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/absyntax_utils/add_en_eno_param_decl.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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 + + +// #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); +} + + + + diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/add_en_eno_param_decl.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/absyntax_utils/add_en_eno_param_decl.hh Thu Aug 27 16:06:46 2009 +0100 @@ -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 + + + + + + + diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/decompose_var_instance_name.cc --- a/absyntax_utils/decompose_var_instance_name.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/decompose_var_instance_name.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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 */ /*********************/ diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/decompose_var_instance_name.hh --- a/absyntax_utils/decompose_var_instance_name.hh Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/decompose_var_instance_name.hh Thu Aug 27 16:06:46 2009 +0100 @@ -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 */ /********************************************/ diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/function_call_iterator.cc --- a/absyntax_utils/function_call_iterator.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/function_call_iterator.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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. */ diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/function_call_iterator.hh --- a/absyntax_utils/function_call_iterator.hh Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/function_call_iterator.hh Thu Aug 27 16:06:46 2009 +0100 @@ -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: diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/function_call_param_iterator.cc --- a/absyntax_utils/function_call_param_iterator.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/function_call_param_iterator.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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(, , ...) 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( = , = , ...) 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 ( = ), + * and not a simple expression (). + */ + 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(variable_name); - - if (variable_name2 == NULL) { - en_param_c *en_param = dynamic_cast(variable_name); - if (en_param != NULL) - variable_name2 = new identifier_c("EN"); - } - - if (variable_name2 == NULL) { - eno_param_c *eno_param = dynamic_cast(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 ... */ -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(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 */ diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/function_call_param_iterator.hh --- a/absyntax_utils/function_call_param_iterator.hh Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/function_call_param_iterator.hh Thu Aug 27 16:06:46 2009 +0100 @@ -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(, , ...) 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( = , = , ...) 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 ... */ - 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); diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/function_param_iterator.cc --- a/absyntax_utils/function_param_iterator.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/function_param_iterator.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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(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(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(pou_decl); + function_block_declaration_c *fb_decl = dynamic_cast(pou_decl); + program_declaration_c * p_decl = dynamic_cast(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(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(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 ... */ +identifier_c *function_param_iterator_c::search(symbol_c *param_name) { + if (NULL == param_name) ERROR; + search_param_name = dynamic_cast(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((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"); diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/function_param_iterator.hh --- a/absyntax_utils/function_param_iterator.hh Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/function_param_iterator.hh Thu Aug 27 16:06:46 2009 +0100 @@ -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 ... */ + /* 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. diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/get_sizeof_datatype.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/absyntax_utils/get_sizeof_datatype.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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 +#include +#include // get definition of ULLONG_MAX +/* tell stdint.h we want the definition of UINT64_MAX */ +#define __STDC_LIMIT_MACROS +#include // 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... diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/get_sizeof_datatype.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/absyntax_utils/get_sizeof_datatype.hh Thu Aug 27 16:06:46 2009 +0100 @@ -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 + + + + diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/search_base_type.cc --- a/absyntax_utils/search_base_type.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/search_base_type.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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; +} + diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/search_base_type.hh --- a/absyntax_utils/search_base_type.hh Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/search_base_type.hh Thu Aug 27 16:06:46 2009 +0100 @@ -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 diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/search_constant_type.cc --- a/absyntax_utils/search_constant_type.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/search_constant_type.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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"); diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/search_constant_type.hh --- a/absyntax_utils/search_constant_type.hh Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/search_constant_type.hh Thu Aug 27 16:06:46 2009 +0100 @@ -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 */ /*******************************/ diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/search_expression_type.cc --- a/absyntax_utils/search_expression_type.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/search_expression_type.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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; } diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/search_expression_type.hh --- a/absyntax_utils/search_expression_type.hh Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/search_expression_type.hh Thu Aug 27 16:06:46 2009 +0100 @@ -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;*/ + diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/search_il_operand_type.cc --- a/absyntax_utils/search_il_operand_type.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/search_il_operand_type.cc Thu Aug 27 16:06:46 2009 +0100 @@ -40,7 +40,7 @@ * 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; diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/search_il_operand_type.hh --- a/absyntax_utils/search_il_operand_type.hh Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/search_il_operand_type.hh Thu Aug 27 16:06:46 2009 +0100 @@ -40,7 +40,7 @@ class search_il_operand_type_c { private: - search_varfb_instance_type_c search_varfb_instance_type; + search_varfb_instance_type_c::search_varfb_instance_type_c search_varfb_instance_type; search_constant_type_c search_constant_type; public: diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/search_var_instance_decl.cc --- a/absyntax_utils/search_var_instance_decl.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/search_var_instance_decl.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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 */ diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/search_var_instance_decl.hh --- a/absyntax_utils/search_var_instance_decl.hh Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/search_var_instance_decl.hh Thu Aug 27 16:06:46 2009 +0100 @@ -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 */ diff -r e657008f43d0 -r da1a8186f86f absyntax_utils/search_varfb_instance_type.cc --- a/absyntax_utils/search_varfb_instance_type.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/absyntax_utils/search_varfb_instance_type.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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) { diff -r e657008f43d0 -r da1a8186f86f main.cc --- a/main.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/main.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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) diff -r e657008f43d0 -r da1a8186f86f stage1_2/iec.y --- a/stage1_2/iec.y Thu Jul 02 11:26:25 2009 +0100 +++ b/stage1_2/iec.y Thu Aug 27 16:06:46 2009 +0100 @@ -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 pragma_token %type 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 en_param -%type eno_param +%type en_identifier +%type eno_identifier + @@ -669,6 +681,7 @@ %type input_declaration_list %type input_declaration %type edge_declaration +/* en_param_declaration is not in the standard, but should be! */ %type en_param_declaration %type var_init_decl %type var1_init_decl @@ -685,6 +698,7 @@ %type output_declarations %type var_output_init_decl %type var_output_init_decl_list +/* eno_param_declaration is not in the standard, but should be! */ %type eno_param_declaration %type 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) diff -r e657008f43d0 -r da1a8186f86f stage4/generate_c/generate_c.cc --- a/stage4/generate_c/generate_c.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/stage4/generate_c/generate_c.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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; } }; diff -r e657008f43d0 -r da1a8186f86f stage4/generate_c/generate_c_base.cc --- a/stage4/generate_c/generate_c_base.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/stage4/generate_c/generate_c_base.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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);} diff -r e657008f43d0 -r da1a8186f86f stage4/generate_c/generate_c_il.cc --- a/stage4/generate_c/generate_c_il.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/stage4/generate_c/generate_c_il.cc Thu Aug 27 16:06:46 2009 +0100 @@ -54,10 +54,6 @@ * the possible il_operand variable instance was declared). */ -#include "../../absyntax_utils/search_il_operand_type.hh" - - - /***********************************************************************/ /***********************************************************************/ /***********************************************************************/ @@ -152,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 @@ -220,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. @@ -279,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); @@ -292,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); } @@ -360,13 +319,14 @@ if (NULL == sv) ERROR; identifier_c *id = dynamic_cast(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(¶m, &this->default_variable_name, NULL); + il_assign_operator_c il_assign_operator(¶m); + 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) @@ -437,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("*"); @@ -447,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 */ @@ -608,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 { @@ -649,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() 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... */ @@ -820,11 +794,11 @@ function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction(); /* Get the value from a foo( = ) 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() 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; @@ -865,18 +839,18 @@ function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction(); /* Get the value from a foo( = ) 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() 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(" = "); @@ -931,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 @@ -940,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 { @@ -974,7 +956,7 @@ /* Get the value from a foo( = ) 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() style call */ /* NOTE: the following line of code is not required in this case, but it doesn't @@ -985,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... */ diff -r e657008f43d0 -r da1a8186f86f stage4/generate_c/generate_c_st.cc --- a/stage4/generate_c/generate_c_st.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/stage4/generate_c/generate_c_st.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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 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( = ) 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() 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( = ) 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() 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( = ) 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() 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) diff -r e657008f43d0 -r da1a8186f86f stage4/generate_c/generate_c_tempvardecl.cc --- a/stage4/generate_c/generate_c_tempvardecl.cc Thu Jul 02 11:26:25 2009 +0100 +++ /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( = ) style call */ - symbol_c *param_value = function_call_param_iterator.search(param_name); - - /* Get the value from a foo() 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"); - } -}; diff -r e657008f43d0 -r da1a8186f86f stage4/generate_c/generate_c_vardecl.cc --- a/stage4/generate_c/generate_c_vardecl.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/stage4/generate_c/generate_c_vardecl.cc Thu Aug 27 16:06:46 2009 +0100 @@ -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(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(...) */ diff -r e657008f43d0 -r da1a8186f86f stage4/generate_iec/generate_iec.cc --- a/stage4/generate_iec/generate_iec.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/stage4/generate_iec/generate_iec.cc Thu Aug 27 16:06:46 2009 +0100 @@ -43,6 +43,7 @@ #include #include #include +#include #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/ 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; } diff -r e657008f43d0 -r da1a8186f86f stage4/stage4.cc --- a/stage4/stage4.cc Thu Jul 02 11:26:25 2009 +0100 +++ b/stage4/stage4.cc Thu Aug 27 16:06:46 2009 +0100 @@ -157,6 +157,8 @@ #endif return NULL; } + + void *stage4out_c::printlocation(std::string str) { return printlocation(str.c_str()); }