absyntax_utils/function_param_iterator.cc
changeset 350 2c3c4dc34979
parent 279 c0453b7f99df
child 424 43d73e28eca8
equal deleted inserted replaced
341:ba80c3ceb6fb 350:2c3c4dc34979
    46  * of each parameter...function_param_iterator_c
    46  * of each parameter...function_param_iterator_c
    47  */
    47  */
    48 
    48 
    49 
    49 
    50 
    50 
    51 #include "function_param_iterator.hh"
    51 #include "absyntax_utils.hh"  /* required for extract_integer() */
    52 #include "spec_init_separator.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() */
       
    55 #include <string.h>
    53 #include <strings.h>
    56 #include <strings.h>
    54 
    57 
    55 
    58 
    56 //#define DEBUG
    59 //#define DEBUG
    57 #ifdef DEBUG
    60 #ifdef DEBUG
    65 /* function defined in main.cc */
    68 /* function defined in main.cc */
    66 extern void error_exit(const char *file_name, int line_no);
    69 extern void error_exit(const char *file_name, int line_no);
    67 
    70 
    68 
    71 
    69 
    72 
       
    73 /* compare the name of two __extensible__ function parameters.
       
    74  * The usual use case is to have one of the parameters as used
       
    75  * in the function declaration, and another as used in a formal function call.
       
    76  *
       
    77  * Will return:
       
    78  *         < 0 : if two parameters are not compatible, or one is invalid
       
    79  *        >= 0 : if both parameters ..........
       
    80  */
       
    81 /*
       
    82  *   ("in", "i0")      -> returns error (<0)
       
    83  *   ("in1", "in")     -> returns error (<0)
       
    84  *   ("in", "in")      -> returns error (<0)
       
    85  *   ("in", "inw")     -> returns error (<0)
       
    86  *   ("in", "in10.4")  -> returns error (<0)
       
    87  *   ("in", "in10e")   -> returns error (<0)
       
    88  *   ("in", "")        -> returns error (<0)
       
    89  *   ("", "in10e")     -> returns error (<0)
       
    90  *   ("in", "in0")     -> returns 0
       
    91  *   ("in", "in9")     -> returns 9
       
    92  *   ("in", "in42")    -> returns 42
       
    93  *   ("in", "in-42")   -> returns -42 (error!)
       
    94  */
       
    95 int function_param_iterator_c::cmp_extparam_names(const char* s1, const char* s2) {
       
    96   int res;
       
    97   char *endptr;
       
    98   int len;
       
    99 
       
   100   if ((s1 == NULL) || (s2 == NULL) || (*s1 == '\0') || (*s2 == '\0')) return -1;
       
   101 
       
   102   len = strlen(s1);
       
   103   if (strncasecmp(s1, s2, len)) return -2;
       
   104 
       
   105   s1 = &s2[len];
       
   106   if (*s1 == '\0') return -3;
       
   107 
       
   108   res = strtol(s1, &endptr, 10);
       
   109   if (*endptr != '\0') return -4;
       
   110 
       
   111   return res;
       
   112 }
       
   113 
       
   114 
       
   115 
    70 void* function_param_iterator_c::handle_param_list(list_c *list) {
   116 void* function_param_iterator_c::handle_param_list(list_c *list) {
    71   switch (current_operation) {
   117   switch (current_operation) {
    72     case iterate_op:
   118     case iterate_op:
    73       if (next_param <= param_count + list->n)
   119       if (next_param <= param_count + list->n)
    74         return list->elements[next_param - param_count - 1];
   120         return list->elements[next_param - param_count - 1];
    77       param_count += list->n;
   123       param_count += list->n;
    78       break;
   124       break;
    79 
   125 
    80     case search_op:
   126     case search_op:
    81       for(int i = 0; i < list->n; i++) {
   127       for(int i = 0; i < list->n; i++) {
    82         identifier_c *variable_name = dynamic_cast<identifier_c *>(list->elements[i]);
   128         symbol_c *sym = list->elements[i];
       
   129         extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(sym);
       
   130         if (extensible_parameter != NULL) {
       
   131           sym = extensible_parameter->var_name;
       
   132           current_param_is_extensible = true;
       
   133           _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
       
   134         }
       
   135         identifier_c *variable_name = dynamic_cast<identifier_c *>(sym);
    83         if (variable_name == NULL) ERROR;
   136         if (variable_name == NULL) ERROR;
    84 
   137         
    85         if (strcasecmp(search_param_name->value, variable_name->value) == 0)
   138         if (!current_param_is_extensible)
    86           /* FOUND! This is the same parameter!! */
   139           if (strcasecmp(search_param_name->value, variable_name->value) == 0)
    87           return (void *)variable_name;
   140             /* FOUND! This is the same parameter!! */
       
   141             return (void *)variable_name;
       
   142   
       
   143         if (current_param_is_extensible) {
       
   144           current_extensible_param_index = cmp_extparam_names(variable_name->value, search_param_name->value);
       
   145           if (current_extensible_param_index >= 0)
       
   146             /* FOUND! This is a compatible extensible parameter!! */
       
   147             return (void *)variable_name;
       
   148         }  
    88       }
   149       }
    89       break;
   150       break;
    90   } /* switch */
   151   } /* switch */
    91 
   152 
    92   /* Not found! */
   153   /* Not found! */
   100       if (next_param == param_count)
   161       if (next_param == param_count)
   101         return var_name;
   162         return var_name;
   102       break;
   163       break;
   103 
   164 
   104     case search_op:
   165     case search_op:
       
   166       extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(var_name);
       
   167       if (extensible_parameter != NULL) {
       
   168         var_name = extensible_parameter->var_name;
       
   169         current_param_is_extensible = true;
       
   170         _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
       
   171       }
   105       identifier_c *variable_name = dynamic_cast<identifier_c *>(var_name);
   172       identifier_c *variable_name = dynamic_cast<identifier_c *>(var_name);
   106       if (variable_name == NULL) ERROR;
   173       if (variable_name == NULL) ERROR;
   107 
   174       
   108       if (strcasecmp(search_param_name->value, variable_name->value) == 0)
   175       if (!current_param_is_extensible)
   109         /* FOUND! This is the same parameter!! */
   176         if (strcasecmp(search_param_name->value, variable_name->value) == 0)
   110         return (void *)variable_name;
   177           /* FOUND! This is the same parameter!! */
       
   178           return (void *)variable_name;
       
   179 
       
   180       if (current_param_is_extensible) {
       
   181         current_extensible_param_index = cmp_extparam_names(variable_name->value, search_param_name->value);
       
   182         if (current_extensible_param_index >= 0)
       
   183           /* FOUND! This is a compatible extensible parameter!! */
       
   184           return (void *)variable_name;
       
   185       }  
   111       break;
   186       break;
   112   } /* switch */
   187   } /* switch */
   113 
   188 
   114   /* Not found! */
   189   /* Not found! */
   115   return NULL;
   190   return NULL;
   126 }
   201 }
   127 
   202 
   128 /* start off at the first parameter once again... */
   203 /* start off at the first parameter once again... */
   129 void function_param_iterator_c::reset(void) {
   204 void function_param_iterator_c::reset(void) {
   130   next_param = param_count = 0;
   205   next_param = param_count = 0;
       
   206   _first_extensible_param_index = -1;
       
   207   current_param_is_extensible = false;
   131   current_param_name = NULL;
   208   current_param_name = NULL;
   132   current_param_type = current_param_default_value = NULL;
   209   current_param_type = current_param_default_value = NULL;
   133 }
   210 }
   134 
   211 
   135 
   212 
   164  */
   241  */
   165 identifier_c *function_param_iterator_c::next(void) {
   242 identifier_c *function_param_iterator_c::next(void) {
   166   void *res;
   243   void *res;
   167   identifier_c *identifier;
   244   identifier_c *identifier;
   168  
   245  
       
   246   if (current_param_is_extensible) {
       
   247     current_extensible_param_index++;
       
   248     return current_param_name;
       
   249   }
       
   250   
   169   param_count = 0;
   251   param_count = 0;
   170   en_eno_param_implicit = false;
   252   en_eno_param_implicit = false;
   171   next_param++;
   253   next_param++;
   172   current_operation = function_param_iterator_c::iterate_op;
   254   current_operation = function_param_iterator_c::iterate_op;
   173   res = f_decl->accept(*this);
   255   res = f_decl->accept(*this);
   174   if (res == NULL) 
   256   if (res == NULL) 
   175     return NULL;
   257     return NULL;
   176 
   258 
   177   symbol_c *sym = (symbol_c *)res;
   259   symbol_c *sym = (symbol_c *)res;
       
   260   extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(sym);
       
   261   if (extensible_parameter != NULL) {
       
   262     sym = extensible_parameter->var_name;
       
   263     current_param_is_extensible = true;
       
   264     _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
       
   265     current_extensible_param_index = _first_extensible_param_index;
       
   266   }
   178   identifier = dynamic_cast<identifier_c *>(sym);
   267   identifier = dynamic_cast<identifier_c *>(sym);
   179   if (identifier == NULL)
   268   if (identifier == NULL)
   180     ERROR;
   269     ERROR;
   181   current_param_name = identifier;
   270   current_param_name = identifier;
   182   return current_param_name;
   271   return current_param_name;
   185 /* Search for the value passed to the parameter named <param_name>...  */
   274 /* Search for the value passed to the parameter named <param_name>...  */
   186 identifier_c *function_param_iterator_c::search(symbol_c *param_name) {
   275 identifier_c *function_param_iterator_c::search(symbol_c *param_name) {
   187   if (NULL == param_name) ERROR;
   276   if (NULL == param_name) ERROR;
   188   search_param_name = dynamic_cast<identifier_c *>(param_name);
   277   search_param_name = dynamic_cast<identifier_c *>(param_name);
   189   if (NULL == search_param_name) ERROR;
   278   if (NULL == search_param_name) ERROR;
       
   279   en_eno_param_implicit = false;
       
   280   current_param_is_extensible = false;
   190   current_operation = function_param_iterator_c::search_op;
   281   current_operation = function_param_iterator_c::search_op;
   191   void *res = f_decl->accept(*this);
   282   void *res = f_decl->accept(*this);
   192   identifier_c *res_param_name = dynamic_cast<identifier_c *>((symbol_c *)res);
   283   identifier_c *res_param_name = dynamic_cast<identifier_c *>((symbol_c *)res);
   193   return res_param_name;
   284   return res_param_name;
   194 }
   285 }
   208 /* Returns if currently referenced parameter is an implicit defined EN/ENO parameter. */
   299 /* Returns if currently referenced parameter is an implicit defined EN/ENO parameter. */
   209 bool function_param_iterator_c::is_en_eno_param_implicit(void) {
   300 bool function_param_iterator_c::is_en_eno_param_implicit(void) {
   210   return en_eno_param_implicit;
   301   return en_eno_param_implicit;
   211 }
   302 }
   212 
   303 
       
   304 /* 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); */
       
   306 bool function_param_iterator_c::is_extensible_param(void) {
       
   307   return current_param_is_extensible;
       
   308 }
       
   309 
       
   310 /* Returns the index of the current extensible parameter. */             
       
   311 /* If the current parameter is not an extensible paramter, returns -1 */
       
   312 int function_param_iterator_c::extensible_param_index(void) {
       
   313   return (current_param_is_extensible? current_extensible_param_index : -1);
       
   314 }
       
   315 
       
   316 /* 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! */
       
   318 int function_param_iterator_c::first_extensible_param_index(void) {
       
   319   return _first_extensible_param_index;
       
   320 }
       
   321 
   213 /* Returns the currently referenced parameter's data passing direction.
   322 /* Returns the currently referenced parameter's data passing direction.
   214  * i.e. VAR_INPUT, VAR_OUTPUT or VAR_INOUT
   323  * i.e. VAR_INPUT, VAR_OUTPUT or VAR_INOUT
   215  */
   324  */
   216 function_param_iterator_c::param_direction_t function_param_iterator_c::param_direction(void) {
   325 function_param_iterator_c::param_direction_t function_param_iterator_c::param_direction(void) {
   217   return current_param_direction;
   326   return current_param_direction;
   218 }
   327 }
   219 
   328 
   220 void *function_param_iterator_c::visit(implicit_definition_c *symbol) {
   329 void *function_param_iterator_c::visit(implicit_definition_c *symbol) {
   221 	en_eno_param_implicit = current_operation == function_param_iterator_c::iterate_op;
   330 	en_eno_param_implicit = true;
   222 	return NULL;
   331 	return NULL;
   223 }
   332 }
   224 
   333 
   225 /****************************************/
   334 /****************************************/
   226 /* 1.4.3 - Declaration & Initialisation */
   335 /* 1.4.3 - Declaration & Initialisation */
   241    * variables, because if the desired parameter is not in the
   350    * variables, because if the desired parameter is not in the
   242    * variable list we will be analysing, the current_param_XXXX
   351    * variable list we will be analysing, the current_param_XXXX
   243    * variables will get overwritten when we visit the next
   352    * variables will get overwritten when we visit the next
   244    * var1_init_decl_c list!
   353    * var1_init_decl_c list!
   245    */
   354    */
   246   symbol->method->accept(*this);
       
   247 
       
   248   current_param_default_value = symbol->value;
   355   current_param_default_value = symbol->value;
   249   current_param_type = symbol->type;
   356   current_param_type = symbol->type;
   250 
   357 
   251   return handle_single_param(symbol->name);
   358   void *res = handle_single_param(symbol->name);
       
   359   
       
   360     /* If we have found the parameter we will be returning, we set the en_eno_param_implicit to TRUE if implicitly defined */
       
   361   if (res != NULL) symbol->method->accept(*this);
       
   362   
       
   363   return res;
   252 }
   364 }
   253 
   365 
   254 /* var1_list ':' array_spec_init */
   366 /* var1_list ':' array_spec_init */
   255 //SYM_REF2(array_var_init_decl_c, var1_list, array_spec_init)
   367 //SYM_REF2(array_var_init_decl_c, var1_list, array_spec_init)
   256 void *function_param_iterator_c::visit(array_var_init_decl_c *symbol) {
   368 void *function_param_iterator_c::visit(array_var_init_decl_c *symbol) {
   276 void *function_param_iterator_c::visit(output_declarations_c *symbol) {
   388 void *function_param_iterator_c::visit(output_declarations_c *symbol) {
   277   TRACE("output_declarations_c");
   389   TRACE("output_declarations_c");
   278   current_param_direction = direction_out;
   390   current_param_direction = direction_out;
   279   return symbol->var_init_decl_list->accept(*this);
   391   return symbol->var_init_decl_list->accept(*this);
   280 }
   392 }
       
   393 
   281 void *function_param_iterator_c::visit(eno_param_declaration_c *symbol) {
   394 void *function_param_iterator_c::visit(eno_param_declaration_c *symbol) {
   282   TRACE("eno_param_declaration_c");
   395   TRACE("eno_param_declaration_c");
   283   /* It is OK to store these values in the current_param_XXX
   396   /* It is OK to store these values in the current_param_XXX
   284    * variables, because if the desired parameter is not in the
   397    * variables, because if the desired parameter is not in the
   285    * variable list we will be analysing, the current_param_XXXX
   398    * variable list we will be analysing, the current_param_XXXX
   286    * variables will get overwritten when we visit the next
   399    * variables will get overwritten when we visit the next
   287    * var1_init_decl_c list!
   400    * var1_init_decl_c list!
   288    */
   401    */
   289   symbol->method->accept(*this);
       
   290 
       
   291   current_param_default_value = NULL;
   402   current_param_default_value = NULL;
   292   current_param_type = symbol->type;
   403   current_param_type = symbol->type;
   293 
   404 
   294   return handle_single_param(symbol->name);
   405   void *res = handle_single_param(symbol->name);
   295 }
   406   
       
   407     /* If we have found the parameter we will be returning, we set the en_eno_param_implicit to TRUE if implicitly defined */
       
   408   if (res != NULL) symbol->method->accept(*this);
       
   409   
       
   410   return res;
       
   411 }
       
   412 
   296 void *function_param_iterator_c::visit(input_output_declarations_c *symbol) {
   413 void *function_param_iterator_c::visit(input_output_declarations_c *symbol) {
   297   TRACE("input_output_declarations_c");
   414   TRACE("input_output_declarations_c");
   298   current_param_direction = direction_inout;
   415   current_param_direction = direction_inout;
   299   return symbol->var_declaration_list->accept(*this);
   416   return symbol->var_declaration_list->accept(*this);
   300 }
   417 }
       
   418 
   301 void *function_param_iterator_c::visit(var_declaration_list_c *symbol) {TRACE("var_declaration_list_c"); return iterate_list(symbol);}
   419 void *function_param_iterator_c::visit(var_declaration_list_c *symbol) {TRACE("var_declaration_list_c"); return iterate_list(symbol);}
   302 
   420 
   303 /*  var1_list ':' array_specification */
   421 /*  var1_list ':' array_specification */
   304 //SYM_REF2(array_var_declaration_c, var1_list, array_specification)
   422 //SYM_REF2(array_var_declaration_c, var1_list, array_specification)
   305 void *function_param_iterator_c::visit(array_var_declaration_c *symbol) {
   423 void *function_param_iterator_c::visit(array_var_declaration_c *symbol) {
   423 
   541 
   424   return symbol->var1_list->accept(*this);
   542   return symbol->var1_list->accept(*this);
   425 }
   543 }
   426 
   544 
   427 
   545 
   428 
       
   429 void *function_param_iterator_c::visit(var1_list_c *symbol) {
   546 void *function_param_iterator_c::visit(var1_list_c *symbol) {
   430   TRACE("var1_list_c");
   547   TRACE("var1_list_c");
   431   return handle_param_list(symbol);
   548   return handle_param_list(symbol);
   432 }
   549 }
       
   550 
   433 
   551 
   434 void *function_param_iterator_c::visit(var_init_decl_list_c *symbol) {TRACE("var_init_decl_list_c"); return iterate_list(symbol);}
   552 void *function_param_iterator_c::visit(var_init_decl_list_c *symbol) {TRACE("var_init_decl_list_c"); return iterate_list(symbol);}
   435 
   553 
   436 
   554 
   437 /***********************/
   555 /***********************/