absyntax_utils/function_param_iterator.cc
changeset 625 c0bda77b37a0
parent 596 4efb11e44065
child 662 b1b11dd09a54
--- 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(&param_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;
 }