stage4/generate_c/generate_c_inlinefcall.cc
changeset 258 d7d92b2f87e9
parent 238 0919986a5c98
child 279 c0453b7f99df
equal deleted inserted replaced
257:90782e241346 258:d7d92b2f87e9
       
     1 /*
       
     2  * (c) 2007 Mario de Sousa and Laurent Bessard
       
     3  *
       
     4  * Offered to the public under the terms of the GNU General Public License
       
     5  * as published by the Free Software Foundation; either version 2 of the
       
     6  * License, or (at your option) any later version.
       
     7  *
       
     8  * This program is distributed in the hope that it will be useful, but
       
     9  * WITHOUT ANY WARRANTY; without even the implied warranty of
       
    10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
       
    11  * Public License for more details.
       
    12  *
       
    13  * This code is made available on the understanding that it will not be
       
    14  * used in safety-critical situations without a full and competent review.
       
    15  */
       
    16 
       
    17 /*
       
    18  * An IEC 61131-3 IL and ST compiler.
       
    19  *
       
    20  * Based on the
       
    21  * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
       
    22  *
       
    23  */
       
    24 
       
    25 /*
       
    26  * This is one of the versions available for the 4th stage.
       
    27  *
       
    28  * This 4th stage generates a c++ source program equivalent
       
    29  * to the IL and ST code.
       
    30  */
       
    31 
       
    32 
       
    33 #define INLINE_RESULT_TEMP_VAR "__res"
       
    34 
       
    35 class generate_c_inlinefcall_c: public generate_c_typedecl_c {
       
    36 
       
    37   public:
       
    38     typedef enum {
       
    39       expression_vg,
       
    40       assignment_vg,
       
    41       complextype_base_vg,
       
    42       complextype_suffix_vg
       
    43     } variablegeneration_t;
       
    44 
       
    45   private:
       
    46 
       
    47     /* The name of the IL default variable... */
       
    48 	#define IL_DEFVAR   VAR_LEADER "IL_DEFVAR"
       
    49 	/* The name of the variable used to pass the result of a
       
    50 	 * parenthesised instruction list to the immediately preceding
       
    51 	 * scope ...
       
    52 	 */
       
    53 	il_default_variable_c default_variable_name;
       
    54 
       
    55 	symbol_c* current_array_type;
       
    56 
       
    57 	int fcall_number;
       
    58 	symbol_c *fbname;
       
    59 
       
    60     search_expression_type_c *search_expression_type;
       
    61 
       
    62     search_varfb_instance_type_c *search_varfb_instance_type;
       
    63 
       
    64     search_base_type_c search_base_type;
       
    65 
       
    66     variablegeneration_t wanted_variablegeneration;
       
    67 
       
    68   public:
       
    69     generate_c_inlinefcall_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
       
    70     : generate_c_typedecl_c(s4o_ptr),
       
    71       default_variable_name(IL_DEFVAR, NULL)
       
    72     {
       
    73       search_expression_type = new search_expression_type_c(scope);
       
    74       search_varfb_instance_type = new search_varfb_instance_type_c(scope);
       
    75       this->set_variable_prefix(variable_prefix);
       
    76       fcall_number = 0;
       
    77       fbname = name;
       
    78       wanted_variablegeneration = expression_vg;
       
    79     }
       
    80 
       
    81     virtual ~generate_c_inlinefcall_c(void) {
       
    82       delete search_expression_type;
       
    83       delete search_varfb_instance_type;
       
    84     }
       
    85 
       
    86     void print(symbol_c* symbol) {
       
    87       function_call_iterator_c fc_iterator(symbol);
       
    88       symbol_c* function_call;
       
    89       while ((function_call = fc_iterator.next()) != NULL) {
       
    90     	function_call->accept(*this);
       
    91       }
       
    92     }
       
    93 
       
    94     void generate_inline(symbol_c *function_name,
       
    95             symbol_c *function_type_prefix,
       
    96             symbol_c *function_type_suffix,
       
    97             std::list<FUNCTION_PARAM*> param_list) {
       
    98             std::list<FUNCTION_PARAM*>::iterator pt;
       
    99 
       
   100       fcall_number++;
       
   101 
       
   102       s4o.print(s4o.indent_spaces);
       
   103       s4o.print("inline ");
       
   104       function_type_prefix->accept(*this);
       
   105       s4o.print(" __");
       
   106       fbname->accept(*this);
       
   107       s4o.print("_");
       
   108       function_name->accept(*this);
       
   109       if (function_type_suffix)
       
   110         function_type_suffix->accept(*this);
       
   111       s4o.print_integer(fcall_number);
       
   112       s4o.print("(");
       
   113       s4o.indent_right();
       
   114 
       
   115       PARAM_LIST_ITERATOR() {
       
   116         if (PARAM_DIRECTION == function_param_iterator_c::direction_in) {
       
   117           PARAM_TYPE->accept(*this);
       
   118           s4o.print(" ");
       
   119           PARAM_NAME->accept(*this);
       
   120           s4o.print(",\n" + s4o.indent_spaces);
       
   121         }
       
   122       }
       
   123       fbname->accept(*this);
       
   124 	  s4o.print(" *");
       
   125 	  s4o.print(FB_FUNCTION_PARAM);
       
   126 	  s4o.indent_left();
       
   127 	  s4o.print(")\n" + s4o.indent_spaces);
       
   128 	  s4o.print("{\n");
       
   129       s4o.indent_right();
       
   130 
       
   131       s4o.print(s4o.indent_spaces);
       
   132       function_type_prefix->accept(*this);
       
   133       s4o.print(" "),
       
   134       s4o.print(INLINE_RESULT_TEMP_VAR);
       
   135       s4o.print(";\n");
       
   136 
       
   137 	  PARAM_LIST_ITERATOR() {
       
   138 		if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
       
   139 		     PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
       
   140 		    PARAM_VALUE != NULL) {
       
   141 		  s4o.print(s4o.indent_spaces);
       
   142 		  PARAM_TYPE->accept(*this);
       
   143           s4o.print(" ");
       
   144           s4o.print(TEMP_VAR);
       
   145           PARAM_NAME->accept(*this);
       
   146           s4o.print(" = ");
       
   147           print_check_function(PARAM_TYPE, PARAM_VALUE);
       
   148           s4o.print(";\n");
       
   149 		}
       
   150 	  }
       
   151 
       
   152 	  s4o.print(s4o.indent_spaces + INLINE_RESULT_TEMP_VAR),
       
   153 			  s4o.print(" = ");
       
   154 	  function_name->accept(*this);
       
   155 	  if (function_type_suffix)
       
   156         function_type_suffix->accept(*this);
       
   157 	  s4o.print("(");
       
   158 	  s4o.indent_right();
       
   159 
       
   160 	  PARAM_LIST_ITERATOR() {
       
   161 		if (pt != param_list.begin())
       
   162 		  s4o.print(",\n" + s4o.indent_spaces);
       
   163 		if (PARAM_DIRECTION == function_param_iterator_c::direction_in)
       
   164 		  PARAM_NAME->accept(*this);
       
   165 		else if (PARAM_VALUE != NULL){
       
   166           s4o.print("&");
       
   167           s4o.print(TEMP_VAR);
       
   168           PARAM_NAME->accept(*this);
       
   169         }
       
   170 		else {
       
   171 		  s4o.print("NULL");
       
   172 		}
       
   173 	  }
       
   174 	  s4o.print(");\n");
       
   175 	  s4o.indent_left();
       
   176 
       
   177 	  PARAM_LIST_ITERATOR() {
       
   178         if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
       
   179         	 PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
       
   180         	PARAM_VALUE != NULL) {
       
   181 
       
   182           s4o.print(s4o.indent_spaces);
       
   183           print_setter(PARAM_VALUE, PARAM_TYPE, PARAM_NAME);
       
   184           s4o.print(";\n");
       
   185 		}
       
   186 	  }
       
   187 	  s4o.print(s4o.indent_spaces + "return ");
       
   188 	  s4o.print(INLINE_RESULT_TEMP_VAR);
       
   189 	  s4o.print(";\n");
       
   190 
       
   191       s4o.indent_left();
       
   192       s4o.print(s4o.indent_spaces + "}\n\n");
       
   193     }
       
   194 
       
   195   private:
       
   196 
       
   197     void *print_getter(symbol_c *symbol) {
       
   198       unsigned int vartype = search_varfb_instance_type->get_vartype(symbol);
       
   199       if (vartype == search_var_instance_decl_c::external_vt)
       
   200     	s4o.print(GET_EXTERNAL);
       
   201       else if (vartype == search_var_instance_decl_c::located_vt)
       
   202     	s4o.print(GET_LOCATED);
       
   203       else
       
   204     	s4o.print(GET_VAR);
       
   205       s4o.print("(");
       
   206 
       
   207       wanted_variablegeneration = complextype_base_vg;
       
   208       symbol->accept(*this);
       
   209       if (search_varfb_instance_type->type_is_complex())
       
   210     	s4o.print(",");
       
   211       wanted_variablegeneration = complextype_suffix_vg;
       
   212       symbol->accept(*this);
       
   213       s4o.print(")");
       
   214       wanted_variablegeneration = expression_vg;
       
   215       return NULL;
       
   216     }
       
   217 
       
   218     void *print_setter(symbol_c* symbol,
       
   219     		symbol_c* type,
       
   220     		symbol_c* value) {
       
   221       unsigned int vartype = search_varfb_instance_type->get_vartype(symbol);
       
   222       if (vartype == search_var_instance_decl_c::external_vt) {
       
   223         symbolic_variable_c *variable = dynamic_cast<symbolic_variable_c *>(symbol);
       
   224         /* TODO Find a solution for forcing global complex variables */
       
   225         if (variable != NULL) {
       
   226           s4o.print(SET_EXTERNAL);
       
   227           s4o.print("(");
       
   228           variable->var_name->accept(*this);
       
   229           s4o.print(",");
       
   230         }
       
   231         else {
       
   232           s4o.print(SET_COMPLEX_EXTERNAL);
       
   233           s4o.print("(");
       
   234         }
       
   235       }
       
   236       else {
       
   237         if (vartype == search_var_instance_decl_c::located_vt)
       
   238           s4o.print(SET_LOCATED);
       
   239         else
       
   240           s4o.print(SET_VAR);
       
   241         s4o.print("(");
       
   242       }
       
   243 
       
   244       wanted_variablegeneration = complextype_base_vg;
       
   245       symbol->accept(*this);
       
   246       s4o.print(",");
       
   247       wanted_variablegeneration = expression_vg;
       
   248       print_check_function(type, value, NULL, true);
       
   249       if (search_varfb_instance_type->type_is_complex()) {
       
   250         s4o.print(",");
       
   251         wanted_variablegeneration = complextype_suffix_vg;
       
   252         symbol->accept(*this);
       
   253       }
       
   254       s4o.print(")");
       
   255       wanted_variablegeneration = expression_vg;
       
   256       return NULL;
       
   257     }
       
   258 
       
   259     /*********************/
       
   260     /* B 1.4 - Variables */
       
   261     /*********************/
       
   262     void *visit(symbolic_variable_c *symbol) {
       
   263       unsigned int vartype;
       
   264       if (wanted_variablegeneration == complextype_base_vg)
       
   265         generate_c_base_c::visit(symbol);
       
   266       else if (wanted_variablegeneration == complextype_suffix_vg)
       
   267         return NULL;
       
   268       else
       
   269         print_getter(symbol);
       
   270       return NULL;
       
   271     }
       
   272 
       
   273     /********************************************/
       
   274     /* B.1.4.1   Directly Represented Variables */
       
   275     /********************************************/
       
   276     // direct_variable: direct_variable_token   {$$ = new direct_variable_c($1);};
       
   277     void *visit(direct_variable_c *symbol) {
       
   278       TRACE("direct_variable_c");
       
   279       /* Do not use print_token() as it will change everything into uppercase */
       
   280       if (strlen(symbol->value) == 0) ERROR;
       
   281       s4o.print(GET_LOCATED);
       
   282       s4o.print("(");
       
   283       this->print_variable_prefix();
       
   284       s4o.printlocation(symbol->value + 1);
       
   285       s4o.print(")");
       
   286       return NULL;
       
   287     }
       
   288 
       
   289     /*************************************/
       
   290     /* B.1.4.2   Multi-element Variables */
       
   291     /*************************************/
       
   292 
       
   293     // SYM_REF2(structured_variable_c, record_variable, field_selector)
       
   294     void *visit(structured_variable_c *symbol) {
       
   295       TRACE("structured_variable_c");
       
   296       switch (wanted_variablegeneration) {
       
   297         case complextype_base_vg:
       
   298           symbol->record_variable->accept(*this);
       
   299           break;
       
   300         case complextype_suffix_vg:
       
   301           symbol->record_variable->accept(*this);
       
   302           s4o.print(".");
       
   303           symbol->field_selector->accept(*this);
       
   304           break;
       
   305         default:
       
   306           print_getter(symbol);
       
   307           break;
       
   308       }
       
   309       return NULL;
       
   310     }
       
   311 
       
   312     /*  subscripted_variable '[' subscript_list ']' */
       
   313     //SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
       
   314     void *visit(array_variable_c *symbol) {
       
   315       switch (wanted_variablegeneration) {
       
   316         case complextype_base_vg:
       
   317           symbol->subscripted_variable->accept(*this);
       
   318           break;
       
   319         case complextype_suffix_vg:
       
   320           symbol->subscripted_variable->accept(*this);
       
   321 
       
   322           current_array_type = search_varfb_instance_type->get_rawtype(symbol->subscripted_variable);
       
   323           if (current_array_type == NULL) ERROR;
       
   324 
       
   325           s4o.print(".table");
       
   326           symbol->subscript_list->accept(*this);
       
   327 
       
   328           current_array_type = NULL;
       
   329           break;
       
   330         default:
       
   331           print_getter(symbol);
       
   332           break;
       
   333       }
       
   334       return NULL;
       
   335     }
       
   336 
       
   337     /****************************************/
       
   338     /* B.2 - Language IL (Instruction List) */
       
   339     /****************************************/
       
   340 
       
   341     /***********************************/
       
   342     /* B 2.1 Instructions and Operands */
       
   343     /***********************************/
       
   344 
       
   345     void *visit(il_function_call_c *symbol) {
       
   346       symbol_c* function_type_prefix = NULL;
       
   347       symbol_c* function_name = NULL;
       
   348       symbol_c* function_type_suffix = NULL;
       
   349       DECLARE_PARAM_LIST()
       
   350 
       
   351       symbol_c *param_data_type = default_variable_name.current_type;
       
   352 
       
   353       function_call_param_iterator_c function_call_param_iterator(symbol);
       
   354 
       
   355       function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
       
   356 	  if (f_decl == function_symtable.end_value()) {
       
   357         function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
       
   358         if (current_function_type == function_none) ERROR;
       
   359 
       
   360         function_type_prefix = (symbol_c *)search_expression_type->compute_standard_function_il(symbol, param_data_type);
       
   361 
       
   362         symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN"));
       
   363         /* Add the value from EN param */
       
   364         ADD_PARAM_LIST(en_param_name,
       
   365                        (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c())),
       
   366                        (symbol_c*)(new bool_type_name_c()),
       
   367                        function_param_iterator_c::direction_in)
       
   368 
       
   369         symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO"));
       
   370         /* Add the value from ENO param */
       
   371         ADD_PARAM_LIST(eno_param_name, NULL, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
       
   372 
       
   373         int nb_param = 1;
       
   374         if (symbol->il_operand_list != NULL)
       
   375           nb_param += ((list_c *)symbol->il_operand_list)->n;
       
   376 
       
   377         #include "il_code_gen.c"
       
   378 
       
   379       }
       
   380 	  else {
       
   381 		function_name = symbol->function_name;
       
   382 
       
   383 		/* determine the base data type returned by the function being called... */
       
   384 		search_base_type_c search_base_type;
       
   385 		function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
       
   386 
       
   387 		/* loop through each function parameter, find the value we should pass
       
   388 		 * to it, and then output the c equivalent...
       
   389 		 */
       
   390 
       
   391 		function_param_iterator_c fp_iterator(f_decl);
       
   392 		identifier_c *param_name;
       
   393 		for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
       
   394 		  symbol_c *param_type = fp_iterator.param_type();
       
   395 		  if (param_type == NULL) ERROR;
       
   396 
       
   397 		  function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
       
   398 
       
   399 		  symbol_c *param_value = NULL;
       
   400 
       
   401 		  /* if it is the first parameter, semantics specifies that we should
       
   402 		   * get the value off the IL default variable!
       
   403 		   */
       
   404 		  if (1 == i)
       
   405 		    param_value = &this->default_variable_name;
       
   406 
       
   407 		  /* Get the value from a foo(<param_name> = <param_value>) style call */
       
   408 		  /* NOTE: the following line of code is not required in this case, but it doesn't
       
   409 		   * harm to leave it in, as in the case of a non-formal syntax function call,
       
   410 		   * it will always return NULL.
       
   411 		   * We leave it in in case we later decide to merge this part of the code together
       
   412 		   * with the function calling code in generate_c_st_c, which does require
       
   413 		   * the following line...
       
   414 		   */
       
   415 		  if (param_value == NULL)
       
   416 			param_value = function_call_param_iterator.search_f(param_name);
       
   417 
       
   418 		  /* Get the value from a foo(<param_value>) style call */
       
   419           if (param_value == NULL) {
       
   420             param_value = function_call_param_iterator.next_nf();
       
   421             if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR;
       
   422           }
       
   423 
       
   424 		  if (param_value == NULL && param_direction == function_param_iterator_c::direction_in) {
       
   425 			/* No value given for parameter, so we must use the default... */
       
   426 			/* First check whether default value specified in function declaration...*/
       
   427 			param_value = fp_iterator.default_value();
       
   428 		  }
       
   429 
       
   430 		  ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction())
       
   431 		} /* for(...) */
       
   432 	  }
       
   433 
       
   434 	  if (function_call_param_iterator.next_nf() != NULL) ERROR;
       
   435       if (NULL == function_type_prefix) ERROR;
       
   436 
       
   437       bool has_output_params = false;
       
   438 
       
   439       PARAM_LIST_ITERATOR() {
       
   440         if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
       
   441              PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
       
   442              PARAM_VALUE != NULL) {
       
   443           has_output_params = true;
       
   444         }
       
   445       }
       
   446 
       
   447       if (has_output_params)
       
   448         generate_inline(function_name, function_type_prefix, function_type_suffix, param_list);
       
   449 
       
   450       CLEAR_PARAM_LIST()
       
   451 
       
   452       return NULL;
       
   453     }
       
   454 
       
   455     /* | function_name '(' eol_list [il_param_list] ')' */
       
   456     // SYM_REF2(il_formal_funct_call_c, function_name, il_param_list)
       
   457     void *visit(il_formal_funct_call_c *symbol) {
       
   458       symbol_c* function_type_prefix = NULL;
       
   459       symbol_c* function_name = NULL;
       
   460       symbol_c* function_type_suffix = NULL;
       
   461       DECLARE_PARAM_LIST()
       
   462 
       
   463       function_call_param_iterator_c function_call_param_iterator(symbol);
       
   464 
       
   465       function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
       
   466       if (f_decl == function_symtable.end_value()) {
       
   467         function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
       
   468         if (current_function_type == function_none) ERROR;
       
   469 
       
   470         function_type_prefix = (symbol_c *)search_expression_type->compute_standard_function_default(NULL, symbol);
       
   471 
       
   472         int nb_param = 0;
       
   473         if (symbol->il_param_list != NULL)
       
   474           nb_param += ((list_c *)symbol->il_param_list)->n;
       
   475 
       
   476         symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN"));
       
   477         /* Get the value from EN param */
       
   478         symbol_c *EN_param_value = function_call_param_iterator.search_f(en_param_name);
       
   479         if (EN_param_value == NULL)
       
   480           EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c()));
       
   481         else
       
   482           nb_param --;
       
   483         ADD_PARAM_LIST(en_param_name, EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in)
       
   484 
       
   485         symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO"));
       
   486         /* Get the value from ENO param */
       
   487         symbol_c *ENO_param_value = function_call_param_iterator.search_f(eno_param_name);
       
   488         if (ENO_param_value != NULL)
       
   489           nb_param --;
       
   490         ADD_PARAM_LIST(eno_param_name, ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
       
   491 
       
   492         #include "st_code_gen.c"
       
   493 
       
   494       }
       
   495       else {
       
   496         function_name = symbol->function_name;
       
   497 
       
   498 		/* determine the base data type returned by the function being called... */
       
   499 		search_base_type_c search_base_type;
       
   500 		function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
       
   501 
       
   502 		/* loop through each function parameter, find the value we should pass
       
   503 		 * to it, and then output the c equivalent...
       
   504 		 */
       
   505 
       
   506 		function_param_iterator_c fp_iterator(f_decl);
       
   507 		identifier_c *param_name;
       
   508 		for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
       
   509 		  symbol_c *param_type = fp_iterator.param_type();
       
   510 		  if (param_type == NULL) ERROR;
       
   511 
       
   512 		  function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
       
   513 
       
   514 
       
   515 		  symbol_c *param_value = NULL;
       
   516 
       
   517 		  /* Get the value from a foo(<param_name> = <param_value>) style call */
       
   518 		  if (param_value == NULL)
       
   519 			param_value = function_call_param_iterator.search_f(param_name);
       
   520 
       
   521 		  /* Get the value from a foo(<param_value>) style call */
       
   522 		  /* NOTE: the following line of code is not required in this case, but it doesn't
       
   523 		   * harm to leave it in, as in the case of a formal syntax function call,
       
   524 		   * it will always return NULL.
       
   525 		   * We leave it in in case we later decide to merge this part of the code together
       
   526 		   * with the function calling code in generate_c_st_c, which does require
       
   527 		   * the following line...
       
   528 		   */
       
   529 		  if (param_value == NULL) {
       
   530             param_value = function_call_param_iterator.next_nf();
       
   531             if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR;
       
   532           }
       
   533 
       
   534 		  if (param_value == NULL) {
       
   535 			/* No value given for parameter, so we must use the default... */
       
   536 			/* First check whether default value specified in function declaration...*/
       
   537 			param_value = fp_iterator.default_value();
       
   538 		  }
       
   539 
       
   540 		  ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction())
       
   541 		}
       
   542       }
       
   543 
       
   544       if (function_call_param_iterator.next_nf() != NULL) ERROR;
       
   545       if (NULL == function_type_prefix) ERROR;
       
   546 
       
   547       bool has_output_params = false;
       
   548 
       
   549       PARAM_LIST_ITERATOR() {
       
   550         if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
       
   551              PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
       
   552              PARAM_VALUE != NULL) {
       
   553           has_output_params = true;
       
   554         }
       
   555       }
       
   556 
       
   557       if (has_output_params)
       
   558         generate_inline(function_name, function_type_prefix, function_type_suffix, param_list);
       
   559 
       
   560       CLEAR_PARAM_LIST()
       
   561 
       
   562       return NULL;
       
   563     }
       
   564 
       
   565     /***************************************/
       
   566     /* B.3 - Language ST (Structured Text) */
       
   567     /***************************************/
       
   568     /***********************/
       
   569     /* B 3.1 - Expressions */
       
   570     /***********************/
       
   571 
       
   572     void *visit(function_invocation_c *symbol) {
       
   573       symbol_c* function_type_prefix = NULL;
       
   574       symbol_c* function_name = NULL;
       
   575       symbol_c* function_type_suffix = NULL;
       
   576       DECLARE_PARAM_LIST()
       
   577 
       
   578       symbol_c *parameter_assignment_list = NULL;
       
   579       if (NULL != symbol->   formal_param_list) parameter_assignment_list = symbol->   formal_param_list;
       
   580       if (NULL != symbol->nonformal_param_list) parameter_assignment_list = symbol->nonformal_param_list;
       
   581       if (NULL == parameter_assignment_list) ERROR;
       
   582 
       
   583       function_call_param_iterator_c function_call_param_iterator(symbol);
       
   584 
       
   585       function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name);
       
   586       if (f_decl == function_symtable.end_value()) {
       
   587         /* The function called is not in the symtable, so we test if it is a
       
   588          * standard function defined in standard */
       
   589 
       
   590         function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
       
   591         if (current_function_type == function_none) ERROR;
       
   592 
       
   593         function_type_prefix = search_expression_type->get_type(symbol);
       
   594 
       
   595         int nb_param = ((list_c *)parameter_assignment_list)->n;
       
   596 
       
   597         symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN"));
       
   598         /* Get the value from EN param */
       
   599         symbol_c *EN_param_value = function_call_param_iterator.search_f(en_param_name);
       
   600         if (EN_param_value == NULL)
       
   601           EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c()));
       
   602         else
       
   603           nb_param --;
       
   604         ADD_PARAM_LIST(en_param_name, EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in)
       
   605 
       
   606         symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO"));
       
   607         /* Get the value from ENO param */
       
   608         symbol_c *ENO_param_value = function_call_param_iterator.search_f(eno_param_name);
       
   609         if (ENO_param_value != NULL)
       
   610           nb_param --;
       
   611         ADD_PARAM_LIST(eno_param_name, ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
       
   612 
       
   613         #include "st_code_gen.c"
       
   614 
       
   615       }
       
   616       else {
       
   617         function_name = symbol->function_name;
       
   618 
       
   619 	    /* determine the base data type returned by the function being called... */
       
   620 		search_base_type_c search_base_type;
       
   621 		function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
       
   622 
       
   623     	/* loop through each function parameter, find the value we should pass
       
   624          * to it, and then output the c equivalent...
       
   625          */
       
   626         function_param_iterator_c fp_iterator(f_decl);
       
   627         identifier_c *param_name;
       
   628         for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
       
   629           symbol_c *param_type = fp_iterator.param_type();
       
   630           if (param_type == NULL) ERROR;
       
   631 
       
   632           function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
       
   633 
       
   634           /* Get the value from a foo(<param_name> = <param_value>) style call */
       
   635           symbol_c *param_value = function_call_param_iterator.search_f(param_name);
       
   636 
       
   637           /* Get the value from a foo(<param_value>) style call */
       
   638           if (param_value == NULL) {
       
   639             param_value = function_call_param_iterator.next_nf();
       
   640             if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR;
       
   641           }
       
   642 
       
   643           if (param_value == NULL && param_direction == function_param_iterator_c::direction_in) {
       
   644             /* No value given for parameter, so we must use the default... */
       
   645             /* First check whether default value specified in function declaration...*/
       
   646             param_value = fp_iterator.default_value();
       
   647           }
       
   648 
       
   649           ADD_PARAM_LIST(param_name, param_value, param_type, param_direction)
       
   650         } /* for(...) */
       
   651         // symbol->parameter_assignment->accept(*this);
       
   652       }
       
   653 
       
   654       if (function_call_param_iterator.next_nf() != NULL) ERROR;
       
   655       if (NULL == function_type_prefix) ERROR;
       
   656 
       
   657 	  bool has_output_params = false;
       
   658 
       
   659 	  PARAM_LIST_ITERATOR() {
       
   660         if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
       
   661              PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
       
   662              PARAM_VALUE != NULL) {
       
   663           has_output_params = true;
       
   664         }
       
   665       }
       
   666 
       
   667       if (has_output_params)
       
   668         generate_inline(function_name, function_type_prefix, function_type_suffix, param_list);
       
   669 
       
   670       CLEAR_PARAM_LIST()
       
   671 
       
   672 	  return NULL;
       
   673     }
       
   674 
       
   675 };  /* generate_c_inlinefcall_c */
       
   676 
       
   677