stage4/generate_c/generate_c.cc
changeset 70 e1f0ebd2d9ec
child 98 d0cdf1d00b74
equal deleted inserted replaced
69:41cb5b80416e 70:e1f0ebd2d9ec
       
     1 /*
       
     2  * (c) 2003 Mario de Sousa
       
     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 /*
       
    27  * This is one of the versions available for the 4th stage.
       
    28  *
       
    29  * This 4th stage generates a c++ source program equivalent
       
    30  * to the IL and ST code.
       
    31  */
       
    32 
       
    33 
       
    34 
       
    35 
       
    36 
       
    37 
       
    38 // #include <stdio.h>  /* required for NULL */
       
    39 #include <string>
       
    40 #include <iostream>
       
    41 #include <sstream>
       
    42 #include <typeinfo>
       
    43 
       
    44 #include "../../util/symtable.hh"
       
    45 #include "../../util/dsymtable.hh"
       
    46 #include "../../absyntax/visitor.hh"
       
    47 
       
    48 #include "../stage4.hh"
       
    49 
       
    50 
       
    51 
       
    52 
       
    53 
       
    54 
       
    55 
       
    56 
       
    57 //#define DEBUG
       
    58 #ifdef DEBUG
       
    59 #define TRACE(classname) printf("\n____%s____\n",classname);
       
    60 #else
       
    61 #define TRACE(classname)
       
    62 #endif
       
    63 
       
    64 
       
    65 
       
    66 #define ERROR error_exit(__FILE__,__LINE__)
       
    67 /* function defined in main.cc */
       
    68 extern void error_exit(const char *file_name, int line_no);
       
    69 
       
    70 
       
    71 
       
    72 
       
    73 
       
    74 
       
    75 
       
    76 /* A symbol table with all globally declared functions... */
       
    77 function_declaration_c null_symbol1(NULL,NULL,NULL,NULL);
       
    78 dsymtable_c<function_declaration_c *, &null_symbol1> function_symtable;
       
    79 
       
    80 /* A symbol table with all globally declared functions block types... */
       
    81 function_block_declaration_c null_symbol2(NULL,NULL,NULL);
       
    82 symtable_c<function_block_declaration_c *, &null_symbol2> function_block_type_symtable;
       
    83 
       
    84 /* A symbol table with all globally declared program types... */
       
    85 program_declaration_c null_symbol3(NULL,NULL,NULL);
       
    86 symtable_c<program_declaration_c *, &null_symbol3> program_type_symtable;
       
    87 
       
    88 /* A symbol table with all user declared type definitions... */
       
    89 /* Note that function block types and program types have their
       
    90  * own symbol tables, so do not get placed in this symbol table!
       
    91  */
       
    92 symbol_c null_symbol4;
       
    93 symtable_c<symbol_c *, &null_symbol4> type_symtable;
       
    94 
       
    95 
       
    96 
       
    97 /***********************************************************************/
       
    98 /***********************************************************************/
       
    99 /***********************************************************************/
       
   100 /***********************************************************************/
       
   101 
       
   102 
       
   103 /* returns 0 if the names are equal!! */
       
   104 /* NOTE: it must ignore case!! */
       
   105 static int compare_identifiers(symbol_c *ident1, symbol_c *ident2) {
       
   106 
       
   107   token_c *name1 = dynamic_cast<token_c *>(ident1);
       
   108   token_c *name2 = dynamic_cast<token_c *>(ident2);
       
   109   
       
   110   if ((name1 == NULL) || (name2 == NULL))
       
   111     /* invalid identifiers... */
       
   112     return -1;
       
   113 
       
   114   if (strcasecmp(name1->value, name2->value) == 0)
       
   115     return 0;
       
   116 
       
   117   /* identifiers do not match! */
       
   118   return 1;
       
   119 }
       
   120 
       
   121 
       
   122 /***********************************************************************/
       
   123 /***********************************************************************/
       
   124 /***********************************************************************/
       
   125 /***********************************************************************/
       
   126 
       
   127 /* Unlike Programs and Configurations which get mapped onto C++ classes,
       
   128  * Function Blocks are mapped onto a C structure containing the variables, and
       
   129  * a C function containing the code in the FB's body. This is to allow direct allocation
       
   130  * of a FB variable (which is really an instance of the C data structure) to
       
   131  * a member of a union variable (note that classes with constructors cannot
       
   132  * be mebers of a union), which is done in IL when loading a FB onto IL's
       
   133  * default variable.
       
   134  *
       
   135  * So as not to clash the names of the C data structure and the C function,
       
   136  * the C structure is given a name identical to that of the FB name, whereas
       
   137  * the name of the function is the FB name with a constant string appended.
       
   138  * The value of that constant string which is appended is defined in the following
       
   139  * constant.
       
   140  * In order not to clash with any variable in the IL and ST source codem the
       
   141  * following constant should contain a double underscore, which is not allowed
       
   142  * in IL and ST.
       
   143  *
       
   144  * e.g.:  FUNTION_BLOCK TEST
       
   145  * is mapped onto a TEST data structure, and a TEST_body__ function.
       
   146  */
       
   147 
       
   148 #define FB_FUNCTION_SUFFIX "_body__"
       
   149 
       
   150 /* Idem as body, but for initializer FB function */
       
   151 #define FB_INIT_SUFFIX "_init__"
       
   152 
       
   153 /* Idem as body, but for run CONFIG and RESOURCE function */
       
   154 #define FB_RUN_SUFFIX "_run__"
       
   155 
       
   156 /* The FB body function is passed as the only parameter a pointer to the FB data
       
   157  * structure instance. The name of this parameter is given by the following constant.
       
   158  * In order not to clash with any variable in the IL and ST source codem the
       
   159  * following constant should contain a double underscore, which is not allowed
       
   160  * in IL and ST.
       
   161  *
       
   162  * e.g.: the body of FUNTION_BLOCK TEST
       
   163  * is mapped onto the C function
       
   164  *  TEST_body__(TEST *data__)
       
   165  */
       
   166 
       
   167 #define FB_FUNCTION_PARAM "data__"
       
   168 
       
   169 
       
   170 #define SFC_STEP_ACTION_PREFIX "__SFC_"
       
   171 
       
   172 /***********************************************************************/
       
   173 /***********************************************************************/
       
   174 /***********************************************************************/
       
   175 /***********************************************************************/
       
   176 
       
   177 
       
   178 #include "spec_init_separator.cc"
       
   179 #include "function_param_iterator.cc"
       
   180 #include "function_call_iterator.cc"
       
   181 #include "function_call_param_iterator.cc"
       
   182 #include "type_initial_value.cc"
       
   183 #include "search_fb_instance_decl.cc"
       
   184 #include "search_base_type.cc"
       
   185 #include "search_var_instance_decl.cc"
       
   186 #include "decompose_var_instance_name.cc"
       
   187 #include "search_varfb_instance_type.cc"
       
   188 #include "search_constant_type.cc"
       
   189 #include "search_expression_type.cc"
       
   190 
       
   191 #include "generate_c_base.cc"
       
   192 #include "generate_c_typedecl.cc"
       
   193 #include "generate_c_sfcdecl.cc"
       
   194 #include "generate_c_vardecl.cc"
       
   195 #include "generate_c_configbody.cc"
       
   196 #include "generate_location_list.cc"
       
   197 
       
   198 /***********************************************************************/
       
   199 /***********************************************************************/
       
   200 /***********************************************************************/
       
   201 /***********************************************************************/
       
   202 
       
   203 /* Generate a name for a temporary variable.
       
   204  * Each new name generated is appended a different number,
       
   205  * starting off from 0.
       
   206  * After calling reset(), the names will start off again from 0.
       
   207  */
       
   208 #define VAR_LEADER "__"
       
   209 #define TEMP_VAR VAR_LEADER "TMP_"
       
   210 #define SOURCE_VAR VAR_LEADER "SRC_"
       
   211 
       
   212 #include "generate_c_tempvardecl.cc"
       
   213 
       
   214 #include "generate_c_st.cc"
       
   215 #include "generate_c_il.cc"
       
   216 
       
   217 #include "generate_c.hh"
       
   218 
       
   219 /***********************************************************************/
       
   220 /***********************************************************************/
       
   221 /***********************************************************************/
       
   222 /***********************************************************************/
       
   223 
       
   224 #define MILLISECOND 1000000
       
   225 #define SECOND 1000 * MILLISECOND
       
   226 
       
   227 /* A helper class that knows how to generate code for both the IL and ST languages... */
       
   228 class calculate_time_c: public iterator_visitor_c {
       
   229   private:
       
   230     unsigned long time;
       
   231     float current_value;
       
   232   
       
   233   public:
       
   234     calculate_time_c(void){time = 0;};
       
   235     
       
   236     unsigned long get_time(void) {return time;};
       
   237 
       
   238     void *get_integer_value(token_c *token) {
       
   239       std::string str = "";
       
   240       for (unsigned int i = 0; i < strlen(token->value); i++)
       
   241         if (token->value[i] != '_')
       
   242           str += token->value[i];
       
   243       current_value = atof(str.c_str());
       
   244       return NULL;
       
   245     }
       
   246 
       
   247     void *get_float_value(token_c *token) {
       
   248       current_value = atof(token->value);
       
   249       return NULL;
       
   250     }
       
   251 
       
   252 /******************************/
       
   253 /* B 1.2.1 - Numeric Literals */
       
   254 /******************************/
       
   255 
       
   256     void *visit(integer_c *symbol) {return get_integer_value(symbol);}
       
   257     
       
   258 /************************/
       
   259 /* B 1.2.3.1 - Duration */
       
   260 /************************/
       
   261   
       
   262     /* SYM_REF2(duration_c, neg, interval) */
       
   263     void *visit(duration_c *symbol) {
       
   264       if (symbol->neg != NULL)
       
   265         ERROR;
       
   266       symbol->interval->accept(*this);
       
   267       return NULL;
       
   268     }
       
   269     
       
   270     /* SYM_TOKEN(fixed_point_c) */
       
   271     void *visit(fixed_point_c *symbol) {return get_float_value(symbol);}
       
   272     
       
   273     /* SYM_REF2(days_c, days, hours) */
       
   274     void *visit(days_c *symbol) {
       
   275       if (symbol->hours)
       
   276         symbol->hours->accept(*this);
       
   277       symbol->days->accept(*this);
       
   278       time += (unsigned long)(current_value * 24 * 3600 * SECOND);
       
   279       return NULL;
       
   280     }
       
   281     
       
   282     /* SYM_REF2(hours_c, hours, minutes) */
       
   283     void *visit(hours_c *symbol) {
       
   284       if (symbol->minutes)
       
   285         symbol->minutes->accept(*this);
       
   286       symbol->hours->accept(*this);
       
   287       time += (unsigned long)(current_value * 3600 * SECOND);
       
   288       return NULL;
       
   289     }
       
   290     
       
   291     /* SYM_REF2(minutes_c, minutes, seconds) */
       
   292     void *visit(minutes_c *symbol) {
       
   293       if (symbol->seconds)
       
   294         symbol->seconds->accept(*this);
       
   295       symbol->minutes->accept(*this);
       
   296       time += (unsigned long)(current_value * 60 * SECOND);
       
   297       return NULL;
       
   298     }
       
   299     
       
   300     /* SYM_REF2(seconds_c, seconds, milliseconds) */
       
   301     void *visit(seconds_c *symbol) {
       
   302       if (symbol->milliseconds)
       
   303         symbol->milliseconds->accept(*this);
       
   304       symbol->seconds->accept(*this);
       
   305       time += (unsigned long)(current_value * SECOND);
       
   306       return NULL;
       
   307     }
       
   308     
       
   309     /* SYM_REF2(milliseconds_c, milliseconds, unused) */
       
   310     void *visit(milliseconds_c *symbol) {
       
   311       symbol->milliseconds->accept(*this);
       
   312       time += (unsigned long)(current_value * MILLISECOND);
       
   313       return NULL;
       
   314     }
       
   315 };
       
   316 
       
   317 /***********************************************************************/
       
   318 /***********************************************************************/
       
   319 /***********************************************************************/
       
   320 /***********************************************************************/
       
   321 
       
   322 class calculate_common_ticktime_c: public iterator_visitor_c {
       
   323   private:
       
   324     unsigned long common_ticktime;
       
   325     
       
   326   public:
       
   327     calculate_common_ticktime_c(void){common_ticktime = 0;}
       
   328     
       
   329     unsigned long euclide(unsigned long a, unsigned long b) {
       
   330       unsigned long c = a % b;
       
   331       if (c == 0)
       
   332         return b;
       
   333       else
       
   334         return euclide(b, c);
       
   335     }
       
   336     
       
   337     void update_ticktime(unsigned long time) {
       
   338       if (common_ticktime == 0)
       
   339         common_ticktime = time;
       
   340       else if (time > common_ticktime)
       
   341         common_ticktime = euclide(time, common_ticktime);
       
   342       else
       
   343         common_ticktime = euclide(common_ticktime, time);
       
   344     }
       
   345 
       
   346     unsigned long get_ticktime(void) {
       
   347       return common_ticktime;
       
   348     }
       
   349 
       
   350 /*  TASK task_name task_initialization */
       
   351 //SYM_REF2(task_configuration_c, task_name, task_initialization)  
       
   352     void *visit(task_initialization_c *symbol) {
       
   353       calculate_time_c calculate_time;
       
   354       unsigned long time = 0;
       
   355       if (symbol->interval_data_source != NULL) {
       
   356         symbol->interval_data_source->accept(calculate_time);
       
   357         time = calculate_time.get_time();
       
   358       }
       
   359       if (time > 0)
       
   360         update_ticktime(time);
       
   361       return NULL;
       
   362     }
       
   363 };    
       
   364 
       
   365 /***********************************************************************/
       
   366 /***********************************************************************/
       
   367 /***********************************************************************/
       
   368 /***********************************************************************/
       
   369 
       
   370 /* A helper class that knows how to generate code for both the IL and ST languages... */
       
   371 class generate_c_SFC_IL_ST_c: public null_visitor_c {
       
   372   private:
       
   373     stage4out_c *s4o_ptr;
       
   374     symbol_c *scope;
       
   375     const char *variable_prefix;
       
   376 
       
   377   public:
       
   378     generate_c_SFC_IL_ST_c(stage4out_c *s4o_ptr, symbol_c *scope, const char *variable_prefix = NULL);
       
   379     /*********************************************/
       
   380     /* B.1.6  Sequential function chart elements */
       
   381     /*********************************************/
       
   382     
       
   383     /*| sequential_function_chart sfc_network*/
       
   384     void *visit(sequential_function_chart_c * symbol);
       
   385     
       
   386     /****************************************/
       
   387     /* B.2 - Language IL (Instruction List) */
       
   388     /****************************************/
       
   389     
       
   390     /***********************************/
       
   391     /* B 2.1 Instructions and Operands */
       
   392     /***********************************/
       
   393     /*| instruction_list il_instruction */
       
   394     void *visit(instruction_list_c *symbol);
       
   395     
       
   396     /* Remainder implemented in generate_c_il_c... */
       
   397     
       
   398     /***************************************/
       
   399     /* B.3 - Language ST (Structured Text) */
       
   400     /***************************************/
       
   401     /***********************/
       
   402     /* B 3.1 - Expressions */
       
   403     /***********************/
       
   404     /* Implemented in generate_c_st_c */
       
   405     
       
   406     /********************/
       
   407     /* B 3.2 Statements */
       
   408     /********************/
       
   409     void *visit(statement_list_c *symbol);
       
   410 
       
   411 /* Remainder implemented in generate_c_st_c... */
       
   412 };
       
   413 
       
   414 #include "generate_c_sfc.cc"
       
   415 
       
   416 generate_c_SFC_IL_ST_c::generate_c_SFC_IL_ST_c(stage4out_c *s4o_ptr, symbol_c *scope, const char *variable_prefix) {
       
   417   if (NULL == scope) ERROR;
       
   418   this->s4o_ptr = s4o_ptr;
       
   419   this->scope = scope;
       
   420   this->variable_prefix = variable_prefix;
       
   421 }
       
   422 
       
   423 void *generate_c_SFC_IL_ST_c::visit(sequential_function_chart_c * symbol) {
       
   424   generate_c_sfc_c generate_c_sfc(s4o_ptr, scope, variable_prefix);
       
   425   generate_c_sfc.generate(symbol);
       
   426   return NULL;
       
   427 }
       
   428 
       
   429 void *generate_c_SFC_IL_ST_c::visit(instruction_list_c *symbol) {
       
   430   generate_c_il_c generate_c_il(s4o_ptr, scope, variable_prefix);
       
   431   generate_c_il.generate(symbol);
       
   432   return NULL;
       
   433 }
       
   434 
       
   435 void *generate_c_SFC_IL_ST_c::visit(statement_list_c *symbol) {
       
   436   generate_c_st_c generate_c_st(s4o_ptr, scope, variable_prefix);
       
   437   generate_c_st.generate(symbol);
       
   438   return NULL;
       
   439 }
       
   440 
       
   441 
       
   442 
       
   443 
       
   444 /***********************************************************************/
       
   445 /***********************************************************************/
       
   446 /***********************************************************************/
       
   447 /***********************************************************************/
       
   448 /***********************************************************************/
       
   449 
       
   450 
       
   451 class generate_c_pous_c: public generate_c_typedecl_c {
       
   452 
       
   453   public:
       
   454     generate_c_pous_c(stage4out_c *s4o_ptr)
       
   455       : generate_c_typedecl_c(s4o_ptr) {};
       
   456     virtual ~generate_c_pous_c(void) {}
       
   457 
       
   458 
       
   459   public:
       
   460 
       
   461 /*************************/
       
   462 /* B.1 - Common elements */
       
   463 /*************************/
       
   464 /*******************************************/
       
   465 /* B 1.1 - Letters, digits and identifiers */
       
   466 /*******************************************/
       
   467   /* done in base class(es) */
       
   468 
       
   469 /*********************/
       
   470 /* B 1.2 - Constants */
       
   471 /*********************/
       
   472   /* originally empty... */
       
   473 
       
   474 /******************************/
       
   475 /* B 1.2.1 - Numeric Literals */
       
   476 /******************************/
       
   477   /* done in base class(es) */
       
   478 
       
   479 /*******************************/
       
   480 /* B.1.2.2   Character Strings */
       
   481 /*******************************/
       
   482   /* done in base class(es) */
       
   483 
       
   484 /***************************/
       
   485 /* B 1.2.3 - Time Literals */
       
   486 /***************************/
       
   487 /************************/
       
   488 /* B 1.2.3.1 - Duration */
       
   489 /************************/
       
   490   /* done in base class(es) */
       
   491 
       
   492 /************************************/
       
   493 /* B 1.2.3.2 - Time of day and Date */
       
   494 /************************************/
       
   495   /* done in base class(es) */
       
   496 
       
   497 /**********************/
       
   498 /* B.1.3 - Data types */
       
   499 /**********************/
       
   500 /***********************************/
       
   501 /* B 1.3.1 - Elementary Data Types */
       
   502 /***********************************/
       
   503   /* done in base class(es) */
       
   504 
       
   505 /********************************/
       
   506 /* B.1.3.2 - Generic data types */
       
   507 /********************************/
       
   508   /* originally empty... */
       
   509 
       
   510 /********************************/
       
   511 /* B 1.3.3 - Derived data types */
       
   512 /********************************/
       
   513   /* done in base class(es) */
       
   514 
       
   515 /*********************/
       
   516 /* B 1.4 - Variables */
       
   517 /*********************/
       
   518   /* done in base class(es) */
       
   519 
       
   520 /********************************************/
       
   521 /* B.1.4.1   Directly Represented Variables */
       
   522 /********************************************/
       
   523   /* done in base class(es) */
       
   524 
       
   525 /*************************************/
       
   526 /* B.1.4.2   Multi-element Variables */
       
   527 /*************************************/
       
   528   /* done in base class(es) */
       
   529 
       
   530 /******************************************/
       
   531 /* B 1.4.3 - Declaration & Initialisation */
       
   532 /******************************************/
       
   533   /* done in base class(es) */
       
   534 
       
   535 /**************************************/
       
   536 /* B.1.5 - Program organization units */
       
   537 /**************************************/
       
   538 /***********************/
       
   539 /* B 1.5.1 - Functions */
       
   540 /***********************/
       
   541 
       
   542 public:
       
   543 /*   FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
       
   544 /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
       
   545 void *visit(function_declaration_c *symbol) {
       
   546   generate_c_vardecl_c *vardecl;
       
   547   TRACE("function_declaration_c");
       
   548 
       
   549   /* start off by adding this declaration to the global
       
   550    * function declaration symbol table...
       
   551    */
       
   552   function_symtable.insert(symbol->derived_function_name, symbol);
       
   553 
       
   554   /* (A) Function declaration... */
       
   555   /* (A.1) Function return type */
       
   556   s4o.print("// FUNCTION\n");
       
   557   symbol->type_name->accept(*this); /* return type */
       
   558   s4o.print(" ");
       
   559   /* (A.2) Function name */
       
   560   symbol->derived_function_name->accept(*this);
       
   561   s4o.print("(");
       
   562 
       
   563   /* (A.3) Function parameters */
       
   564   s4o.indent_right();
       
   565   vardecl = new generate_c_vardecl_c(&s4o,
       
   566   				      generate_c_vardecl_c::finterface_vf,
       
   567   				      generate_c_vardecl_c::input_vt |
       
   568 				      generate_c_vardecl_c::output_vt |
       
   569 				      generate_c_vardecl_c::inoutput_vt);
       
   570   vardecl->print(symbol->var_declarations_list);
       
   571   delete vardecl;
       
   572   s4o.indent_left();
       
   573 
       
   574   s4o.print(")\n" + s4o.indent_spaces + "{\n");
       
   575 
       
   576   /* (B) Function local variable declaration */
       
   577     /* (B.1) Variables declared in ST source code */
       
   578   s4o.indent_right();
       
   579   vardecl = new generate_c_vardecl_c(&s4o, generate_c_vardecl_c::localinit_vf, generate_c_vardecl_c::private_vt);
       
   580   vardecl->print(symbol->var_declarations_list);
       
   581   delete vardecl;
       
   582 
       
   583     /* (B.2) Temporary variable for function's return value */
       
   584   /* It will have the same name as the function itself! */
       
   585   s4o.print(s4o.indent_spaces);
       
   586   symbol->type_name->accept(*this); /* return type */
       
   587   s4o.print(" ");
       
   588   symbol->derived_function_name->accept(*this);
       
   589   s4o.print(" = ");
       
   590   {
       
   591     /* get the default value of this variable's type */
       
   592     symbol_c *default_value = (symbol_c *)symbol->type_name->accept(*type_initial_value_c::instance());
       
   593     if (default_value == NULL) ERROR;
       
   594     default_value->accept(*this);
       
   595   }
       
   596   s4o.print(";\n\n");
       
   597 
       
   598   /* (C) Function body */
       
   599   generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol);
       
   600   symbol->function_body->accept(generate_c_code);
       
   601   s4o.print(s4o.indent_spaces + "return ");
       
   602   symbol->derived_function_name->accept(*this);
       
   603   s4o.print(";\n");
       
   604   s4o.indent_left();
       
   605   s4o.print(s4o.indent_spaces + "}\n\n\n");
       
   606 
       
   607   return NULL;
       
   608 }
       
   609 
       
   610 
       
   611 /* The remaining var_declarations_list_c, function_var_decls_c
       
   612  * and var2_init_decl_list_c are handled in the generate_c_vardecl_c class
       
   613  */
       
   614 
       
   615 
       
   616 /*****************************/
       
   617 /* B 1.5.2 - Function Blocks */
       
   618 /*****************************/
       
   619 public:
       
   620 /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
       
   621 //SYM_REF4(function_block_declaration_c, fblock_name, var_declarations, fblock_body, unused)
       
   622 void *visit(function_block_declaration_c *symbol) {
       
   623   generate_c_vardecl_c *vardecl;
       
   624   generate_c_sfcdecl_c *sfcdecl;
       
   625   TRACE("function_block_declaration_c");
       
   626 
       
   627   /* start off by adding this declaration to the global
       
   628    * function block declaration symbol table...
       
   629    */
       
   630   function_block_type_symtable.insert(symbol->fblock_name, symbol);
       
   631   
       
   632   /* (A) Function Block data structure declaration... */
       
   633   /* (A.1) Data structure declaration */
       
   634   s4o.print("// FUNCTION_BLOCK ");
       
   635   symbol->fblock_name->accept(*this);
       
   636   s4o.print("\n// Data part\n");
       
   637   s4o.print("typedef struct {\n");
       
   638   s4o.indent_right();
       
   639   /* (A.2) Public variables: i.e. the function parameters... */
       
   640   s4o.print(s4o.indent_spaces + "// FB Interface - IN, OUT, IN_OUT variables\n");
       
   641   vardecl = new generate_c_vardecl_c(&s4o,
       
   642   				      generate_c_vardecl_c::local_vf,
       
   643   				      generate_c_vardecl_c::input_vt |
       
   644   				      generate_c_vardecl_c::output_vt |
       
   645   				      generate_c_vardecl_c::inoutput_vt);
       
   646   vardecl->print(symbol->var_declarations);
       
   647   delete vardecl;
       
   648   s4o.print("\n");
       
   649   /* (A.3) Private internal variables */
       
   650   s4o.print(s4o.indent_spaces + "// FB private variables - TEMP, private and located variables\n");
       
   651   vardecl = new generate_c_vardecl_c(&s4o,
       
   652   				      generate_c_vardecl_c::local_vf,
       
   653 				        generate_c_vardecl_c::temp_vt |
       
   654   				      generate_c_vardecl_c::private_vt |
       
   655   				      generate_c_vardecl_c::located_vt |
       
   656   				      generate_c_vardecl_c::external_vt);
       
   657   vardecl->print(symbol->var_declarations);
       
   658   delete vardecl;
       
   659   /* (A.4) Generate private internal variables for SFC */
       
   660   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::sfcdecl_sd);
       
   661   sfcdecl->print(symbol->fblock_body);
       
   662   delete sfcdecl;
       
   663   s4o.print("\n");
       
   664 
       
   665   /* (A.5) Function Block data structure type name. */
       
   666   s4o.indent_left();
       
   667   s4o.print("} ");
       
   668   symbol->fblock_name->accept(*this);
       
   669   s4o.print(";\n\n");
       
   670 
       
   671 
       
   672   /* (B) Constructor */
       
   673   /* (B.1) Constructor name... */
       
   674   s4o.print(s4o.indent_spaces + "void ");
       
   675   symbol->fblock_name->accept(*this);
       
   676   s4o.print(FB_INIT_SUFFIX);
       
   677   s4o.print("(");
       
   678 
       
   679   /* first and only parameter is a pointer to the data */
       
   680   symbol->fblock_name->accept(*this);
       
   681   s4o.print(" *");
       
   682   s4o.print(FB_FUNCTION_PARAM);
       
   683   s4o.print(") {\n");
       
   684   s4o.indent_right();
       
   685 
       
   686   /* (B.2) Member initializations... */
       
   687   s4o.print(s4o.indent_spaces);
       
   688   vardecl = new generate_c_vardecl_c(&s4o,
       
   689   				      generate_c_vardecl_c::constructorinit_vf,
       
   690   				      generate_c_vardecl_c::input_vt |
       
   691   				      generate_c_vardecl_c::output_vt |
       
   692   				      generate_c_vardecl_c::inoutput_vt |
       
   693   				      generate_c_vardecl_c::private_vt |
       
   694 				        generate_c_vardecl_c::located_vt |
       
   695 				        generate_c_vardecl_c::external_vt);
       
   696   vardecl->print(symbol->var_declarations, NULL, FB_FUNCTION_PARAM"->");
       
   697   delete vardecl;
       
   698   s4o.print("\n");
       
   699   /* (B.3) Generate private internal variables for SFC */
       
   700   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::sfcinit_sd);
       
   701   sfcdecl->print(symbol->fblock_body, FB_FUNCTION_PARAM"->");
       
   702   delete sfcdecl;
       
   703   s4o.indent_left();
       
   704   s4o.print(s4o.indent_spaces + "}\n\n");
       
   705 
       
   706   
       
   707   /* (C) Function with FB body */
       
   708   /* (C.1) Step definitions */
       
   709   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::stepdef_sd);
       
   710   sfcdecl->print(symbol->fblock_body);
       
   711   delete sfcdecl;
       
   712   
       
   713   /* (C.2) Action definitions */
       
   714   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::actiondef_sd);
       
   715   sfcdecl->print(symbol->fblock_body);
       
   716   delete sfcdecl;
       
   717   
       
   718   /* (C.3) Function declaration */
       
   719   s4o.print("// Code part\n");
       
   720   /* function interface */
       
   721   s4o.print("void ");
       
   722   symbol->fblock_name->accept(*this);
       
   723   s4o.print(FB_FUNCTION_SUFFIX);
       
   724   s4o.print("(");
       
   725   /* first and only parameter is a pointer to the data */
       
   726   symbol->fblock_name->accept(*this);
       
   727   s4o.print(" *");
       
   728   s4o.print(FB_FUNCTION_PARAM);
       
   729   s4o.print(") {\n");
       
   730   s4o.indent_right();
       
   731 
       
   732   /* (C.4) Initialize TEMP variables */
       
   733   /* function body */
       
   734   s4o.print(s4o.indent_spaces + "// Initialise TEMP variables\n");
       
   735   vardecl = new generate_c_vardecl_c(&s4o,
       
   736   				      generate_c_vardecl_c::init_vf,
       
   737 				      generate_c_vardecl_c::temp_vt);
       
   738   vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
       
   739   delete vardecl;
       
   740   s4o.print("\n");
       
   741 
       
   742   /* (C.5) Function code */
       
   743   generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol, FB_FUNCTION_PARAM"->");
       
   744   symbol->fblock_body->accept(generate_c_code);
       
   745   s4o.indent_left();
       
   746   s4o.print(s4o.indent_spaces + "} // ");
       
   747   symbol->fblock_name->accept(*this);
       
   748   s4o.print(FB_FUNCTION_SUFFIX);
       
   749   s4o.print(s4o.indent_spaces + "() \n\n");
       
   750 
       
   751   /* (C.6) Step undefinitions */
       
   752   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::stepundef_sd);
       
   753   sfcdecl->print(symbol->fblock_body);
       
   754   delete sfcdecl;
       
   755   
       
   756   /* (C.7) Action undefinitions */
       
   757   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::actionundef_sd);
       
   758   sfcdecl->print(symbol->fblock_body);
       
   759   delete sfcdecl;
       
   760 
       
   761   s4o.indent_left();
       
   762   s4o.print("\n\n\n\n");
       
   763 
       
   764   return NULL;
       
   765 }
       
   766 
       
   767 
       
   768 /* The remaining temp_var_decls_c, temp_var_decls_list_c
       
   769  * and non_retentive_var_decls_c are handled in the generate_c_vardecl_c class
       
   770  */
       
   771 
       
   772 
       
   773 /**********************/
       
   774 /* B 1.5.3 - Programs */
       
   775 /**********************/
       
   776 
       
   777 
       
   778 
       
   779 public:
       
   780 /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
       
   781 //SYM_REF4(program_declaration_c, program_type_name, var_declarations, function_block_body, unused)
       
   782 void *visit(program_declaration_c *symbol) {
       
   783   generate_c_vardecl_c *vardecl;
       
   784   generate_c_sfcdecl_c *sfcdecl;
       
   785   TRACE("program_declaration_c");
       
   786 
       
   787   /* start off by adding this declaration to the global
       
   788    * program declaration symbol table...
       
   789    */
       
   790   program_type_symtable.insert(symbol->program_type_name, symbol);
       
   791 
       
   792   /* (A) Program data structure declaration... */
       
   793   /* (A.1) Data structure declaration */
       
   794   s4o.print("// PROGRAM ");
       
   795   symbol->program_type_name->accept(*this);
       
   796   s4o.print("\n// Data part\n");
       
   797   s4o.print("typedef struct {\n");
       
   798   s4o.indent_right();
       
   799 
       
   800   /* (A.2) Public variables: i.e. the program parameters... */
       
   801   s4o.print(s4o.indent_spaces + "// PROGRAM Interface - IN, OUT, IN_OUT variables\n");
       
   802   vardecl = new generate_c_vardecl_c(&s4o,
       
   803   				      generate_c_vardecl_c::local_vf,
       
   804   				      generate_c_vardecl_c::input_vt |
       
   805   				      generate_c_vardecl_c::output_vt |
       
   806   				      generate_c_vardecl_c::inoutput_vt);
       
   807   vardecl->print(symbol->var_declarations);
       
   808   delete vardecl;
       
   809   s4o.print("\n");
       
   810   /* (A.3) Private internal variables */
       
   811   s4o.print(s4o.indent_spaces + "// PROGRAM private variables - TEMP, private and located variables\n");
       
   812   vardecl = new generate_c_vardecl_c(&s4o,
       
   813                 generate_c_vardecl_c::local_vf,
       
   814                 generate_c_vardecl_c::temp_vt |
       
   815                 generate_c_vardecl_c::private_vt |
       
   816                 generate_c_vardecl_c::located_vt |
       
   817                 generate_c_vardecl_c::external_vt);
       
   818   vardecl->print(symbol->var_declarations);
       
   819   delete vardecl;
       
   820   /* (A.4) Generate private internal variables for SFC */
       
   821   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::sfcdecl_sd);
       
   822   sfcdecl->print(symbol->function_block_body);
       
   823   delete sfcdecl;
       
   824   
       
   825   /* (A.5) Program data structure type name. */
       
   826   s4o.indent_left();
       
   827   s4o.print("} ");
       
   828   symbol->program_type_name->accept(*this);
       
   829   s4o.print(";\n\n");
       
   830 
       
   831   /* (B) Constructor */
       
   832   /* (B.1) Constructor name... */
       
   833   s4o.print(s4o.indent_spaces + "void ");
       
   834   symbol->program_type_name->accept(*this);
       
   835   s4o.print(FB_INIT_SUFFIX);
       
   836   s4o.print("(");
       
   837 
       
   838   /* first and only parameter is a pointer to the data */
       
   839   symbol->program_type_name->accept(*this);
       
   840   s4o.print(" *");
       
   841   s4o.print(FB_FUNCTION_PARAM);
       
   842   s4o.print(") {\n");
       
   843   s4o.indent_right();
       
   844 
       
   845   /* (B.2) Member initializations... */
       
   846   s4o.print(s4o.indent_spaces);
       
   847   vardecl = new generate_c_vardecl_c(&s4o,
       
   848   				      generate_c_vardecl_c::constructorinit_vf,
       
   849   				      generate_c_vardecl_c::input_vt |
       
   850   				      generate_c_vardecl_c::output_vt |
       
   851   				      generate_c_vardecl_c::inoutput_vt |
       
   852   				      generate_c_vardecl_c::private_vt |
       
   853   				      generate_c_vardecl_c::located_vt |
       
   854 				      generate_c_vardecl_c::external_vt);
       
   855   vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
       
   856   delete vardecl;
       
   857   s4o.print("\n");
       
   858   /* (B.3) Generate private internal variables for SFC */
       
   859   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::sfcinit_sd);
       
   860   sfcdecl->print(symbol->function_block_body,FB_FUNCTION_PARAM"->");
       
   861   delete sfcdecl;
       
   862 
       
   863   s4o.indent_left();
       
   864   s4o.print(s4o.indent_spaces + "}\n\n");
       
   865 
       
   866   /* (C) Function with PROGRAM body */
       
   867   /* (C.1) Step definitions */
       
   868   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::stepdef_sd);
       
   869   sfcdecl->print(symbol->function_block_body);
       
   870   delete sfcdecl;
       
   871   
       
   872   /* (C.2) Action definitions */
       
   873   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::actiondef_sd);
       
   874   sfcdecl->print(symbol->function_block_body);
       
   875   delete sfcdecl;
       
   876 
       
   877   /* (C.3) Function declaration */
       
   878   s4o.print("// Code part\n");
       
   879   /* function interface */
       
   880   s4o.print("void ");
       
   881   symbol->program_type_name->accept(*this);
       
   882   s4o.print(FB_FUNCTION_SUFFIX);
       
   883   s4o.print("(");
       
   884   /* first and only parameter is a pointer to the data */
       
   885   symbol->program_type_name->accept(*this);
       
   886   s4o.print(" *");
       
   887   s4o.print(FB_FUNCTION_PARAM);
       
   888   s4o.print(") {\n");
       
   889   s4o.indent_right();
       
   890 
       
   891   /* (C.4) Initialize TEMP variables */
       
   892   /* function body */
       
   893   s4o.print(s4o.indent_spaces + "// Initialise TEMP variables\n");
       
   894   vardecl = new generate_c_vardecl_c(&s4o,
       
   895   				      generate_c_vardecl_c::init_vf,
       
   896 				      generate_c_vardecl_c::temp_vt);
       
   897   vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
       
   898   delete vardecl;
       
   899   s4o.print("\n");
       
   900 
       
   901   /* (C.5) Function code */
       
   902   generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol, FB_FUNCTION_PARAM"->");
       
   903   symbol->function_block_body->accept(generate_c_code);
       
   904   s4o.indent_left();
       
   905   s4o.print(s4o.indent_spaces + "} // ");
       
   906   symbol->program_type_name->accept(*this);
       
   907   s4o.print(FB_FUNCTION_SUFFIX);
       
   908   s4o.print(s4o.indent_spaces + "() \n\n");
       
   909 
       
   910   /* (C.6) Step undefinitions */
       
   911   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::stepundef_sd);
       
   912   sfcdecl->print(symbol->function_block_body);
       
   913   delete sfcdecl;
       
   914   
       
   915   /* (C.7) Action undefinitions */
       
   916   sfcdecl = new generate_c_sfcdecl_c(&s4o, generate_c_sfcdecl_c::actionundef_sd);
       
   917   sfcdecl->print(symbol->function_block_body);
       
   918   delete sfcdecl;
       
   919   
       
   920   s4o.indent_left();
       
   921   s4o.print("\n\n\n\n");
       
   922 
       
   923   return NULL;
       
   924 }
       
   925 
       
   926 }; /* generate_c_pous_c */
       
   927 
       
   928 /***********************************************************************/
       
   929 /***********************************************************************/
       
   930 /***********************************************************************/
       
   931 /***********************************************************************/
       
   932 /***********************************************************************/
       
   933 /***********************************************************************/
       
   934 /***********************************************************************/
       
   935 /***********************************************************************/
       
   936 
       
   937 class generate_c_config_c: public generate_c_typedecl_c {
       
   938 
       
   939     public:
       
   940     generate_c_config_c(stage4out_c *s4o_ptr)
       
   941       : generate_c_typedecl_c(s4o_ptr) {};
       
   942     virtual ~generate_c_config_c(void) {}
       
   943 
       
   944     typedef enum {
       
   945       initprotos_dt,
       
   946       initdeclare_dt,
       
   947       runprotos_dt,
       
   948       rundeclare_dt
       
   949     } declaretype_t;
       
   950 
       
   951     declaretype_t wanted_declaretype;
       
   952 
       
   953 /********************************/
       
   954 /* B 1.7 Configuration elements */
       
   955 /********************************/
       
   956 
       
   957 
       
   958 public:
       
   959 /*
       
   960 CONFIGURATION configuration_name
       
   961    optional_global_var_declarations
       
   962    (resource_declaration_list | single_resource_declaration)
       
   963    optional_access_declarations
       
   964    optional_instance_specific_initializations
       
   965 END_CONFIGURATION
       
   966 */
       
   967 /*
       
   968 SYM_REF6(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, unused)
       
   969 */
       
   970 void *visit(configuration_declaration_c *symbol) {
       
   971   generate_c_vardecl_c *vardecl;
       
   972   
       
   973   /* Insert the header... */
       
   974   s4o.print("/*******************************************/\n");
       
   975   s4o.print("/*     FILE GENERATED BY iec2c             */\n");
       
   976   s4o.print("/* Editing this file is not recommended... */\n");
       
   977   s4o.print("/*******************************************/\n\n");
       
   978   s4o.print("#include \"iec_std_lib.h\"\n\n");
       
   979   
       
   980   /* (A) configuration declaration... */
       
   981   /* (A.1) configuration name in comment */
       
   982   s4o.print("// CONFIGURATION ");
       
   983   symbol->configuration_name->accept(*this);
       
   984   s4o.print("\n");
       
   985   
       
   986   /* (A.2) Global variables */
       
   987   vardecl = new generate_c_vardecl_c(&s4o,
       
   988   				      generate_c_vardecl_c::local_vf,
       
   989   				      generate_c_vardecl_c::global_vt);
       
   990   vardecl->print(symbol);
       
   991   delete vardecl;
       
   992   s4o.print("\n");
       
   993 
       
   994   /* (B) Initialisation Function */
       
   995   /* (B.1) Ressources initialisation protos... */
       
   996   wanted_declaretype = initprotos_dt;
       
   997   symbol->resource_declarations->accept(*this);
       
   998   s4o.print("\n");
       
   999   
       
  1000   /* (B.2) Initialisation function name... */
       
  1001   s4o.print(s4o.indent_spaces + "void config");
       
  1002   s4o.print(FB_INIT_SUFFIX);
       
  1003   s4o.print("(void) {\n");
       
  1004   s4o.indent_right();
       
  1005   
       
  1006   /* (B.3) Global variables initializations... */
       
  1007   s4o.print(s4o.indent_spaces);
       
  1008   vardecl = new generate_c_vardecl_c(&s4o,
       
  1009   				      generate_c_vardecl_c::constructorinit_vf,
       
  1010   				      generate_c_vardecl_c::global_vt);
       
  1011   vardecl->print(symbol);
       
  1012   delete vardecl;
       
  1013   s4o.print("\n");
       
  1014   
       
  1015   /* (B.3) Resources initializations... */
       
  1016   wanted_declaretype = initdeclare_dt;
       
  1017   symbol->resource_declarations->accept(*this);
       
  1018   
       
  1019   s4o.indent_left();
       
  1020   s4o.print(s4o.indent_spaces + "}\n\n");
       
  1021 
       
  1022 
       
  1023   /* (C) Run Function*/
       
  1024   /* (C.1) Resources run functions protos... */
       
  1025   wanted_declaretype = runprotos_dt;
       
  1026   symbol->resource_declarations->accept(*this);
       
  1027   s4o.print("\n");
       
  1028 
       
  1029   /* (C.2) Run function name... */
       
  1030   s4o.print(s4o.indent_spaces + "void config");
       
  1031   s4o.print(FB_RUN_SUFFIX);
       
  1032   s4o.print("(int tick) {\n");
       
  1033   s4o.indent_right();
       
  1034 
       
  1035   /* (C.3) Resources initializations... */
       
  1036   wanted_declaretype = rundeclare_dt;
       
  1037   symbol->resource_declarations->accept(*this);
       
  1038 
       
  1039   /* (C.3) Close Public Function body */
       
  1040   s4o.indent_left();
       
  1041   s4o.print(s4o.indent_spaces + "}\n");
       
  1042 
       
  1043   return NULL;
       
  1044 }
       
  1045 
       
  1046 void *visit(resource_declaration_c *symbol) {
       
  1047   if (wanted_declaretype == initprotos_dt || wanted_declaretype == runprotos_dt) {
       
  1048     s4o.print(s4o.indent_spaces + "void ");
       
  1049     symbol->resource_name->accept(*this);
       
  1050     if (wanted_declaretype == initprotos_dt) {
       
  1051       s4o.print(FB_INIT_SUFFIX);
       
  1052       s4o.print("(void);\n");
       
  1053     }
       
  1054     else {
       
  1055       s4o.print(FB_RUN_SUFFIX);
       
  1056       s4o.print("(int tick);\n");
       
  1057     }
       
  1058   }
       
  1059   if (wanted_declaretype == initdeclare_dt || wanted_declaretype == rundeclare_dt) {
       
  1060     s4o.print(s4o.indent_spaces);
       
  1061     symbol->resource_name->accept(*this);
       
  1062     if (wanted_declaretype == initdeclare_dt) {
       
  1063       s4o.print(FB_INIT_SUFFIX);
       
  1064       s4o.print("();\n");
       
  1065     }
       
  1066     else {
       
  1067       s4o.print(FB_RUN_SUFFIX);
       
  1068       s4o.print("(tick);\n");
       
  1069     }
       
  1070   }
       
  1071   return NULL;
       
  1072 }
       
  1073 
       
  1074 void *visit(single_resource_declaration_c *symbol) {
       
  1075   if (wanted_declaretype == initprotos_dt || wanted_declaretype == runprotos_dt) {
       
  1076     s4o.print(s4o.indent_spaces + "void RESOURCE");
       
  1077     if (wanted_declaretype == initprotos_dt) {
       
  1078       s4o.print(FB_INIT_SUFFIX);
       
  1079       s4o.print("(void);\n");
       
  1080     }
       
  1081     else {
       
  1082       s4o.print(FB_RUN_SUFFIX);
       
  1083       s4o.print("(int tick);\n");
       
  1084     }
       
  1085   }
       
  1086   if (wanted_declaretype == initdeclare_dt || wanted_declaretype == rundeclare_dt) {
       
  1087     s4o.print(s4o.indent_spaces + "RESOURCE");
       
  1088     if (wanted_declaretype == initdeclare_dt) {
       
  1089       s4o.print(FB_INIT_SUFFIX);
       
  1090       s4o.print("();\n");
       
  1091     }
       
  1092     else {
       
  1093       s4o.print(FB_RUN_SUFFIX);
       
  1094       s4o.print("(tick);\n");
       
  1095     }
       
  1096   }
       
  1097   return NULL;
       
  1098 }
       
  1099 
       
  1100 };
       
  1101 
       
  1102 /***********************************************************************/
       
  1103 /***********************************************************************/
       
  1104 /***********************************************************************/
       
  1105 /***********************************************************************/
       
  1106 /***********************************************************************/
       
  1107 /***********************************************************************/
       
  1108 /***********************************************************************/
       
  1109 /***********************************************************************/
       
  1110 
       
  1111 
       
  1112 class generate_c_resources_c: public generate_c_typedecl_c {
       
  1113 
       
  1114   search_var_instance_decl_c *search_config_instance;
       
  1115   search_var_instance_decl_c *search_resource_instance;
       
  1116 
       
  1117   private:
       
  1118     /* The name of the resource curretnly being processed... */
       
  1119     symbol_c *current_resource_name;
       
  1120     symbol_c *current_global_vars;
       
  1121 
       
  1122   public:
       
  1123     generate_c_resources_c(stage4out_c *s4o_ptr, symbol_c *config_scope, symbol_c *resource_scope, unsigned long time)
       
  1124       : generate_c_typedecl_c(s4o_ptr) {
       
  1125       search_config_instance = new search_var_instance_decl_c(config_scope);
       
  1126       search_resource_instance = new search_var_instance_decl_c(resource_scope);
       
  1127       common_ticktime = time;
       
  1128       current_resource_name = NULL;
       
  1129       current_global_vars = NULL;
       
  1130     };
       
  1131     virtual ~generate_c_resources_c(void) {
       
  1132       delete search_config_instance;
       
  1133       delete search_resource_instance;
       
  1134     }
       
  1135 
       
  1136     typedef enum {
       
  1137       declare_dt,
       
  1138       init_dt,
       
  1139       run_dt
       
  1140     } declaretype_t;
       
  1141 
       
  1142     declaretype_t wanted_declaretype;
       
  1143 
       
  1144     unsigned long common_ticktime;
       
  1145     
       
  1146     const char *current_program_name;
       
  1147 
       
  1148     typedef enum {
       
  1149       assign_at,
       
  1150       send_at
       
  1151     } assigntype_t;
       
  1152 
       
  1153     assigntype_t wanted_assigntype;
       
  1154 
       
  1155 /********************************/
       
  1156 /* B 1.7 Configuration elements */
       
  1157 /********************************/
       
  1158 
       
  1159 /*
       
  1160 RESOURCE resource_name ON resource_type_name
       
  1161    optional_global_var_declarations
       
  1162    single_resource_declaration
       
  1163 END_RESOURCE
       
  1164 */
       
  1165 // SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration)
       
  1166     void *visit(resource_declaration_c *symbol) {
       
  1167       current_resource_name = symbol->resource_name;
       
  1168       current_global_vars = symbol->global_var_declarations;
       
  1169       
       
  1170       symbol->resource_declaration->accept(*this);
       
  1171       
       
  1172       current_resource_name = NULL;
       
  1173       current_global_vars = NULL;
       
  1174       return NULL;
       
  1175     }
       
  1176 
       
  1177 /* task_configuration_list program_configuration_list */
       
  1178 // SYM_REF2(single_resource_declaration_c, task_configuration_list, program_configuration_list)
       
  1179     void *visit(single_resource_declaration_c *symbol) {
       
  1180     	bool single_resource = current_resource_name == NULL;
       
  1181       if (single_resource)
       
  1182         current_resource_name = new identifier_c("RESOURCE");
       
  1183       generate_c_vardecl_c *vardecl;
       
  1184       
       
  1185       /* Insert the header... */
       
  1186       s4o.print("/*******************************************/\n");
       
  1187       s4o.print("/*     FILE GENERATED BY iec2c             */\n");
       
  1188       s4o.print("/* Editing this file is not recommended... */\n");
       
  1189       s4o.print("/*******************************************/\n\n");
       
  1190       s4o.print("#include \"iec_std_lib.h\"\n\n");
       
  1191       
       
  1192       /* (A) resource declaration... */
       
  1193       /* (A.1) resource name in comment */
       
  1194       s4o.print("// RESOURCE ");
       
  1195       current_resource_name->accept(*this);
       
  1196       s4o.print("\n");
       
  1197        
       
  1198       /* (A.2) Global variables... */
       
  1199       if (current_global_vars != NULL) {
       
  1200         vardecl = new generate_c_vardecl_c(&s4o,
       
  1201                       generate_c_vardecl_c::local_vf,
       
  1202                       generate_c_vardecl_c::global_vt);
       
  1203         vardecl->print(current_global_vars);
       
  1204         delete vardecl;
       
  1205       }
       
  1206       s4o.print("\n");
       
  1207       
       
  1208       /* (A.3) POUs inclusion */
       
  1209       s4o.print("#include \"POUS.c\"\n\n");
       
  1210       
       
  1211       /* (A.4) Resource programs declaration... */
       
  1212       wanted_declaretype = declare_dt;
       
  1213       symbol->program_configuration_list->accept(*this);
       
  1214       s4o.print("\n");
       
  1215       
       
  1216       /* (B) resource initialisation function... */
       
  1217       /* (B.1) initialisation function name... */
       
  1218       s4o.print("void ");
       
  1219       current_resource_name->accept(*this);
       
  1220       s4o.print(FB_INIT_SUFFIX);
       
  1221       s4o.print("(void) {\n");
       
  1222       s4o.indent_right();
       
  1223       
       
  1224       /* (B.2) Global variables initialisations... */
       
  1225       if (current_global_vars != NULL) {
       
  1226         s4o.print(s4o.indent_spaces);
       
  1227         vardecl = new generate_c_vardecl_c(&s4o,
       
  1228                       generate_c_vardecl_c::constructorinit_vf,
       
  1229                       generate_c_vardecl_c::global_vt);
       
  1230         vardecl->print(current_global_vars);
       
  1231         delete vardecl;
       
  1232       }
       
  1233       s4o.print("\n");
       
  1234       
       
  1235       /* (B.3) Resource programs initialisations... */
       
  1236       wanted_declaretype = init_dt;
       
  1237       symbol->program_configuration_list->accept(*this);
       
  1238       
       
  1239       s4o.indent_left();
       
  1240       s4o.print("}\n\n");
       
  1241       
       
  1242       /* (C) Resource run function... */
       
  1243       /* (C.1) Run function name... */
       
  1244       s4o.print("void ");
       
  1245       current_resource_name->accept(*this);
       
  1246       s4o.print(FB_RUN_SUFFIX);
       
  1247       s4o.print("(int tick) {\n");
       
  1248       s4o.indent_right();
       
  1249       
       
  1250       /* (C.2) Task management... */
       
  1251       symbol->task_configuration_list->accept(*this);
       
  1252       
       
  1253       /* (C.3) Program run declaration... */
       
  1254       wanted_declaretype = run_dt;
       
  1255       symbol->program_configuration_list->accept(*this);
       
  1256       
       
  1257       s4o.indent_left();
       
  1258       s4o.print("}\n\n");
       
  1259       
       
  1260       if (single_resource) {
       
  1261         delete current_resource_name;
       
  1262         current_resource_name = NULL;
       
  1263       }
       
  1264       return NULL;
       
  1265     }
       
  1266     
       
  1267 /*  PROGRAM [RETAIN | NON_RETAIN] program_name [WITH task_name] ':' program_type_name ['(' prog_conf_elements ')'] */
       
  1268 //SYM_REF6(program_configuration_c, retain_option, program_name, task_name, program_type_name, prog_conf_elements, unused)
       
  1269     void *visit(program_configuration_c *symbol) {
       
  1270       if (wanted_declaretype == declare_dt) {
       
  1271         s4o.print(s4o.indent_spaces);
       
  1272         symbol->program_type_name->accept(*this);
       
  1273         s4o.print(" ");
       
  1274         symbol->program_name->accept(*this);
       
  1275         s4o.print(";\n");
       
  1276       }
       
  1277       if (wanted_declaretype == init_dt) {
       
  1278         s4o.print(s4o.indent_spaces);
       
  1279         symbol->program_type_name->accept(*this);
       
  1280         s4o.print(FB_INIT_SUFFIX);
       
  1281         s4o.print("(&");
       
  1282         symbol->program_name->accept(*this);
       
  1283         s4o.print(");\n");
       
  1284       }
       
  1285       if (wanted_declaretype == run_dt) {
       
  1286         current_program_name = ((identifier_c*)(symbol->program_name))->value;
       
  1287         if (symbol->task_name != NULL) {
       
  1288           s4o.print(s4o.indent_spaces);
       
  1289           s4o.print("if (!");
       
  1290           symbol->task_name->accept(*this);
       
  1291           s4o.print(") {\n");
       
  1292           s4o.indent_right(); 
       
  1293         }
       
  1294         
       
  1295         wanted_assigntype = assign_at;
       
  1296         if (symbol->prog_conf_elements != NULL)
       
  1297           symbol->prog_conf_elements->accept(*this);
       
  1298         
       
  1299         s4o.print(s4o.indent_spaces);
       
  1300         symbol->program_type_name->accept(*this);
       
  1301         s4o.print(FB_FUNCTION_SUFFIX);
       
  1302         s4o.print("(&");
       
  1303         symbol->program_name->accept(*this);
       
  1304         s4o.print(");\n");
       
  1305         
       
  1306         wanted_assigntype = send_at;
       
  1307         if (symbol->prog_conf_elements != NULL)
       
  1308           symbol->prog_conf_elements->accept(*this);
       
  1309         
       
  1310         if (symbol->task_name != NULL) {
       
  1311           s4o.indent_left();
       
  1312           s4o.print(s4o.indent_spaces + "}\n");
       
  1313         }
       
  1314       }
       
  1315       return NULL;
       
  1316     }
       
  1317     
       
  1318 /*  TASK task_name task_initialization */
       
  1319 //SYM_REF2(task_configuration_c, task_name, task_initialization)
       
  1320     void *visit(task_configuration_c *symbol) {
       
  1321       s4o.print(s4o.indent_spaces + "int ");
       
  1322       symbol->task_name->accept(*this);
       
  1323       s4o.print(" = ");
       
  1324       symbol->task_initialization->accept(*this);
       
  1325       s4o.print(";\n");
       
  1326       return NULL;
       
  1327     }
       
  1328     
       
  1329 /*  '(' [SINGLE ASSIGN data_source ','] [INTERVAL ASSIGN data_source ','] PRIORITY ASSIGN integer ')' */
       
  1330 //SYM_REF4(task_initialization_c, single_data_source, interval_data_source, priority_data_source, unused)
       
  1331     void *visit(task_initialization_c *symbol) {
       
  1332       if (symbol->interval_data_source != NULL) {
       
  1333         calculate_time_c calculate_time;
       
  1334         symbol->interval_data_source->accept(calculate_time);
       
  1335         unsigned long time = calculate_time.get_time();
       
  1336         if (time != 0) {
       
  1337           s4o.print("tick % ");
       
  1338           s4o.print_integer((int)(time / common_ticktime));
       
  1339         }
       
  1340         else
       
  1341           s4o.print("1");
       
  1342       }
       
  1343       else
       
  1344         s4o.print("1");
       
  1345       return NULL;
       
  1346     }
       
  1347 
       
  1348 /*  any_symbolic_variable ASSIGN prog_data_source */
       
  1349 //SYM_REF2(prog_cnxn_assign_c, symbolic_variable, prog_data_source)
       
  1350     void *visit(prog_cnxn_assign_c *symbol) {
       
  1351       if (wanted_assigntype == assign_at) {
       
  1352         symbol_c *var_decl;
       
  1353         unsigned int vartype = 0;
       
  1354         symbol_c *current_var_reference = ((global_var_reference_c *)(symbol->prog_data_source))->global_var_name;
       
  1355         var_decl = search_resource_instance->get_decl(current_var_reference);
       
  1356         if (var_decl == NULL) {
       
  1357           var_decl = search_config_instance->get_decl(current_var_reference);
       
  1358           if (var_decl == NULL)
       
  1359             ERROR;
       
  1360           else
       
  1361             vartype = search_config_instance->get_vartype();
       
  1362         }
       
  1363         else
       
  1364           vartype = search_resource_instance->get_vartype();
       
  1365         
       
  1366         s4o.print(s4o.indent_spaces + "{extern ");
       
  1367         var_decl->accept(*this);
       
  1368         s4o.print(" ");
       
  1369         symbol->prog_data_source->accept(*this);
       
  1370         s4o.print("; ");
       
  1371         s4o.print(current_program_name);
       
  1372         s4o.print(".");
       
  1373         symbol->symbolic_variable->accept(*this);
       
  1374         s4o.print(" = ");
       
  1375         if (vartype || search_var_instance_decl_c::global_vt)
       
  1376           s4o.print("*");
       
  1377         symbol->prog_data_source->accept(*this);
       
  1378         s4o.print(";}\n");
       
  1379       }
       
  1380       return NULL;
       
  1381     }
       
  1382 
       
  1383 /* any_symbolic_variable SENDTO data_sink */
       
  1384 //SYM_REF2(prog_cnxn_sendto_c, symbolic_variable, data_sink)
       
  1385     void *visit(prog_cnxn_sendto_c *symbol) {
       
  1386       if (wanted_assigntype == send_at) {
       
  1387         symbol_c *var_decl;
       
  1388         unsigned int vartype = 0;
       
  1389         symbol_c *current_var_reference = ((global_var_reference_c *)(symbol->data_sink))->global_var_name;
       
  1390         var_decl = search_resource_instance->get_decl(current_var_reference);
       
  1391         if (var_decl == NULL) {
       
  1392           var_decl = search_config_instance->get_decl(current_var_reference);
       
  1393           if (var_decl == NULL)
       
  1394             ERROR;
       
  1395           else
       
  1396             vartype = search_config_instance->get_vartype();
       
  1397         }
       
  1398         else
       
  1399           vartype = search_resource_instance->get_vartype();
       
  1400         
       
  1401         s4o.print(s4o.indent_spaces);
       
  1402         s4o.print(s4o.indent_spaces + "{extern ");
       
  1403         var_decl->accept(*this);
       
  1404         s4o.print(" ");
       
  1405         symbol->data_sink->accept(*this);
       
  1406         s4o.print("; ");
       
  1407         if (vartype || search_var_instance_decl_c::global_vt)
       
  1408           s4o.print("*");
       
  1409         symbol->data_sink->accept(*this);
       
  1410         s4o.print(" = ");
       
  1411         s4o.print(current_program_name);
       
  1412         s4o.print(".");
       
  1413         symbol->symbolic_variable->accept(*this);
       
  1414         s4o.print("};\n");
       
  1415       }
       
  1416       return NULL;
       
  1417     }
       
  1418 
       
  1419 };
       
  1420 
       
  1421 /***********************************************************************/
       
  1422 /***********************************************************************/
       
  1423 /***********************************************************************/
       
  1424 /***********************************************************************/
       
  1425 /***********************************************************************/
       
  1426 /***********************************************************************/
       
  1427 /***********************************************************************/
       
  1428 /***********************************************************************/
       
  1429 
       
  1430 class generate_c_c: public iterator_visitor_c {
       
  1431   protected:
       
  1432     stage4out_c &s4o;
       
  1433     stage4out_c pous_s4o;
       
  1434     stage4out_c located_variables_s4o;
       
  1435     generate_c_pous_c generate_c_pous;
       
  1436 
       
  1437     symbol_c *current_configuration;
       
  1438 
       
  1439     const char *current_name;
       
  1440     const char *current_builddir;
       
  1441 
       
  1442     unsigned long common_ticktime;
       
  1443 
       
  1444   public:
       
  1445     generate_c_c(stage4out_c *s4o_ptr, const char *builddir): 
       
  1446             s4o(*s4o_ptr),
       
  1447             pous_s4o(builddir, "POUS", "c"),
       
  1448             located_variables_s4o(builddir, "LOCATED_VARIABLES","h"),
       
  1449             generate_c_pous(&pous_s4o) {
       
  1450       current_builddir = builddir;
       
  1451       current_configuration = NULL;
       
  1452     }
       
  1453             
       
  1454     ~generate_c_c(void) {}
       
  1455 
       
  1456 /***************************/
       
  1457 /* B 0 - Programming Model */
       
  1458 /***************************/
       
  1459     void *visit(library_c *symbol) {
       
  1460       generate_location_list_c generate_location_list(&located_variables_s4o);
       
  1461       symbol->accept(generate_location_list);
       
  1462       
       
  1463       for(int i = 0; i < symbol->n; i++) {
       
  1464         symbol->elements[i]->accept(*this);
       
  1465       }
       
  1466       return NULL;
       
  1467     }
       
  1468 
       
  1469 /*************************/
       
  1470 /* B.1 - Common elements */
       
  1471 /*************************/
       
  1472 /*******************************************/
       
  1473 /* B 1.1 - Letters, digits and identifiers */
       
  1474 /*******************************************/
       
  1475     void *visit(identifier_c *symbol) {
       
  1476     	current_name = symbol->value;
       
  1477     	return NULL;
       
  1478     }
       
  1479 
       
  1480 /**************************************/
       
  1481 /* B.1.5 - Program organization units */
       
  1482 /**************************************/
       
  1483 /***********************/
       
  1484 /* B 1.5.1 - Functions */
       
  1485 /***********************/
       
  1486     void *visit(function_declaration_c *symbol) {
       
  1487     	symbol->accept(generate_c_pous);
       
  1488     	return NULL;
       
  1489     }
       
  1490     
       
  1491 /*****************************/
       
  1492 /* B 1.5.2 - Function Blocks */
       
  1493 /*****************************/
       
  1494     void *visit(function_block_declaration_c *symbol) {
       
  1495     	symbol->accept(generate_c_pous);
       
  1496     	return NULL;
       
  1497     }
       
  1498     
       
  1499 /**********************/
       
  1500 /* B 1.5.3 - Programs */
       
  1501 /**********************/    
       
  1502     void *visit(program_declaration_c *symbol) {
       
  1503     	symbol->accept(generate_c_pous);
       
  1504     	return NULL;
       
  1505     }
       
  1506     
       
  1507 
       
  1508 /********************************/
       
  1509 /* B 1.7 Configuration elements */
       
  1510 /********************************/
       
  1511     void *visit(configuration_declaration_c *symbol) {
       
  1512   	  static int configuration_count = 0;
       
  1513   
       
  1514       if (configuration_count++) {
       
  1515         /* the first configuration is the one we will use!! */
       
  1516         ERROR;
       
  1517       }
       
  1518       
       
  1519       current_configuration = symbol;
       
  1520       
       
  1521       calculate_common_ticktime_c calculate_common_ticktime;
       
  1522       symbol->accept(calculate_common_ticktime);
       
  1523       common_ticktime = calculate_common_ticktime.get_ticktime();
       
  1524       
       
  1525       symbol->configuration_name->accept(*this);
       
  1526       stage4out_c config_s4o(current_builddir, current_name, "c");
       
  1527       generate_c_config_c generate_c_config(&config_s4o);
       
  1528       symbol->accept(generate_c_config);
       
  1529         
       
  1530       config_s4o.print("int common_ticktime__ = ");
       
  1531       config_s4o.print_integer((int)(common_ticktime / 1000000));
       
  1532       config_s4o.print("; /*ms*/\n");
       
  1533       
       
  1534       symbol->resource_declarations->accept(*this);
       
  1535 
       
  1536       current_configuration = NULL;
       
  1537       
       
  1538       return NULL;
       
  1539     }
       
  1540 
       
  1541     void *visit(resource_declaration_c *symbol) {
       
  1542     	symbol->resource_name->accept(*this);
       
  1543     	stage4out_c resources_s4o(current_builddir, current_name, "c");
       
  1544       generate_c_resources_c generate_c_resources(&resources_s4o, current_configuration, symbol, common_ticktime);
       
  1545     	symbol->accept(generate_c_resources);
       
  1546     	return NULL;
       
  1547     }
       
  1548 
       
  1549     void *visit(single_resource_declaration_c *symbol) {
       
  1550     	stage4out_c resources_s4o(current_builddir, "RESOURCE", "c");
       
  1551       generate_c_resources_c generate_c_resources(&resources_s4o, current_configuration, symbol, common_ticktime);
       
  1552     	symbol->accept(generate_c_resources);
       
  1553     	return NULL;
       
  1554     }
       
  1555     
       
  1556 };
       
  1557 
       
  1558 /***********************************************************************/
       
  1559 /***********************************************************************/
       
  1560 /***********************************************************************/
       
  1561 /***********************************************************************/
       
  1562 /***********************************************************************/
       
  1563 /***********************************************************************/
       
  1564 /***********************************************************************/
       
  1565 /***********************************************************************/
       
  1566 
       
  1567 
       
  1568 
       
  1569 
       
  1570 visitor_c *new_code_generator(stage4out_c *s4o, const char *builddir)  {return new generate_c_c(s4o, builddir);}
       
  1571 void delete_code_generator(visitor_c *code_generator) {delete code_generator;}
       
  1572 
       
  1573