diff -r aad38592bdde -r c0bda77b37a0 absyntax_utils/function_param_iterator.cc --- a/absyntax_utils/function_param_iterator.cc Tue Aug 14 19:40:01 2012 +0200 +++ b/absyntax_utils/function_param_iterator.cc Wed Aug 22 16:46:17 2012 +0200 @@ -47,14 +47,14 @@ */ - -#include "absyntax_utils.hh" /* required for extract_integer() */ -// #include "function_param_iterator.hh" /* no longer required, aready included by absyntax_utils.hh */ -// #include "spec_init_separator.hh" /* no longer required, aready included by absyntax_utils.hh */ +#include "function_param_iterator.hh" /* no longer required, aready included by absyntax_utils.hh */ +#include "spec_init_separator.hh" /* no longer required, aready included by absyntax_utils.hh */ #include /* required for strtol() */ #include #include - +#include // required for std::numeric_limits< XXX >::max() +#include // required for errno +#include "../main.hh" // required for ERROR() and ERROR_MSG() macros. //#define DEBUG #ifdef DEBUG @@ -64,9 +64,59 @@ #endif -#define ERROR error_exit(__FILE__,__LINE__) -/* function defined in main.cc */ -extern void error_exit(const char *file_name, int line_no); + + + +/* NOTE: The following function is not really needed, as we could get the value that constant_folding_c determined for this + * integer. Remember that currently constant_folding_c runs before this class is ever used/called! + * However, I (Mario) do not currently feel it would be a good idea to restrict the use of this + * abstract syntax utility to only after the constant_folding_c has had a chance to fill in the constant value + * of this symbol. + * For this reason only, I have opted to let this abstract syntax utility have its own private copy of the + * extract_integer() function. + * Another aspect that makes this OK is that this function will only be used to extract the integer value of the + * index for the first extensible paramater (examples follow shortly). Since this is an extension to IEC 61131-3 + * that we created to allow us to handle extensible functions with very little hard coding, it is OK if we + * impose extra/different limits on how an integer may be legally be formated in this case. This will also + * only show up in code that describes the interface to the standard function of IEC 61131-3, which the user + * will not ever get to see. We write that IEC 61131-3 code ourselves! + * + * Example of source code we will be parsing and analysing: + * + * FUNCTION ADD : REAL VAR_INPUT IN 1 .. : REAL; END_VAR RETURN; END_FUNCTION + * ^^^ + * + * FUNCTION MUX : REAL VAR_INPUT K : USINT; IN 0 .. : REAL; END_VAR RETURN; END_FUNCTION + * ^^^ + * + * Basically, currently this will only be either a '0' or a '1' !! + */ + +/* NOTE: it must ignore underscores! */ +static int extract_first_index_value(symbol_c *sym) { + std::string str = ""; + integer_c *integer; + long int ret; + + if ((integer = dynamic_cast(sym)) == NULL) ERROR; + for(unsigned int i = 0; i < strlen(integer->value); i++) + if (integer->value[i] != '_') str += integer->value[i]; + + errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! + ret = strtol(str.c_str(), NULL, 10); + if (errno != 0) ERROR; + if (ret < 0) ERROR; // the following code assumes that the first index will never be negative! + if (ret > std::numeric_limits< int >::max()) ERROR; // output of this function is only an int!! + + return ret; +} + + + + + + + @@ -130,7 +180,7 @@ if (extensible_parameter != NULL) { sym = extensible_parameter->var_name; current_param_is_extensible = true; - _first_extensible_param_index = extract_integer(extensible_parameter->first_index); + _first_extensible_param_index = extract_first_index_value(extensible_parameter->first_index); } identifier_c *variable_name = dynamic_cast(sym); if (variable_name == NULL) ERROR; @@ -167,7 +217,7 @@ if (extensible_parameter != NULL) { var_name = extensible_parameter->var_name; current_param_is_extensible = true; - _first_extensible_param_index = extract_integer(extensible_parameter->first_index); + _first_extensible_param_index = extract_first_index_value(extensible_parameter->first_index); } identifier_c *variable_name = dynamic_cast(var_name); if (variable_name == NULL) ERROR; @@ -206,7 +256,9 @@ _first_extensible_param_index = -1; current_param_is_extensible = false; current_param_name = NULL; - current_param_type = current_param_default_value = NULL; + current_param_type = NULL; + current_param_default_value = NULL; + last_returned_parameter = NULL; /* the last parameter returned by search() or next() */ } @@ -223,7 +275,8 @@ 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; + if ((NULL == f_decl) && (NULL == fb_decl) && (NULL == p_decl)) + ERROR; /* OK. Now initialise this object... */ this->f_decl = pou_decl; @@ -248,6 +301,7 @@ return current_param_name; } + last_returned_parameter = NULL; param_count = 0; en_eno_param_implicit = false; next_param++; @@ -261,13 +315,14 @@ if (extensible_parameter != NULL) { sym = extensible_parameter->var_name; current_param_is_extensible = true; - _first_extensible_param_index = extract_integer(extensible_parameter->first_index); + _first_extensible_param_index = extract_first_index_value(extensible_parameter->first_index); current_extensible_param_index = _first_extensible_param_index; } identifier = dynamic_cast(sym); if (identifier == NULL) ERROR; current_param_name = identifier; + last_returned_parameter = current_param_name; return current_param_name; } @@ -281,35 +336,53 @@ current_operation = function_param_iterator_c::search_op; void *res = f_decl->accept(*this); identifier_c *res_param_name = dynamic_cast((symbol_c *)res); + last_returned_parameter = res_param_name; return res_param_name; } +identifier_c *function_param_iterator_c::search(const char *param_name) { + identifier_c param_name_id(param_name); + return search(¶m_name_id); +} + + + /* Returns the currently referenced parameter's default value, * or NULL if none is specified in the function declrataion itself. */ symbol_c *function_param_iterator_c::default_value(void) { + if (NULL == last_returned_parameter) + return NULL; return current_param_default_value; } /* Returns the currently referenced parameter's type name. */ symbol_c *function_param_iterator_c::param_type(void) { + if (NULL == last_returned_parameter) + return NULL; return current_param_type; } /* Returns if currently referenced parameter is an implicit defined EN/ENO parameter. */ bool function_param_iterator_c::is_en_eno_param_implicit(void) { + if (NULL == last_returned_parameter) + ERROR; return en_eno_param_implicit; } /* Returns if currently referenced parameter is an extensible parameter. */ /* extensible paramters only occur in some standard functions, e.g. AND(word#34, word#44, word#65); */ bool function_param_iterator_c::is_extensible_param(void) { + if (NULL == last_returned_parameter) + ERROR; return current_param_is_extensible; } /* Returns the index of the current extensible parameter. */ /* If the current parameter is not an extensible paramter, returns -1 */ int function_param_iterator_c::extensible_param_index(void) { + if (NULL == last_returned_parameter) + ERROR; return (current_param_is_extensible? current_extensible_param_index : -1); } @@ -323,6 +396,8 @@ * i.e. VAR_INPUT, VAR_OUTPUT or VAR_INOUT */ function_param_iterator_c::param_direction_t function_param_iterator_c::param_direction(void) { + if (NULL == last_returned_parameter) + ERROR; return current_param_direction; }