stage4/generate_c/generate_c_st.cc
changeset 217 f5dfadf5de54
parent 216 136d6ae70745
child 220 f332b62cd2c1
equal deleted inserted replaced
216:136d6ae70745 217:f5dfadf5de54
    38 /***********************************************************************/
    38 /***********************************************************************/
    39 
    39 
    40 
    40 
    41 class generate_c_st_c: public generate_c_typedecl_c {
    41 class generate_c_st_c: public generate_c_typedecl_c {
    42 
    42 
       
    43   public:
       
    44     typedef enum {
       
    45       expression_vg,
       
    46       assignment_vg,
       
    47       fparam_output_vg
       
    48     } variablegeneration_t;
       
    49 
    43   private:
    50   private:
    44     /* When calling a function block, we must first find it's type,
    51     /* When calling a function block, we must first find it's type,
    45      * by searching through the declarations of the variables currently
    52      * by searching through the declarations of the variables currently
    46      * in scope.
    53      * in scope.
    47      * This class does just that...
    54      * This class does just that...
    70 
    77 
    71     search_base_type_c search_base_type;
    78     search_base_type_c search_base_type;
    72 
    79 
    73     symbol_c* current_array_type;
    80     symbol_c* current_array_type;
    74 
    81 
    75     bool current_param_is_pointer;
    82     int fcall_number;
       
    83     symbol_c *fbname;
       
    84 
       
    85     variablegeneration_t wanted_variablegeneration;
    76 
    86 
    77   public:
    87   public:
    78     generate_c_st_c(stage4out_c *s4o_ptr, symbol_c *scope, const char *variable_prefix = NULL)
    88     generate_c_st_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
    79     : generate_c_typedecl_c(s4o_ptr) {
    89     : generate_c_typedecl_c(s4o_ptr) {
    80       search_fb_instance_decl = new search_fb_instance_decl_c(scope);
    90       search_fb_instance_decl = new search_fb_instance_decl_c(scope);
    81       search_expression_type = new search_expression_type_c(scope);
    91       search_expression_type = new search_expression_type_c(scope);
    82       search_varfb_instance_type = new search_varfb_instance_type_c(scope);
    92       search_varfb_instance_type = new search_varfb_instance_type_c(scope);
    83       this->set_variable_prefix(variable_prefix);
    93       this->set_variable_prefix(variable_prefix);
    84       current_array_type = NULL;
    94       current_array_type = NULL;
    85       current_param_is_pointer = false;
    95       fcall_number = 0;
       
    96       fbname = name;
       
    97       wanted_variablegeneration = expression_vg;
    86     }
    98     }
    87 
    99 
    88     virtual ~generate_c_st_c(void) {
   100     virtual ~generate_c_st_c(void) {
    89       delete search_fb_instance_decl;
   101       delete search_fb_instance_decl;
    90       delete search_expression_type;
   102       delete search_expression_type;
   103 /*********************/
   115 /*********************/
   104 /* B 1.4 - Variables */
   116 /* B 1.4 - Variables */
   105 /*********************/
   117 /*********************/
   106 void *visit(symbolic_variable_c *symbol) {
   118 void *visit(symbolic_variable_c *symbol) {
   107   unsigned int vartype = search_varfb_instance_type->get_vartype(symbol);
   119   unsigned int vartype = search_varfb_instance_type->get_vartype(symbol);
   108   if (!current_param_is_pointer && (vartype == search_var_instance_decl_c::external_vt || vartype == search_var_instance_decl_c::located_vt)) {
   120   if (this->is_variable_prefix_null()) {
   109     s4o.print("*(");
   121     if (wanted_variablegeneration == fparam_output_vg) {
   110     generate_c_base_c::visit(symbol);
   122       if (vartype == search_var_instance_decl_c::external_vt) {
   111     s4o.print(")");
   123     	s4o.print(GET_EXTERNAL);
   112   }
   124     	s4o.print("(");
   113   else if (current_param_is_pointer && vartype != search_var_instance_decl_c::external_vt && vartype != search_var_instance_decl_c::located_vt) {
   125     	symbol->var_name->accept(*this);
   114     s4o.print("&(");
   126       }
   115     generate_c_base_c::visit(symbol);
   127       else {
   116     s4o.print(")");
   128     	s4o.print("&(");
       
   129         generate_c_base_c::visit(symbol);
       
   130       }
       
   131       s4o.print(")");
       
   132     }
       
   133     else {
       
   134       if (vartype == search_var_instance_decl_c::external_vt) {
       
   135         s4o.print(GET_EXTERNAL);
       
   136         s4o.print("(");
       
   137         symbol->var_name->accept(*this);
       
   138         s4o.print(")");
       
   139       }
       
   140       else
       
   141     	generate_c_base_c::visit(symbol);
       
   142     }
   117   }
   143   }
   118   else {
   144   else {
   119     generate_c_base_c::visit(symbol);
   145     switch (wanted_variablegeneration) {
       
   146       case expression_vg:
       
   147         if (vartype == search_var_instance_decl_c::external_vt) {
       
   148     	  s4o.print(GET_EXTERNAL);
       
   149     	  s4o.print("(");
       
   150           symbol->var_name->accept(*this);
       
   151         }
       
   152         else {
       
   153           if (vartype == search_var_instance_decl_c::located_vt)
       
   154             s4o.print(GET_LOCATED);
       
   155           else
       
   156             s4o.print(GET_VAR);
       
   157           s4o.print("(");
       
   158           generate_c_base_c::visit(symbol);
       
   159         }
       
   160         s4o.print(")");
       
   161 		break;
       
   162       case fparam_output_vg:
       
   163         if (vartype == search_var_instance_decl_c::external_vt) {
       
   164           s4o.print(GET_EXTERNAL_BY_REF);
       
   165           s4o.print("(");
       
   166           symbol->var_name->accept(*this);
       
   167         }
       
   168         else {
       
   169           if (vartype == search_var_instance_decl_c::located_vt)
       
   170             s4o.print(GET_LOCATED_BY_REF);
       
   171           else
       
   172             s4o.print(GET_VAR_BY_REF);
       
   173           s4o.print("(");
       
   174           generate_c_base_c::visit(symbol);
       
   175         }
       
   176         s4o.print(")");
       
   177         break;
       
   178       default:
       
   179         if (vartype == search_var_instance_decl_c::external_vt)
       
   180           symbol->var_name->accept(*this);
       
   181         else
       
   182           generate_c_base_c::visit(symbol);
       
   183         break;
       
   184 	}
   120   }
   185   }
   121   return NULL;
   186   return NULL;
   122 }
   187 }
   123 
   188 
   124 /********************************************/
   189 /********************************************/
   127 // direct_variable: direct_variable_token   {$$ = new direct_variable_c($1);};
   192 // direct_variable: direct_variable_token   {$$ = new direct_variable_c($1);};
   128 void *visit(direct_variable_c *symbol) {
   193 void *visit(direct_variable_c *symbol) {
   129   TRACE("direct_variable_c");
   194   TRACE("direct_variable_c");
   130   /* Do not use print_token() as it will change everything into uppercase */
   195   /* Do not use print_token() as it will change everything into uppercase */
   131   if (strlen(symbol->value) == 0) ERROR;
   196   if (strlen(symbol->value) == 0) ERROR;
   132   if (!current_param_is_pointer) {
   197   if (this->is_variable_prefix_null()) {
   133     s4o.print("*(");
   198     if (wanted_variablegeneration != fparam_output_vg)
       
   199 	  s4o.print("*(");
       
   200   }
       
   201   else {
       
   202     switch (wanted_variablegeneration) {
       
   203       case expression_vg:
       
   204   	    s4o.print(GET_LOCATED);
       
   205   	    s4o.print("(");
       
   206   	    break;
       
   207       case fparam_output_vg:
       
   208         s4o.print(GET_LOCATED_BY_REF);
       
   209         s4o.print("(");
       
   210         break;
       
   211       default:
       
   212         break;
       
   213     }
   134   }
   214   }
   135   this->print_variable_prefix();
   215   this->print_variable_prefix();
   136   s4o.printlocation(symbol->value + 1);
   216   s4o.printlocation(symbol->value + 1);
   137   if (!current_param_is_pointer) {
   217   if ((this->is_variable_prefix_null() && wanted_variablegeneration != fparam_output_vg) ||
       
   218 	  wanted_variablegeneration != assignment_vg)
   138     s4o.print(")");
   219     s4o.print(")");
   139   }
       
   140   return NULL;
   220   return NULL;
   141 }
   221 }
   142 
   222 
   143 /*************************************/
   223 /*************************************/
   144 /* B.1.4.2   Multi-element Variables */
   224 /* B.1.4.2   Multi-element Variables */
   402 
   482 
   403 void *visit(function_invocation_c *symbol) {
   483 void *visit(function_invocation_c *symbol) {
   404   symbol_c* function_type_prefix = NULL;
   484   symbol_c* function_type_prefix = NULL;
   405   symbol_c* function_name = NULL;
   485   symbol_c* function_name = NULL;
   406   symbol_c* function_type_suffix = NULL;
   486   symbol_c* function_type_suffix = NULL;
   407   std::list<FUNCTION_PARAM> param_list;
   487   DECLARE_PARAM_LIST()
   408   FUNCTION_PARAM *param;
       
   409 
   488 
   410   symbol_c *parameter_assignment_list = NULL;
   489   symbol_c *parameter_assignment_list = NULL;
   411   if (NULL != symbol->   formal_param_list) parameter_assignment_list = symbol->   formal_param_list;
   490   if (NULL != symbol->   formal_param_list) parameter_assignment_list = symbol->   formal_param_list;
   412   if (NULL != symbol->nonformal_param_list) parameter_assignment_list = symbol->nonformal_param_list;
   491   if (NULL != symbol->nonformal_param_list) parameter_assignment_list = symbol->nonformal_param_list;
   413   if (NULL == parameter_assignment_list) ERROR;
   492   if (NULL == parameter_assignment_list) ERROR;
   431     symbol_c *EN_param_value = function_call_param_iterator.search_f(&en_param_name);
   510     symbol_c *EN_param_value = function_call_param_iterator.search_f(&en_param_name);
   432     if (EN_param_value == NULL)
   511     if (EN_param_value == NULL)
   433       EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c()));
   512       EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c()));
   434     else
   513     else
   435       nb_param --;
   514       nb_param --;
   436     ADD_PARAM_LIST(EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in)
   515     ADD_PARAM_LIST(&en_param_name, EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in)
   437 
   516 
   438     identifier_c eno_param_name("ENO");
   517     identifier_c eno_param_name("ENO");
   439     /* Get the value from ENO param */
   518     /* Get the value from ENO param */
   440     symbol_c *ENO_param_value = function_call_param_iterator.search_f(&eno_param_name);
   519     symbol_c *ENO_param_value = function_call_param_iterator.search_f(&eno_param_name);
   441     if (ENO_param_value != NULL)
   520     if (ENO_param_value != NULL)
   442       nb_param --;
   521       nb_param --;
   443     ADD_PARAM_LIST(ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
   522     ADD_PARAM_LIST(&eno_param_name, ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out)
   444 
   523 
   445     #include "st_code_gen.c"
   524     #include "st_code_gen.c"
   446 
   525 
   447   }
   526   }
   448   else {
   527   else {
   449     /* loop through each function parameter, find the value we should pass
   528 	function_name = symbol->function_name;
       
   529 
       
   530 	/* loop through each function parameter, find the value we should pass
   450      * to it, and then output the c equivalent...
   531      * to it, and then output the c equivalent...
   451      */
   532      */
   452     function_param_iterator_c fp_iterator(f_decl);
   533     function_param_iterator_c fp_iterator(f_decl);
   453   
       
   454     function_name = symbol->function_name;
       
   455   
       
   456     identifier_c *param_name;
   534     identifier_c *param_name;
   457     function_call_param_iterator_c function_call_param_iterator(symbol);
   535     function_call_param_iterator_c function_call_param_iterator(symbol);
   458     for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
   536     for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
   459       
   537       
   460       function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
   538       function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
   473       }
   551       }
   474       
   552       
   475       symbol_c *param_type = fp_iterator.param_type();
   553       symbol_c *param_type = fp_iterator.param_type();
   476       if (param_type == NULL) ERROR;
   554       if (param_type == NULL) ERROR;
   477       
   555       
   478       ADD_PARAM_LIST(param_value, param_type, param_direction)
   556       ADD_PARAM_LIST(param_name, param_value, param_type, param_direction)
   479     } /* for(...) */
   557     } /* for(...) */
   480     // symbol->parameter_assignment->accept(*this);
   558     // symbol->parameter_assignment->accept(*this);
   481   }
   559   }
   482   
   560   
       
   561   bool has_output_params = false;
       
   562 
       
   563   if (!this->is_variable_prefix_null()) {
       
   564     PARAM_LIST_ITERATOR() {
       
   565 	  if ((PARAM_DIRECTION == function_param_iterator_c::direction_out ||
       
   566 		   PARAM_DIRECTION == function_param_iterator_c::direction_inout) &&
       
   567 		  PARAM_VALUE != NULL) {
       
   568 	    if (!has_output_params) {
       
   569 		  has_output_params = true;
       
   570 		}
       
   571 	  }
       
   572     }
       
   573   }
       
   574 
   483   if (function_type_prefix != NULL) {
   575   if (function_type_prefix != NULL) {
   484     s4o.print("(");
   576     s4o.print("(");
   485     function_type_prefix->accept(*this);
   577     function_type_prefix->accept(*this);
   486     s4o.print(")");
   578     s4o.print(")");
   487   }
   579   }
   488   if (function_name != NULL)
   580   if (has_output_params) {
       
   581 	fcall_number++;
       
   582 	s4o.print("__");
       
   583     fbname->accept(*this);
       
   584     s4o.print("_");
   489     function_name->accept(*this);
   585     function_name->accept(*this);
   490   if (function_type_suffix != NULL)
   586     s4o.print_integer(fcall_number);
   491     function_type_suffix->accept(*this);
   587   }
       
   588   else {
       
   589     function_name->accept(*this);
       
   590     if (function_type_suffix != NULL)
       
   591       function_type_suffix->accept(*this);
       
   592   }
   492   s4o.print("(");
   593   s4o.print("(");
   493   s4o.indent_right();
   594   s4o.indent_right();
   494   
   595   
   495   std::list<FUNCTION_PARAM>::iterator pt;
   596   int nb_param = 0;
   496   for(pt = param_list.begin(); pt != param_list.end(); pt++) {
   597   PARAM_LIST_ITERATOR() {
   497     if (pt != param_list.begin())
   598     symbol_c *param_value = PARAM_VALUE;
   498       s4o.print(",\n"+s4o.indent_spaces);
   599     symbol_c *param_type = PARAM_TYPE;
   499     symbol_c *param_value = pt->param_value;
       
   500     symbol_c *param_type = pt->param_type;
       
   501           
   600           
   502     switch (pt->param_direction) {
   601     switch (PARAM_DIRECTION) {
   503       case function_param_iterator_c::direction_in:
   602       case function_param_iterator_c::direction_in:
   504         if (param_value == NULL) {
   603     	if (nb_param > 0)
       
   604     	  s4o.print(",\n"+s4o.indent_spaces);
       
   605     	if (param_value == NULL) {
   505           /* If not, get the default value of this variable's type */
   606           /* If not, get the default value of this variable's type */
   506           param_value = (symbol_c *)param_type->accept(*type_initial_value_c::instance());
   607           param_value = (symbol_c *)param_type->accept(*type_initial_value_c::instance());
   507         }
   608         }
   508         if (param_value == NULL) ERROR;
   609         if (param_value == NULL) ERROR;
   509         s4o.print("(");
   610         s4o.print("(");
   513         	function_type_suffix->accept(*this);
   614         	function_type_suffix->accept(*this);
   514         }
   615         }
   515         else
   616         else
   516         	param_type->accept(*this);
   617         	param_type->accept(*this);
   517         s4o.print(")");
   618         s4o.print(")");
   518         if (search_base_type.type_is_subrange(param_type)) {
   619         print_check_function(param_type, param_value);
   519           s4o.print("__CHECK_");
   620         nb_param++;
   520           param_type->accept(*this);
       
   521           s4o.print("(");
       
   522         }
       
   523         param_value->accept(*this);
       
   524         if (search_base_type.type_is_subrange(param_type))
       
   525           s4o.print(")");
       
   526         break;
   621         break;
   527       case function_param_iterator_c::direction_out:
   622       case function_param_iterator_c::direction_out:
   528       case function_param_iterator_c::direction_inout:
   623       case function_param_iterator_c::direction_inout:
   529         current_param_is_pointer = true;
   624     	if (!has_output_params) {
   530         if (param_value == NULL) {
   625           if (nb_param > 0)
   531           s4o.print("NULL");
   626         	s4o.print(",\n"+s4o.indent_spaces);
   532         } else {
   627     	  if (param_value == NULL)
   533           param_value->accept(*this);
   628             s4o.print("NULL");
   534         }
   629           else {
   535         current_param_is_pointer = false;
   630             wanted_variablegeneration = fparam_output_vg;
       
   631             param_value->accept(*this);
       
   632             wanted_variablegeneration = expression_vg;
       
   633           }
       
   634     	  nb_param++;
       
   635     	}
   536         break;
   636         break;
   537       case function_param_iterator_c::direction_extref:
   637       case function_param_iterator_c::direction_extref:
   538         /* TODO! */
   638         /* TODO! */
   539         ERROR;
   639         ERROR;
   540         break;
   640         break;
   541     } /* switch */
   641     } /* switch */
   542   }  
   642   }
   543   
   643   if (has_output_params) {
       
   644     if (nb_param > 0)
       
   645       s4o.print(",\n"+s4o.indent_spaces);
       
   646     s4o.print(FB_FUNCTION_PARAM);
       
   647   }
   544   s4o.print(")");
   648   s4o.print(")");
   545   s4o.indent_left();
   649   s4o.indent_left();
       
   650 
       
   651   CLEAR_PARAM_LIST()
   546 
   652 
   547   return NULL;
   653   return NULL;
   548 }
   654 }
   549 
   655 
   550 /********************/
   656 /********************/
   558 /* B 3.2.1 Assignment Statements */
   664 /* B 3.2.1 Assignment Statements */
   559 /*********************************/
   665 /*********************************/
   560 void *visit(assignment_statement_c *symbol) {
   666 void *visit(assignment_statement_c *symbol) {
   561   symbol_c *left_type = search_varfb_instance_type->get_type(symbol->l_exp, false);
   667   symbol_c *left_type = search_varfb_instance_type->get_type(symbol->l_exp, false);
   562   
   668   
   563   symbol->l_exp->accept(*this);
   669   if (!this->is_variable_prefix_null()) {
   564   s4o.print(" = ");
   670     unsigned int vartype = search_varfb_instance_type->get_vartype(symbol->l_exp);
   565   if (search_base_type.type_is_subrange(left_type)) {
   671     if (vartype == search_var_instance_decl_c::external_vt)
   566     s4o.print("__CHECK_");
   672 	  s4o.print(SET_EXTERNAL);
   567     left_type->accept(*this);
   673     else if (vartype == search_var_instance_decl_c::located_vt)
       
   674 	  s4o.print(SET_LOCATED);
       
   675     else
       
   676 	  s4o.print(SET_VAR);
   568     s4o.print("(");
   677     s4o.print("(");
   569   }
   678 
   570   symbol->r_exp->accept(*this);
   679     wanted_variablegeneration = assignment_vg;
   571   if (search_base_type.type_is_subrange(left_type))
   680     symbol->l_exp->accept(*this);
       
   681     wanted_variablegeneration = expression_vg;
       
   682 
       
   683     s4o.print(",");
       
   684   }
       
   685   else {
       
   686 	symbol->l_exp->accept(*this);
       
   687 
       
   688     s4o.print(" = ");
       
   689   }
       
   690   print_check_function(left_type, symbol->r_exp);
       
   691   if (!this->is_variable_prefix_null())
   572     s4o.print(")");
   692     s4o.print(")");
   573   return NULL;
   693   return NULL;
   574 }
   694 }
   575 
   695 
   576 /*****************************************/
   696 /*****************************************/
   615     
   735     
   616     /* now output the value assignment */
   736     /* now output the value assignment */
   617     if (param_value != NULL)
   737     if (param_value != NULL)
   618       if ((param_direction == function_param_iterator_c::direction_in) ||
   738       if ((param_direction == function_param_iterator_c::direction_in) ||
   619           (param_direction == function_param_iterator_c::direction_inout)) {
   739           (param_direction == function_param_iterator_c::direction_inout)) {
   620         print_variable_prefix();
   740         if (!this->is_variable_prefix_null()) {
       
   741           s4o.print(SET_VAR);
       
   742           s4o.print("(");
       
   743         }
       
   744     	print_variable_prefix();
   621         symbol->fb_name->accept(*this);
   745         symbol->fb_name->accept(*this);
   622         s4o.print(".");
   746         s4o.print(".");
   623         param_name->accept(*this);
   747         param_name->accept(*this);
   624         s4o.print(" = ");
   748         if (this->is_variable_prefix_null())
   625         if (search_base_type.type_is_subrange(param_type)) {
   749           s4o.print(" = ");
   626           s4o.print("__CHECK_");
   750         else
   627           param_type->accept(*this);
   751           s4o.print(",");
   628           s4o.print("(");
   752         print_check_function(param_type, param_value);
   629         }
   753         if (!this->is_variable_prefix_null())
   630         param_value->accept(*this);
       
   631         if (search_base_type.type_is_subrange(param_type))
       
   632           s4o.print(")");
   754           s4o.print(")");
   633         s4o.print(";\n" + s4o.indent_spaces);
   755         s4o.print(";\n" + s4o.indent_spaces);
   634       }
   756       }
   635   } /* for(...) */
   757   } /* for(...) */
   636 
   758 
   660     /* now output the value assignment */
   782     /* now output the value assignment */
   661     if (param_value != NULL)
   783     if (param_value != NULL)
   662       if ((param_direction == function_param_iterator_c::direction_out) ||
   784       if ((param_direction == function_param_iterator_c::direction_out) ||
   663           (param_direction == function_param_iterator_c::direction_inout)) {
   785           (param_direction == function_param_iterator_c::direction_inout)) {
   664         symbol_c *param_type = search_varfb_instance_type->get_type(param_value, false);
   786         symbol_c *param_type = search_varfb_instance_type->get_type(param_value, false);
   665         
   787 
   666         s4o.print(";\n"+ s4o.indent_spaces);
   788         if (!this->is_variable_prefix_null()) {
   667         param_value->accept(*this);
   789           unsigned int vartype = search_varfb_instance_type->get_vartype(param_value);
   668         s4o.print(" = ");
   790           s4o.print(";\n"+ s4o.indent_spaces);
   669         if (search_base_type.type_is_subrange(param_type)) {
   791           if (vartype == search_var_instance_decl_c::external_vt)
   670           s4o.print("__CHECK_");
   792             s4o.print(SET_EXTERNAL);
   671           param_type->accept(*this);
   793           else if (vartype == search_var_instance_decl_c::located_vt)
       
   794             s4o.print(SET_LOCATED);
       
   795           else
       
   796             s4o.print(SET_VAR);
   672           s4o.print("(");
   797           s4o.print("(");
       
   798 
       
   799           wanted_variablegeneration = assignment_vg;
       
   800           param_value->accept(*this);
       
   801           wanted_variablegeneration = expression_vg;
       
   802           s4o.print(",");
   673         }
   803         }
   674         print_variable_prefix();
   804         else {
   675         symbol->fb_name->accept(*this);
   805           param_value->accept(*this);
   676         s4o.print(".");
   806           s4o.print(" = ");
   677         param_name->accept(*this);
   807         }
   678         if (search_base_type.type_is_subrange(param_type))
   808         print_check_function(param_type, param_name, symbol->fb_name);
       
   809         if (!this->is_variable_prefix_null())
   679           s4o.print(")");
   810           s4o.print(")");
   680       }
   811       }
   681   } /* for(...) */
   812   } /* for(...) */
   682 
   813 
   683   return NULL;
   814   return NULL;