--- 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 <stdlib.h> /* required for strtol() */
#include <string.h>
#include <strings.h>
-
+#include <limits> // required for std::numeric_limits< XXX >::max()
+#include <errno.h> // 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<integer_c *>(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<identifier_c *>(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<identifier_c *>(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<function_block_declaration_c *>(pou_decl);
program_declaration_c * p_decl = dynamic_cast<program_declaration_c *>(pou_decl);
- if ((NULL == f_decl) && (NULL == fb_decl) && (NULL == p_decl)) ERROR;
+ 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<identifier_c *>(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<identifier_c *>((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;
}