absyntax_utils/function_param_iterator.cc
changeset 625 c0bda77b37a0
parent 596 4efb11e44065
child 662 b1b11dd09a54
equal deleted inserted replaced
412:aad38592bdde 625:c0bda77b37a0
    45  * function in/out/inout parameter, returning the name
    45  * function in/out/inout parameter, returning the name
    46  * of each parameter...function_param_iterator_c
    46  * of each parameter...function_param_iterator_c
    47  */
    47  */
    48 
    48 
    49 
    49 
    50 
    50 #include "function_param_iterator.hh"  /* no longer required, aready included by absyntax_utils.hh */
    51 #include "absyntax_utils.hh"  /* required for extract_integer() */
    51 #include "spec_init_separator.hh"  /* no longer required, aready included by absyntax_utils.hh */
    52 // #include "function_param_iterator.hh"  /* no longer required, aready included by absyntax_utils.hh */
       
    53 // #include "spec_init_separator.hh"  /* no longer required, aready included by absyntax_utils.hh */
       
    54 #include <stdlib.h>  /* required for strtol() */
    52 #include <stdlib.h>  /* required for strtol() */
    55 #include <string.h>
    53 #include <string.h>
    56 #include <strings.h>
    54 #include <strings.h>
    57 
    55 #include <limits> // required for std::numeric_limits< XXX >::max()
       
    56 #include <errno.h> // required for errno
       
    57 #include "../main.hh" // required for ERROR() and ERROR_MSG() macros.
    58 
    58 
    59 //#define DEBUG
    59 //#define DEBUG
    60 #ifdef DEBUG
    60 #ifdef DEBUG
    61 #define TRACE(classname) printf("\n____%s____\n",classname);
    61 #define TRACE(classname) printf("\n____%s____\n",classname);
    62 #else
    62 #else
    63 #define TRACE(classname)
    63 #define TRACE(classname)
    64 #endif
    64 #endif
    65 
    65 
    66 
    66 
    67 #define ERROR error_exit(__FILE__,__LINE__)
    67 
    68 /* function defined in main.cc */
    68 
    69 extern void error_exit(const char *file_name, int line_no);
    69 
       
    70 /* NOTE: The following function is not really needed, as we could get the value that constant_folding_c determined for this
       
    71  *       integer. Remember that currently constant_folding_c runs before this class is ever used/called!
       
    72  *       However, I (Mario) do not currently feel it would be a good idea to restrict the use of this
       
    73  *       abstract syntax utility to only after the constant_folding_c has had a chance to fill in the constant value
       
    74  *       of this symbol. 
       
    75  *       For this reason only, I have opted to let this abstract syntax utility have its own private copy of the
       
    76  *       extract_integer() function.
       
    77  *       Another aspect that makes this OK is that this function will only be used to extract the integer value of the
       
    78  *       index for the first extensible paramater (examples follow shortly). Since this is an extension to IEC 61131-3 
       
    79  *       that we created to allow us to handle extensible functions with very little hard coding, it is OK if we
       
    80  *       impose extra/different limits on how an integer may be legally be formated in this case. This will also 
       
    81  *       only show up in code that describes the interface to the standard function of IEC 61131-3, which the user
       
    82  *       will not ever get to see. We write that IEC 61131-3 code ourselves!
       
    83  *
       
    84  *      Example of source code we will be parsing and analysing:
       
    85  *
       
    86  *      FUNCTION ADD : REAL VAR_INPUT IN 1 .. : REAL; END_VAR RETURN; END_FUNCTION
       
    87  *                                      ^^^
       
    88  *
       
    89  *      FUNCTION MUX : REAL VAR_INPUT K : USINT; IN 0 .. : REAL; END_VAR RETURN; END_FUNCTION
       
    90  *                                                 ^^^
       
    91  *
       
    92  *      Basically, currently this will only be either a '0' or a '1' !!
       
    93  */
       
    94 
       
    95 /* NOTE: it must ignore underscores! */
       
    96 static int extract_first_index_value(symbol_c *sym) {
       
    97   std::string str = "";
       
    98   integer_c *integer;
       
    99   long int ret;
       
   100 
       
   101   if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
       
   102   for(unsigned int i = 0; i < strlen(integer->value); i++)
       
   103     if (integer->value[i] != '_')  str += integer->value[i];
       
   104 
       
   105   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
       
   106   ret = strtol(str.c_str(), NULL, 10);
       
   107   if (errno != 0) ERROR;
       
   108   if (ret < 0) ERROR; // the following code assumes that the first index will never be negative!
       
   109   if (ret > std::numeric_limits< int >::max()) ERROR; // output of this function is only an int!!
       
   110 
       
   111   return ret;
       
   112 }
       
   113 
       
   114 
       
   115 
       
   116 
       
   117 
       
   118 
       
   119 
    70 
   120 
    71 
   121 
    72 
   122 
    73 /* compare the name of two __extensible__ function parameters.
   123 /* compare the name of two __extensible__ function parameters.
    74  * The usual use case is to have one of the parameters as used
   124  * The usual use case is to have one of the parameters as used
   128         symbol_c *sym = list->elements[i];
   178         symbol_c *sym = list->elements[i];
   129         extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(sym);
   179         extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(sym);
   130         if (extensible_parameter != NULL) {
   180         if (extensible_parameter != NULL) {
   131           sym = extensible_parameter->var_name;
   181           sym = extensible_parameter->var_name;
   132           current_param_is_extensible = true;
   182           current_param_is_extensible = true;
   133           _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
   183           _first_extensible_param_index = extract_first_index_value(extensible_parameter->first_index);
   134         }
   184         }
   135         identifier_c *variable_name = dynamic_cast<identifier_c *>(sym);
   185         identifier_c *variable_name = dynamic_cast<identifier_c *>(sym);
   136         if (variable_name == NULL) ERROR;
   186         if (variable_name == NULL) ERROR;
   137         
   187         
   138         if (!current_param_is_extensible)
   188         if (!current_param_is_extensible)
   165     case search_op:
   215     case search_op:
   166       extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(var_name);
   216       extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(var_name);
   167       if (extensible_parameter != NULL) {
   217       if (extensible_parameter != NULL) {
   168         var_name = extensible_parameter->var_name;
   218         var_name = extensible_parameter->var_name;
   169         current_param_is_extensible = true;
   219         current_param_is_extensible = true;
   170         _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
   220         _first_extensible_param_index = extract_first_index_value(extensible_parameter->first_index);
   171       }
   221       }
   172       identifier_c *variable_name = dynamic_cast<identifier_c *>(var_name);
   222       identifier_c *variable_name = dynamic_cast<identifier_c *>(var_name);
   173       if (variable_name == NULL) ERROR;
   223       if (variable_name == NULL) ERROR;
   174       
   224       
   175       if (!current_param_is_extensible)
   225       if (!current_param_is_extensible)
   204 void function_param_iterator_c::reset(void) {
   254 void function_param_iterator_c::reset(void) {
   205   next_param = param_count = 0;
   255   next_param = param_count = 0;
   206   _first_extensible_param_index = -1;
   256   _first_extensible_param_index = -1;
   207   current_param_is_extensible = false;
   257   current_param_is_extensible = false;
   208   current_param_name = NULL;
   258   current_param_name = NULL;
   209   current_param_type = current_param_default_value = NULL;
   259   current_param_type = NULL;
       
   260   current_param_default_value = NULL;
       
   261   last_returned_parameter = NULL; /* the last parameter returned by search() or next() */
   210 }
   262 }
   211 
   263 
   212 
   264 
   213 /* initialise the iterator object.
   265 /* initialise the iterator object.
   214  * We must be given a reference to one of the following
   266  * We must be given a reference to one of the following
   221   /* do some consistency checks... */
   273   /* do some consistency checks... */
   222   function_declaration_c       * f_decl = dynamic_cast<function_declaration_c       *>(pou_decl);
   274   function_declaration_c       * f_decl = dynamic_cast<function_declaration_c       *>(pou_decl);
   223   function_block_declaration_c *fb_decl = dynamic_cast<function_block_declaration_c *>(pou_decl);
   275   function_block_declaration_c *fb_decl = dynamic_cast<function_block_declaration_c *>(pou_decl);
   224   program_declaration_c        * p_decl = dynamic_cast<program_declaration_c        *>(pou_decl);
   276   program_declaration_c        * p_decl = dynamic_cast<program_declaration_c        *>(pou_decl);
   225 
   277 
   226   if ((NULL == f_decl) && (NULL == fb_decl) && (NULL == p_decl)) ERROR;
   278   if ((NULL == f_decl) && (NULL == fb_decl) && (NULL == p_decl)) 
       
   279     ERROR;
   227 
   280 
   228   /* OK. Now initialise this object... */
   281   /* OK. Now initialise this object... */
   229   this->f_decl = pou_decl;
   282   this->f_decl = pou_decl;
   230   reset();
   283   reset();
   231 }
   284 }
   246   if (current_param_is_extensible) {
   299   if (current_param_is_extensible) {
   247     current_extensible_param_index++;
   300     current_extensible_param_index++;
   248     return current_param_name;
   301     return current_param_name;
   249   }
   302   }
   250   
   303   
       
   304   last_returned_parameter = NULL; 
   251   param_count = 0;
   305   param_count = 0;
   252   en_eno_param_implicit = false;
   306   en_eno_param_implicit = false;
   253   next_param++;
   307   next_param++;
   254   current_operation = function_param_iterator_c::iterate_op;
   308   current_operation = function_param_iterator_c::iterate_op;
   255   res = f_decl->accept(*this);
   309   res = f_decl->accept(*this);
   259   symbol_c *sym = (symbol_c *)res;
   313   symbol_c *sym = (symbol_c *)res;
   260   extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(sym);
   314   extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(sym);
   261   if (extensible_parameter != NULL) {
   315   if (extensible_parameter != NULL) {
   262     sym = extensible_parameter->var_name;
   316     sym = extensible_parameter->var_name;
   263     current_param_is_extensible = true;
   317     current_param_is_extensible = true;
   264     _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
   318     _first_extensible_param_index = extract_first_index_value(extensible_parameter->first_index);
   265     current_extensible_param_index = _first_extensible_param_index;
   319     current_extensible_param_index = _first_extensible_param_index;
   266   }
   320   }
   267   identifier = dynamic_cast<identifier_c *>(sym);
   321   identifier = dynamic_cast<identifier_c *>(sym);
   268   if (identifier == NULL)
   322   if (identifier == NULL)
   269     ERROR;
   323     ERROR;
   270   current_param_name = identifier;
   324   current_param_name = identifier;
       
   325   last_returned_parameter = current_param_name; 
   271   return current_param_name;
   326   return current_param_name;
   272 }
   327 }
   273 
   328 
   274 /* Search for the value passed to the parameter named <param_name>...  */
   329 /* Search for the value passed to the parameter named <param_name>...  */
   275 identifier_c *function_param_iterator_c::search(symbol_c *param_name) {
   330 identifier_c *function_param_iterator_c::search(symbol_c *param_name) {
   279   en_eno_param_implicit = false;
   334   en_eno_param_implicit = false;
   280   current_param_is_extensible = false;
   335   current_param_is_extensible = false;
   281   current_operation = function_param_iterator_c::search_op;
   336   current_operation = function_param_iterator_c::search_op;
   282   void *res = f_decl->accept(*this);
   337   void *res = f_decl->accept(*this);
   283   identifier_c *res_param_name = dynamic_cast<identifier_c *>((symbol_c *)res);
   338   identifier_c *res_param_name = dynamic_cast<identifier_c *>((symbol_c *)res);
       
   339   last_returned_parameter = res_param_name; 
   284   return res_param_name;
   340   return res_param_name;
   285 }
   341 }
       
   342 
       
   343 identifier_c *function_param_iterator_c::search(const char *param_name) {
       
   344   identifier_c   param_name_id(param_name);
       
   345   return search(&param_name_id);
       
   346 }
       
   347 
       
   348 
   286 
   349 
   287 /* Returns the currently referenced parameter's default value,
   350 /* Returns the currently referenced parameter's default value,
   288  * or NULL if none is specified in the function declrataion itself.
   351  * or NULL if none is specified in the function declrataion itself.
   289  */
   352  */
   290 symbol_c *function_param_iterator_c::default_value(void) {
   353 symbol_c *function_param_iterator_c::default_value(void) {
       
   354   if (NULL == last_returned_parameter) 
       
   355     return NULL;
   291   return current_param_default_value;
   356   return current_param_default_value;
   292 }
   357 }
   293 
   358 
   294 /* Returns the currently referenced parameter's type name. */
   359 /* Returns the currently referenced parameter's type name. */
   295 symbol_c *function_param_iterator_c::param_type(void) {
   360 symbol_c *function_param_iterator_c::param_type(void) {
       
   361   if (NULL == last_returned_parameter) 
       
   362     return NULL;
   296   return current_param_type;
   363   return current_param_type;
   297 }
   364 }
   298 
   365 
   299 /* Returns if currently referenced parameter is an implicit defined EN/ENO parameter. */
   366 /* Returns if currently referenced parameter is an implicit defined EN/ENO parameter. */
   300 bool function_param_iterator_c::is_en_eno_param_implicit(void) {
   367 bool function_param_iterator_c::is_en_eno_param_implicit(void) {
       
   368   if (NULL == last_returned_parameter) 
       
   369     ERROR;
   301   return en_eno_param_implicit;
   370   return en_eno_param_implicit;
   302 }
   371 }
   303 
   372 
   304 /* Returns if currently referenced parameter is an extensible parameter. */
   373 /* Returns if currently referenced parameter is an extensible parameter. */
   305 /* extensible paramters only occur in some standard functions, e.g. AND(word#34, word#44, word#65); */
   374 /* extensible paramters only occur in some standard functions, e.g. AND(word#34, word#44, word#65); */
   306 bool function_param_iterator_c::is_extensible_param(void) {
   375 bool function_param_iterator_c::is_extensible_param(void) {
       
   376   if (NULL == last_returned_parameter) 
       
   377     ERROR;
   307   return current_param_is_extensible;
   378   return current_param_is_extensible;
   308 }
   379 }
   309 
   380 
   310 /* Returns the index of the current extensible parameter. */             
   381 /* Returns the index of the current extensible parameter. */             
   311 /* If the current parameter is not an extensible paramter, returns -1 */
   382 /* If the current parameter is not an extensible paramter, returns -1 */
   312 int function_param_iterator_c::extensible_param_index(void) {
   383 int function_param_iterator_c::extensible_param_index(void) {
       
   384   if (NULL == last_returned_parameter) 
       
   385     ERROR;
   313   return (current_param_is_extensible? current_extensible_param_index : -1);
   386   return (current_param_is_extensible? current_extensible_param_index : -1);
   314 }
   387 }
   315 
   388 
   316 /* Returns the index of the first extensible parameter, or -1 if no extensible parameter found. */             
   389 /* Returns the index of the first extensible parameter, or -1 if no extensible parameter found. */             
   317 /* WARNING: Will only return the correct value _after_ an extensible parameter has been found! */
   390 /* WARNING: Will only return the correct value _after_ an extensible parameter has been found! */
   321 
   394 
   322 /* Returns the currently referenced parameter's data passing direction.
   395 /* Returns the currently referenced parameter's data passing direction.
   323  * i.e. VAR_INPUT, VAR_OUTPUT or VAR_INOUT
   396  * i.e. VAR_INPUT, VAR_OUTPUT or VAR_INOUT
   324  */
   397  */
   325 function_param_iterator_c::param_direction_t function_param_iterator_c::param_direction(void) {
   398 function_param_iterator_c::param_direction_t function_param_iterator_c::param_direction(void) {
       
   399   if (NULL == last_returned_parameter) 
       
   400     ERROR;
   326   return current_param_direction;
   401   return current_param_direction;
   327 }
   402 }
   328 
   403 
   329 void *function_param_iterator_c::visit(implicit_definition_c *symbol) {
   404 void *function_param_iterator_c::visit(implicit_definition_c *symbol) {
   330 	en_eno_param_implicit = true;
   405 	en_eno_param_implicit = true;