stage4/generate_c/generate_c.cc
changeset 625 c0bda77b37a0
parent 412 aad38592bdde
parent 624 c2546c6e0cfa
child 631 1a4f5ce62962
equal deleted inserted replaced
412:aad38592bdde 625:c0bda77b37a0
    29 #include <list>
    29 #include <list>
    30 #include <map>
    30 #include <map>
    31 #include <sstream>
    31 #include <sstream>
    32 #include <strings.h>
    32 #include <strings.h>
    33 
    33 
       
    34 
    34 #include "../../util/symtable.hh"
    35 #include "../../util/symtable.hh"
    35 #include "../../util/dsymtable.hh"
    36 #include "../../util/dsymtable.hh"
    36 #include "../../absyntax/visitor.hh"
    37 #include "../../absyntax/visitor.hh"
    37 #include "../../absyntax_utils/absyntax_utils.hh"
    38 #include "../../absyntax_utils/absyntax_utils.hh"
       
    39 #include "../../main.hh" // required for ERROR() and ERROR_MSG() macros.
    38 
    40 
    39 #include "../stage4.hh"
    41 #include "../stage4.hh"
    40 
    42 
    41 //#define DEBUG
    43 //#define DEBUG
    42 #ifdef DEBUG
    44 #ifdef DEBUG
    43 #define TRACE(classname) printf("\n____%s____\n",classname);
    45 #define TRACE(classname) printf("\n____%s____\n",classname);
    44 #else
    46 #else
    45 #define TRACE(classname)
    47 #define TRACE(classname)
    46 #endif
    48 #endif
    47 
    49 
    48 #define ERROR error_exit(__FILE__,__LINE__)
    50 
    49 /* function defined in main.cc */
    51 
    50 extern void error_exit(const char *file_name, int line_no);
    52 #define STAGE4_ERROR(symbol1, symbol2, ...) {stage4err("while generating C code", symbol1, symbol2, __VA_ARGS__); exit(EXIT_FAILURE);}
       
    53 
       
    54 
       
    55 /* Macros to access the constant value of each expression (if it exists) from the annotation introduced to the symbol_c object by constant_folding_c in stage3! */
       
    56 #define VALID_CVALUE(dtype, symbol)           (symbol_c::cs_const_value == (symbol)->const_value._##dtype.status)
       
    57 #define GET_CVALUE(dtype, symbol)             ((symbol)->const_value._##dtype.value) 
       
    58 
       
    59 
    51 
    60 
    52 /***********************************************************************/
    61 /***********************************************************************/
    53 
    62 
    54 /* Unlike Programs and Configurations which get mapped onto C++ classes,
    63 /* Unlike Programs and Configurations which get mapped onto C++ classes,
    55  * Function Blocks are mapped onto a C structure containing the variables, and
    64  * Function Blocks are mapped onto a C structure containing the variables, and
   195         }  
   204         }  
   196       }
   205       }
   197     }
   206     }
   198     
   207     
   199   public:
   208   public:
   200     print_function_parameter_data_types_c(stage4out_c *s4o_ptr):
   209     print_function_parameter_data_types_c(stage4out_c *s4o_ptr): 
   201       generate_c_base_c(s4o_ptr) {
   210       generate_c_base_c(s4o_ptr)
   202     	current_type = NULL;
   211       {current_type = NULL;}
   203       }
       
   204 
   212 
   205     /**************************************/
   213     /**************************************/
   206     /* B.1.5 - Program organization units */
   214     /* B.1.5 - Program organization units */
   207     /**************************************/
   215     /**************************************/
   208     /***********************/
   216     /***********************/
   209     /* B 1.5.1 - Functions */
   217     /* B 1.5.1 - Functions */
   210     /***********************/
   218     /***********************/
   211     /*   FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
   219     /*   FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
   212     /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
   220     /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
   213     void *visit(function_declaration_c *symbol) {
   221     void *visit(function_declaration_c *symbol) {
   214       /* return type */
   222       symbol->type_name->accept(*this); /* return type */
   215       symbol->type_name->accept(*this);
       
   216       symbol->var_declarations_list->accept(*this);
   223       symbol->var_declarations_list->accept(*this);
   217       return NULL;
   224       return NULL;
   218     }
   225     }
   219 
   226 
   220     /* already handled by iterator base class (note that generate_c_base_c inherits from iterator_c) */
   227     /* already handled by iterator base class (note that generate_c_base_c inherits from iterator_c) */
   337 /***********************************************************************/
   344 /***********************************************************************/
   338 
   345 
   339 #define MILLISECOND 1000000
   346 #define MILLISECOND 1000000
   340 #define SECOND 1000 * MILLISECOND
   347 #define SECOND 1000 * MILLISECOND
   341 
   348 
   342 /* A helper class that knows how to generate code for both the IL and ST languages... */
   349 unsigned long long calculate_time(symbol_c *symbol) {
   343 class calculate_time_c: public iterator_visitor_c {
   350   if (NULL == symbol) return 0;
   344   private:
       
   345     unsigned long long time;
       
   346     float current_value;
       
   347   
   351   
   348   public:
   352   interval_c *interval = dynamic_cast<interval_c *>(symbol);
   349     calculate_time_c(void){time = 0;};
   353   duration_c *duration = dynamic_cast<duration_c *>(symbol);
   350     
       
   351     unsigned long long get_time(void) {return time;};
       
   352 
       
   353     void *get_integer_value(token_c *token) {
       
   354       std::string str = "";
       
   355       for (unsigned int i = 0; i < strlen(token->value); i++)
       
   356         if (token->value[i] != '_')
       
   357           str += token->value[i];
       
   358       current_value = atof(str.c_str());
       
   359       return NULL;
       
   360     }
       
   361 
       
   362     void *get_float_value(token_c *token) {
       
   363       current_value = atof(token->value);
       
   364       return NULL;
       
   365     }
       
   366 
       
   367 /******************************/
       
   368 /* B 1.2.1 - Numeric Literals */
       
   369 /******************************/
       
   370 
       
   371     void *visit(integer_c *symbol) {return get_integer_value(symbol);}
       
   372     
       
   373 /************************/
       
   374 /* B 1.2.3.1 - Duration */
       
   375 /************************/
       
   376   
   354   
       
   355   if ((NULL == interval) && (NULL == duration)) ERROR;
       
   356 
       
   357   if (NULL != duration) {
   377     /* SYM_REF2(duration_c, neg, interval) */
   358     /* SYM_REF2(duration_c, neg, interval) */
   378     void *visit(duration_c *symbol) {
   359     if (duration->neg != NULL)
   379       if (symbol->neg != NULL)
   360       {STAGE4_ERROR(duration, duration, "Negative TIME literals are not currently supported"); ERROR;}
   380         ERROR;
   361     return calculate_time(duration->interval);
   381       symbol->interval->accept(*this);
   362   }
   382       return NULL;
   363 
   383     }
   364   if (NULL != interval) {
   384     
   365     /* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */
   385     /* SYM_TOKEN(fixed_point_c) */
   366       unsigned long long int time_ull = 0; 
   386     void *visit(fixed_point_c *symbol) {return get_float_value(symbol);}
   367       long double            time_ld  = 0;
   387     
   368       /*
   388     /* SYM_REF2(days_c, days, hours) */
   369       const unsigned long long int MILLISECOND = 1000000;
   389     void *visit(days_c *symbol) {
   370       const unsigned long long int      SECOND = 1000 * MILLISECOND
   390       if (symbol->hours)
   371       */
   391         symbol->hours->accept(*this);
   372       
   392       symbol->days->accept(*this);
   373       if (NULL != interval->milliseconds) {
   393       time += (unsigned long long)(current_value * 24 * 3600 * SECOND);
   374         if      (VALID_CVALUE( int64, interval->milliseconds) &&           GET_CVALUE( int64, interval->milliseconds) < 0) ERROR; // interval elements should always be positive!
   394       return NULL;
   375         if      (VALID_CVALUE( int64, interval->milliseconds)) time_ull += GET_CVALUE( int64, interval->milliseconds) * MILLISECOND;
   395     }
   376         else if (VALID_CVALUE(uint64, interval->milliseconds)) time_ull += GET_CVALUE(uint64, interval->milliseconds) * MILLISECOND;
   396     
   377         else if (VALID_CVALUE(real64, interval->milliseconds)) time_ld  += GET_CVALUE(real64, interval->milliseconds) * MILLISECOND;
   397     /* SYM_REF2(hours_c, hours, minutes) */
   378         else ERROR; // if (NULL != interval->milliseconds) is true, then it must have a valid constant value!
   398     void *visit(hours_c *symbol) {
   379       }
   399       if (symbol->minutes)
   380    
   400         symbol->minutes->accept(*this);
   381       if (NULL != interval->seconds     ) {
   401       symbol->hours->accept(*this);
   382         if      (VALID_CVALUE( int64, interval->seconds     ) &&           GET_CVALUE( int64, interval->seconds     ) < 0) ERROR; // interval elements should always be positive!
   402       time += (unsigned long long)(current_value * 3600 * SECOND);
   383         if      (VALID_CVALUE( int64, interval->seconds     )) time_ull += GET_CVALUE( int64, interval->seconds     ) * SECOND;
   403       return NULL;
   384         else if (VALID_CVALUE(uint64, interval->seconds     )) time_ull += GET_CVALUE(uint64, interval->seconds     ) * SECOND;
   404     }
   385         else if (VALID_CVALUE(real64, interval->seconds     )) time_ld  += GET_CVALUE(real64, interval->seconds     ) * SECOND;
   405     
   386         else ERROR; // if (NULL != interval->seconds) is true, then it must have a valid constant value!
   406     /* SYM_REF2(minutes_c, minutes, seconds) */
   387       }
   407     void *visit(minutes_c *symbol) {
   388 
   408       if (symbol->seconds)
   389       if (NULL != interval->minutes     ) {
   409         symbol->seconds->accept(*this);
   390         if      (VALID_CVALUE( int64, interval->minutes     ) &&           GET_CVALUE( int64, interval->minutes     ) < 0) ERROR; // interval elements should always be positive!
   410       symbol->minutes->accept(*this);
   391         if      (VALID_CVALUE( int64, interval->minutes     )) time_ull += GET_CVALUE( int64, interval->minutes     ) * SECOND * 60;
   411       time += (unsigned long long)(current_value * 60 * SECOND);
   392         else if (VALID_CVALUE(uint64, interval->minutes     )) time_ull += GET_CVALUE(uint64, interval->minutes     ) * SECOND * 60;
   412       return NULL;
   393         else if (VALID_CVALUE(real64, interval->minutes     )) time_ld  += GET_CVALUE(real64, interval->minutes     ) * SECOND * 60;
   413     }
   394         else ERROR; // if (NULL != interval->minutes) is true, then it must have a valid constant value!
   414     
   395       }
   415     /* SYM_REF2(seconds_c, seconds, milliseconds) */
   396 
   416     void *visit(seconds_c *symbol) {
   397       if (NULL != interval->hours       ) {
   417       if (symbol->milliseconds)
   398         if      (VALID_CVALUE( int64, interval->hours       ) &&           GET_CVALUE( int64, interval->hours       ) < 0) ERROR; // interval elements should always be positive!
   418         symbol->milliseconds->accept(*this);
   399         if      (VALID_CVALUE( int64, interval->hours       )) time_ull += GET_CVALUE( int64, interval->hours       ) * SECOND * 60 * 60;
   419       symbol->seconds->accept(*this);
   400         else if (VALID_CVALUE(uint64, interval->hours       )) time_ull += GET_CVALUE(uint64, interval->hours       ) * SECOND * 60 * 60;
   420       time += (unsigned long long)(current_value * SECOND);
   401         else if (VALID_CVALUE(real64, interval->hours       )) time_ld  += GET_CVALUE(real64, interval->hours       ) * SECOND * 60 * 60;
   421       return NULL;
   402         else ERROR; // if (NULL != interval->hours) is true, then it must have a valid constant value!
   422     }
   403       }
   423     
   404 
   424     /* SYM_REF2(milliseconds_c, milliseconds, unused) */
   405       if (NULL != interval->days        ) {
   425     void *visit(milliseconds_c *symbol) {
   406         if      (VALID_CVALUE( int64, interval->days        ) &&           GET_CVALUE( int64, interval->days        ) < 0) ERROR; // interval elements should always be positive!
   426       symbol->milliseconds->accept(*this);
   407         if      (VALID_CVALUE( int64, interval->days        )) time_ull += GET_CVALUE( int64, interval->days        ) * SECOND * 60 * 60 * 24;
   427       time += (unsigned long long)(current_value * MILLISECOND);
   408         else if (VALID_CVALUE(uint64, interval->days        )) time_ull += GET_CVALUE(uint64, interval->days        ) * SECOND * 60 * 60 * 24;
   428       return NULL;
   409         else if (VALID_CVALUE(real64, interval->days        )) time_ld  += GET_CVALUE(real64, interval->days        ) * SECOND * 60 * 60 * 24;
   429     }
   410         else ERROR; // if (NULL != interval->days) is true, then it must have a valid constant value!
       
   411       }
       
   412 
       
   413       time_ull += time_ld;
       
   414       return time_ull;
       
   415   };
       
   416   ERROR; // should never reach this point!
       
   417   return 0; // humour the compiler!
   430 };
   418 };
   431 
   419 
   432 /***********************************************************************/
   420 /***********************************************************************/
   433 /***********************************************************************/
   421 /***********************************************************************/
   434 /***********************************************************************/
   422 /***********************************************************************/
   478     }
   466     }
   479 
   467 
   480 /*  TASK task_name task_initialization */
   468 /*  TASK task_name task_initialization */
   481 //SYM_REF2(task_configuration_c, task_name, task_initialization)  
   469 //SYM_REF2(task_configuration_c, task_name, task_initialization)  
   482     void *visit(task_initialization_c *symbol) {
   470     void *visit(task_initialization_c *symbol) {
   483       calculate_time_c calculate_time;
   471       unsigned long long time = calculate_time(symbol->interval_data_source);
   484       unsigned long long time = 0;
   472       if (time < 0)  ERROR;
   485       if (symbol->interval_data_source != NULL) {
   473       else           update_ticktime(time);
   486         symbol->interval_data_source->accept(calculate_time);
       
   487         time = calculate_time.get_time();
       
   488       }
       
   489       if (time > 0)
       
   490         update_ticktime(time);
       
   491       return NULL;
   474       return NULL;
   492     }
   475     }
   493 };    
   476 };    
   494 
   477 
   495 /***********************************************************************/
   478 /***********************************************************************/
   786     }
   769     }
   787 
   770 
   788     /*  signed_integer DOTDOT signed_integer */
   771     /*  signed_integer DOTDOT signed_integer */
   789     //SYM_REF2(subrange_c, lower_limit, upper_limit)
   772     //SYM_REF2(subrange_c, lower_limit, upper_limit)
   790     void *visit(subrange_c *symbol) {
   773     void *visit(subrange_c *symbol) {
   791       int dimension = extract_integer(symbol->upper_limit) - extract_integer(symbol->lower_limit) + 1;
       
   792       switch (current_mode) {
   774       switch (current_mode) {
   793         case arrayname_im:
   775         case arrayname_im:
   794           current_array_name += "_";
   776           current_array_name += "_";
   795           {
   777           {
   796             std::stringstream ss;
   778             std::stringstream ss;
   797             ss << dimension;
   779             ss << symbol->dimension;
   798             current_array_name += ss.str();
   780             current_array_name += ss.str();
   799           }
   781           }
   800           break;
   782           break;
   801         case arraydeclaration_im:
   783         case arraydeclaration_im:
   802           s4o_incl.print("[");
   784           s4o_incl.print("[");
   803           s4o_incl.print_integer(dimension);
   785           s4o_incl.print(symbol->dimension);
   804           s4o_incl.print("]");
   786           s4o_incl.print("]");
   805         default:
   787         default:
   806           generate_c_typedecl_c::visit(symbol);
   788           generate_c_typedecl_c::visit(symbol);
   807           break;
   789           break;
   808       }
   790       }
   809       return NULL;
   791       return NULL;
   810     }
   792     }
   811 
       
   812     /*  var1_list ':' structure_type_name */
       
   813 	void *visit(structured_var_declaration_c *symbol) {
       
   814 	  return NULL;
       
   815 	}
       
   816 
   793 
   817     /*  var1_list ':' initialized_structure */
   794     /*  var1_list ':' initialized_structure */
   818     // SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure)
   795     // SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure)
   819     void *visit(structured_var_init_decl_c *symbol) {
   796     void *visit(structured_var_init_decl_c *symbol) {
   820       return NULL;
   797       return NULL;
   846 	  if (specification != NULL) {
   823 	  if (specification != NULL) {
   847         current_mode = arrayname_im;
   824         current_mode = arrayname_im;
   848         symbol->array_specification->accept(*this);
   825         symbol->array_specification->accept(*this);
   849         current_mode = none_im;
   826         current_mode = none_im;
   850       }
   827       }
       
   828       return NULL;
       
   829     }
       
   830 
       
   831     /*  var1_list ':' structure_type_name */
       
   832     //SYM_REF2(structured_var_declaration_c, var1_list, structure_type_name)
       
   833     void *visit(structured_var_declaration_c *symbol) {
   851       return NULL;
   834       return NULL;
   852     }
   835     }
   853 
   836 
   854     /* VAR [CONSTANT] var_init_decl_list END_VAR */
   837     /* VAR [CONSTANT] var_init_decl_list END_VAR */
   855     /* option -> may be NULL ! */
   838     /* option -> may be NULL ! */
  1674   
  1657   
  1675   /* (B.3) Global variables initializations... */
  1658   /* (B.3) Global variables initializations... */
  1676   s4o.print(s4o.indent_spaces);
  1659   s4o.print(s4o.indent_spaces);
  1677   vardecl = new generate_c_vardecl_c(&s4o,
  1660   vardecl = new generate_c_vardecl_c(&s4o,
  1678                                      generate_c_vardecl_c::constructorinit_vf,
  1661                                      generate_c_vardecl_c::constructorinit_vf,
  1679                                      generate_c_vardecl_c::global_vt);
  1662                                      generate_c_vardecl_c::global_vt,
       
  1663                                      symbol->configuration_name);
  1680   vardecl->print(symbol);
  1664   vardecl->print(symbol);
  1681   delete vardecl;
  1665   delete vardecl;
  1682   s4o.print("\n");
  1666   s4o.print("\n");
  1683   
  1667   
  1684   /* (B.3) Resources initializations... */
  1668   /* (B.3) Resources initializations... */
  1817       run_dt
  1801       run_dt
  1818     } declaretype_t;
  1802     } declaretype_t;
  1819 
  1803 
  1820     declaretype_t wanted_declaretype;
  1804     declaretype_t wanted_declaretype;
  1821 
  1805 
  1822     unsigned long common_ticktime;
  1806     unsigned long long common_ticktime;
  1823     
  1807     
  1824     const char *current_program_name;
  1808     const char *current_program_name;
  1825 
  1809 
  1826     typedef enum {
  1810     typedef enum {
  1827       assign_at,
  1811       assign_at,
  2194           else {
  2178           else {
  2195             s4o.print(s4o.indent_spaces);
  2179             s4o.print(s4o.indent_spaces);
  2196             current_task_name->accept(*this);
  2180             current_task_name->accept(*this);
  2197             s4o.print(" = ");
  2181             s4o.print(" = ");
  2198             if (symbol->interval_data_source != NULL) {
  2182             if (symbol->interval_data_source != NULL) {
  2199               calculate_time_c calculate_time;
  2183               unsigned long long int time = calculate_time(symbol->interval_data_source);
  2200               symbol->interval_data_source->accept(calculate_time);
       
  2201               unsigned long time = calculate_time.get_time();
       
  2202               if (time != 0) {
  2184               if (time != 0) {
  2203                 s4o.print("!(tick % ");
  2185                 s4o.print("!(tick % ");
  2204                 s4o.print_integer((int)(time / common_ticktime));
  2186                 s4o.print(time / common_ticktime);
  2205                 s4o.print(")");
  2187                 s4o.print(")");
  2206               }
  2188               }
  2207               else
  2189               else
  2208                 s4o.print("1");
  2190                 s4o.print("1");
  2209             }
  2191             }
  2229         if (var_decl == NULL) {
  2211         if (var_decl == NULL) {
  2230           var_decl = search_config_instance->get_decl(current_var_reference);
  2212           var_decl = search_config_instance->get_decl(current_var_reference);
  2231           if (var_decl == NULL)
  2213           if (var_decl == NULL)
  2232             ERROR;
  2214             ERROR;
  2233           else
  2215           else
  2234             vartype = search_config_instance->get_vartype();
  2216             vartype = search_config_instance->get_vartype(current_var_reference);
  2235         }
  2217         }
  2236         else
  2218         else
  2237           vartype = search_resource_instance->get_vartype();
  2219           vartype = search_resource_instance->get_vartype(current_var_reference);
  2238         
  2220         
  2239         s4o.print(s4o.indent_spaces + "{extern ");
  2221         s4o.print(s4o.indent_spaces + "{extern ");
  2240         var_decl->accept(*this);
  2222         var_decl->accept(*this);
  2241         s4o.print(" *");
  2223         s4o.print(" *");
  2242         symbol->prog_data_source->accept(*this);
  2224         symbol->prog_data_source->accept(*this);
  2243         s4o.print("; ");
  2225         s4o.print("; ");
  2244         s4o.printupper(current_program_name);
  2226         s4o.printupper(current_program_name);
  2245         s4o.print(".");
  2227         s4o.print(".");
  2246         symbol->symbolic_variable->accept(*this);
  2228         symbol->symbolic_variable->accept(*this);
  2247         s4o.print(" = ");
  2229         s4o.print(" = ");
  2248         if (vartype || search_var_instance_decl_c::global_vt)
  2230         if (vartype == search_var_instance_decl_c::global_vt)
  2249           s4o.print("*");
  2231           s4o.print("*");
  2250         symbol->prog_data_source->accept(*this);
  2232         symbol->prog_data_source->accept(*this);
  2251         s4o.print(";}\n");
  2233         s4o.print(";}\n");
  2252       }
  2234       }
  2253       return NULL;
  2235       return NULL;
  2264         if (var_decl == NULL) {
  2246         if (var_decl == NULL) {
  2265           var_decl = search_config_instance->get_decl(current_var_reference);
  2247           var_decl = search_config_instance->get_decl(current_var_reference);
  2266           if (var_decl == NULL)
  2248           if (var_decl == NULL)
  2267             ERROR;
  2249             ERROR;
  2268           else
  2250           else
  2269             vartype = search_config_instance->get_vartype();
  2251             vartype = search_config_instance->get_vartype(current_var_reference);
  2270         }
  2252         }
  2271         else
  2253         else
  2272           vartype = search_resource_instance->get_vartype();
  2254           vartype = search_resource_instance->get_vartype(current_var_reference);
  2273         
  2255         
  2274         s4o.print(s4o.indent_spaces + "{extern ");
  2256         s4o.print(s4o.indent_spaces + "{extern ");
  2275         var_decl->accept(*this);
  2257         var_decl->accept(*this);
  2276         s4o.print(" *");
  2258         s4o.print(" *");
  2277         symbol->data_sink->accept(*this);
  2259         symbol->data_sink->accept(*this);
  2278         s4o.print("; ");
  2260         s4o.print("; ");
  2279         if (vartype || search_var_instance_decl_c::global_vt)
  2261         if (vartype == search_var_instance_decl_c::global_vt)
  2280           s4o.print("*");
  2262           s4o.print("*");
  2281         symbol->data_sink->accept(*this);
  2263         symbol->data_sink->accept(*this);
  2282         s4o.print(" = ");
  2264         s4o.print(" = ");
  2283         s4o.printupper(current_program_name);
  2265         s4o.printupper(current_program_name);
  2284         s4o.print(".");
  2266         s4o.print(".");
  2489         case pous_gm:
  2471         case pous_gm:
  2490           static int configuration_count = 0;
  2472           static int configuration_count = 0;
  2491 
  2473 
  2492           if (configuration_count++) {
  2474           if (configuration_count++) {
  2493             /* the first configuration is the one we will use!! */
  2475             /* the first configuration is the one we will use!! */
       
  2476             STAGE4_ERROR(symbol, symbol, "A previous CONFIGURATION has already been declared (C code generation currently only allows a single configuration).");
  2494             ERROR;
  2477             ERROR;
  2495           }
  2478           }
  2496 
  2479 
  2497           current_configuration = symbol;
  2480           current_configuration = symbol;
  2498 
  2481 
  2499           {
  2482           {
  2500             calculate_common_ticktime_c calculate_common_ticktime;
  2483             calculate_common_ticktime_c calculate_common_ticktime;
  2501             symbol->accept(calculate_common_ticktime);
  2484             symbol->accept(calculate_common_ticktime);
  2502             common_ticktime = calculate_common_ticktime.get_common_ticktime();
  2485             common_ticktime = calculate_common_ticktime.get_common_ticktime();
  2503             if (common_ticktime == 0) {
  2486             if (common_ticktime == 0) {
  2504               fprintf(stderr, "\nYou must at least define a periodic task to set cycle period!");
  2487               STAGE4_ERROR(symbol, symbol, "You must define at least one periodic task (to set cycle period)!");
  2505               ERROR;
  2488               ERROR;
  2506             }
  2489             }
  2507 
  2490 
  2508             symbol->configuration_name->accept(*this);
  2491             symbol->configuration_name->accept(*this);
  2509             
  2492