stage4/generate_c/generate_c.cc
changeset 907 c3edb882a4b2
parent 906 b225af94405f
child 908 9e8e1ba5ca46
equal deleted inserted replaced
906:b225af94405f 907:c3edb882a4b2
  1189 /***********************************************************************/
  1189 /***********************************************************************/
  1190 /***********************************************************************/
  1190 /***********************************************************************/
  1191 /***********************************************************************/
  1191 /***********************************************************************/
  1192 /***********************************************************************/
  1192 /***********************************************************************/
  1193 
  1193 
  1194 
  1194 class generate_c_pous_c {  
  1195 class generate_c_pous_c: public generate_c_base_c {
  1195   /* NOTE: This is NOT a visistor class!!
       
  1196    * 
       
  1197    *       Actually, it does not even really need to be a class. It is simply a collection of similar functions!!
       
  1198    */ 
       
  1199 
  1196   private:
  1200   private:
  1197     stage4out_c &s4o_incl;
  1201     static void print_end_of_block_label(stage4out_c &s4o) {
  1198     
       
  1199   public:
       
  1200     generate_c_pous_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr)
       
  1201       : generate_c_base_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) {
       
  1202     };
       
  1203     virtual ~generate_c_pous_c(void) {}
       
  1204 
       
  1205   private:
       
  1206     void print_end_of_block_label(void) {
       
  1207       /* Print and __end label for return statements!
  1202       /* Print and __end label for return statements!
  1208        * If label is not used by at least one goto, compiler will generate a warning.
  1203        * If label is not used by at least one goto, compiler will generate a warning.
  1209        * To work around this we introduce the useless goto.
  1204        * To work around this we introduce the useless goto.
  1210        */
  1205        */
  1211       s4o.print("\n");
  1206       s4o.print("\n");
  1225       s4o.print(":\n");
  1220       s4o.print(":\n");
  1226       s4o.indent_right();
  1221       s4o.indent_right();
  1227     }
  1222     }
  1228   
  1223   
  1229 
  1224 
  1230 
  1225     /*************/
       
  1226     /* Functions */
       
  1227     /*************/
  1231   public:
  1228   public:
  1232 /********************/
  1229     /* NOTE: The following function will be called twice:
  1233 /* 2.1.6 - Pragmas  */
  1230      *         1st time:  s4o will reference the .h file, and print_declaration=true
  1234 /********************/
  1231      *                     Here, we generate the function prototypes...
  1235 void *visit(enable_code_generation_pragma_c * symbol)   {s4o.enable_output();  return NULL;}
  1232      *         2nd time:  s4o will reference the .c file, and print_declaration=false
  1236 void *visit(disable_code_generation_pragma_c * symbol)  {s4o.disable_output(); return NULL;} 
  1233      *                     Here we generate the source code!
  1237 
  1234      */
  1238 /*************************/
  1235     /*   FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
  1239 /* B.1 - Common elements */
  1236     /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
  1240 /*************************/
  1237     static void handle_function(function_declaration_c *symbol, stage4out_c &s4o, bool print_declaration) {
  1241 /*******************************************/
  1238       generate_c_vardecl_c *vardecl = NULL;
  1242 /* B 1.1 - Letters, digits and identifiers */
  1239       generate_c_base_c     print_base(&s4o);
  1243 /*******************************************/
  1240       
  1244   /* done in base class(es) */
  1241       TRACE("function_declaration_c");
  1245 
  1242     
  1246 /*********************/
  1243       /* (A) Function declaration... */
  1247 /* B 1.2 - Constants */
  1244       /* (A.1) Function return type */
  1248 /*********************/
  1245       s4o.print("// FUNCTION\n");
  1249   /* originally empty... */
  1246       symbol->type_name->accept(print_base); /* return type */
  1250 
  1247       s4o.print(" ");
  1251 /******************************/
  1248       /* (A.2) Function name */
  1252 /* B 1.2.1 - Numeric Literals */
  1249       symbol->derived_function_name->accept(print_base);
  1253 /******************************/
  1250       s4o.print("(");
  1254   /* done in base class(es) */
  1251     
  1255 
  1252       /* (A.3) Function parameters */
  1256 /*******************************/
  1253       s4o.indent_right();
  1257 /* B.1.2.2   Character Strings */
  1254       vardecl = new generate_c_vardecl_c(&s4o,
  1258 /*******************************/
  1255                                          generate_c_vardecl_c::finterface_vf,
  1259   /* done in base class(es) */
  1256                                          generate_c_vardecl_c::input_vt    |
  1260 
  1257                                          generate_c_vardecl_c::output_vt   |
  1261 /***************************/
  1258                                          generate_c_vardecl_c::inoutput_vt |
  1262 /* B 1.2.3 - Time Literals */
  1259                                          generate_c_vardecl_c::en_vt       |
  1263 /***************************/
  1260                                          generate_c_vardecl_c::eno_vt);
  1264 /************************/
  1261       vardecl->print(symbol->var_declarations_list);
  1265 /* B 1.2.3.1 - Duration */
  1262       delete vardecl;
  1266 /************************/
  1263       
  1267   /* done in base class(es) */
  1264       s4o.indent_left();
  1268 
  1265       
  1269 /************************************/
  1266       s4o.print(")");
  1270 /* B 1.2.3.2 - Time of day and Date */
  1267       
  1271 /************************************/
  1268       /* If we only want the declaration/prototype, then return!! */
  1272   /* done in base class(es) */
  1269       if (print_declaration) 
  1273 
  1270         {s4o.print(";\n"); return;}
  1274 /**********************/
  1271       
  1275 /* B.1.3 - Data types */
  1272       /* continue generating the function definition/code... */
  1276 /**********************/
  1273       s4o.print("\n" + s4o.indent_spaces + "{\n");
  1277 /***********************************/
  1274     
  1278 /* B 1.3.1 - Elementary Data Types */
  1275       /* (B) Function local variable declaration */
  1279 /***********************************/
  1276       /* (B.1) Variables declared in ST source code */
  1280   /* done in base class(es) */
  1277       s4o.indent_right();
  1281 
  1278       
  1282 /********************************/
  1279       vardecl = new generate_c_vardecl_c(&s4o,
  1283 /* B.1.3.2 - Generic data types */
  1280                     generate_c_vardecl_c::localinit_vf,
  1284 /********************************/
  1281                     generate_c_vardecl_c::output_vt   |
  1285   /* originally empty... */
  1282                     generate_c_vardecl_c::inoutput_vt |
  1286 
  1283                     generate_c_vardecl_c::private_vt  |
  1287 /********************************/
  1284                     generate_c_vardecl_c::eno_vt);
  1288 /* B 1.3.3 - Derived data types */
  1285       vardecl->print(symbol->var_declarations_list);
  1289 /********************************/
  1286       delete vardecl;
  1290   /* done in base class(es) */
  1287     
  1291 
  1288       /* (B.2) Temporary variable for function's return value */
  1292 /*********************/
  1289       /* It will have the same name as the function itself! */
  1293 /* B 1.4 - Variables */
  1290       s4o.print(s4o.indent_spaces);
  1294 /*********************/
  1291       symbol->type_name->accept(print_base); /* return type */
  1295   /* done in base class(es) */
  1292       s4o.print(" ");
  1296 
  1293       symbol->derived_function_name->accept(print_base);
  1297 /********************************************/
  1294       s4o.print(" = ");
  1298 /* B.1.4.1   Directly Represented Variables */
  1295       {
  1299 /********************************************/
  1296         /* get the default value of this variable's type */
  1300   /* done in base class(es) */
  1297         symbol_c *default_value = type_initial_value_c::get(symbol->type_name);
  1301 
  1298         if (default_value == NULL) ERROR;
  1302 /*************************************/
  1299         initialization_analyzer_c initialization_analyzer(default_value);
  1303 /* B.1.4.2   Multi-element Variables */
  1300         switch (initialization_analyzer.get_initialization_type()) {
  1304 /*************************************/
  1301           case initialization_analyzer_c::struct_it:
  1305   /* done in base class(es) */
  1302             {
  1306 
  1303               generate_c_structure_initialization_c *structure_initialization = new generate_c_structure_initialization_c(&s4o);
  1307 /******************************************/
  1304               structure_initialization->init_structure_default(symbol->type_name);
  1308 /* B 1.4.3 - Declaration & Initialisation */
  1305               structure_initialization->init_structure_values(default_value);
  1309 /******************************************/
  1306               delete structure_initialization;
  1310   /* done in base class(es) */
  1307             }
  1311 
  1308             break;
  1312 /**************************************/
  1309           case initialization_analyzer_c::array_it:
  1313 /* B.1.5 - Program organization units */
  1310             {
  1314 /**************************************/
  1311               generate_c_array_initialization_c *array_initialization = new generate_c_array_initialization_c(&s4o);
  1315 /***********************/
  1312               array_initialization->init_array_size(symbol->type_name);
  1316 /* B 1.5.1 - Functions */
  1313               array_initialization->init_array_values(default_value);
  1317 /***********************/
  1314               delete array_initialization;
  1318 
  1315             }
  1319 public:
  1316             break;
  1320 /*   FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
  1317           default:
  1321 /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
  1318             default_value->accept(print_base);
  1322 void *visit(function_declaration_c *symbol) {
  1319             break;
  1323   generate_c_vardecl_c *vardecl;
  1320         }
  1324   TRACE("function_declaration_c");
  1321       }
  1325 
  1322       s4o.print(";\n\n");
  1326   /* (A) Function declaration... */
  1323       
  1327   /* (A.1) Function return type */
  1324       s4o.print(s4o.indent_spaces + "// Control execution\n");
  1328   s4o.print("// FUNCTION\n");
  1325       s4o.print(s4o.indent_spaces + "if (!EN) {\n");
  1329   symbol->type_name->accept(*this); /* return type */
  1326       s4o.indent_right();
  1330   s4o.print(" ");
  1327       s4o.print(s4o.indent_spaces + "if (__ENO != NULL) {\n");
  1331   /* (A.2) Function name */
  1328       s4o.indent_right();
  1332   symbol->derived_function_name->accept(*this);
  1329       s4o.print(s4o.indent_spaces + "*__ENO = __BOOL_LITERAL(FALSE);\n");
  1333   s4o.print("(");
  1330       s4o.indent_left();
  1334 
  1331       s4o.print(s4o.indent_spaces + "}\n");
  1335   /* (A.3) Function parameters */
  1332       s4o.print(s4o.indent_spaces + "return ");
  1336   s4o.indent_right();
  1333       symbol->derived_function_name->accept(print_base);
  1337   vardecl = new generate_c_vardecl_c(&s4o,
  1334       s4o.print(";\n");
  1338                                      generate_c_vardecl_c::finterface_vf,
  1335       s4o.indent_left();
  1339                                      generate_c_vardecl_c::input_vt    |
  1336       s4o.print(s4o.indent_spaces + "}\n");
  1340                                      generate_c_vardecl_c::output_vt   |
  1337     
  1341                                      generate_c_vardecl_c::inoutput_vt |
  1338       /* (C) Function body */
  1342                                      generate_c_vardecl_c::en_vt       |
  1339       generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->derived_function_name, symbol);
  1343                                      generate_c_vardecl_c::eno_vt);
  1340       symbol->function_body->accept(generate_c_code);
  1344   vardecl->print(symbol->var_declarations_list);
  1341       
  1345   delete vardecl;
  1342       print_end_of_block_label(s4o);
       
  1343       
       
  1344       vardecl = new generate_c_vardecl_c(&s4o,
       
  1345                     generate_c_vardecl_c::foutputassign_vf,
       
  1346                     generate_c_vardecl_c::output_vt   |
       
  1347                     generate_c_vardecl_c::inoutput_vt |
       
  1348                     generate_c_vardecl_c::eno_vt);
       
  1349       vardecl->print(symbol->var_declarations_list);
       
  1350       delete vardecl;
       
  1351       
       
  1352       s4o.print(s4o.indent_spaces + "return ");
       
  1353       symbol->derived_function_name->accept(print_base);
       
  1354       s4o.print(";\n");
       
  1355       s4o.indent_left();
       
  1356       s4o.print(s4o.indent_spaces + "}\n\n\n");
       
  1357     
       
  1358       return;
       
  1359     }
       
  1360     
       
  1361     
       
  1362     /*******************/
       
  1363     /* Function Blocks */
       
  1364     /*******************/
       
  1365   public:
       
  1366     /* NOTE: The following function will be called twice:
       
  1367      *         1st time:  s4o will reference the .h file, and print_declaration=true
       
  1368      *                     Here, we generate the function prototypes...
       
  1369      *         2nd time:  s4o will reference the .c file, and print_declaration=false
       
  1370      *                     Here we generate the source code!
       
  1371      */
       
  1372     /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
       
  1373     //SYM_REF4(function_block_declaration_c, fblock_name, var_declarations, fblock_body, unused)
       
  1374     static void handle_function_block(function_block_declaration_c *symbol, stage4out_c &s4o, bool print_declaration) {
       
  1375       generate_c_vardecl_c     *vardecl;
       
  1376       generate_c_sfcdecl_c     *sfcdecl;
       
  1377       generate_c_base_c         print_base(&s4o);
       
  1378       TRACE("function_block_declaration_c");
       
  1379     
       
  1380       /* (A) Function Block data structure declaration... */
       
  1381       if (print_declaration) {
       
  1382         /* (A.1) Data structure declaration */
       
  1383         s4o.print("// FUNCTION_BLOCK ");
       
  1384         symbol->fblock_name->accept(print_base);
       
  1385         s4o.print("\n// Data part\n");
       
  1386         s4o.print("typedef struct {\n");
       
  1387         s4o.indent_right();
       
  1388 
       
  1389         /* (A.2) Public variables: i.e. the function parameters... */
       
  1390         s4o.print(s4o.indent_spaces + "// FB Interface - IN, OUT, IN_OUT variables\n");
       
  1391         vardecl = new generate_c_vardecl_c(&s4o,
       
  1392                                            generate_c_vardecl_c::local_vf,
       
  1393                                            generate_c_vardecl_c::input_vt    |
       
  1394                                            generate_c_vardecl_c::output_vt   |
       
  1395                                            generate_c_vardecl_c::inoutput_vt |
       
  1396                                            generate_c_vardecl_c::en_vt       |
       
  1397                                            generate_c_vardecl_c::eno_vt);
       
  1398         vardecl->print(symbol->var_declarations);
       
  1399         delete vardecl;
       
  1400         s4o.print("\n");
       
  1401 
       
  1402         /* (A.3) Private internal variables */
       
  1403         s4o.print(s4o.indent_spaces + "// FB private variables - TEMP, private and located variables\n");
       
  1404         vardecl = new generate_c_vardecl_c(&s4o,
       
  1405                                            generate_c_vardecl_c::local_vf,
       
  1406                                            generate_c_vardecl_c::temp_vt    |
       
  1407                                            generate_c_vardecl_c::private_vt |
       
  1408                                            generate_c_vardecl_c::located_vt |
       
  1409                                            generate_c_vardecl_c::external_vt);
       
  1410         vardecl->print(symbol->var_declarations);
       
  1411         delete vardecl;
       
  1412         
       
  1413         /* (A.4) Generate private internal variables for SFC */
       
  1414         sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol);
       
  1415         sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::sfcdecl_sd);
       
  1416         delete sfcdecl;
       
  1417         s4o.print("\n");
       
  1418       
       
  1419         /* (A.5) Function Block data structure type name. */
       
  1420         s4o.indent_left();
       
  1421         s4o.print("} ");
       
  1422         symbol->fblock_name->accept(print_base);
       
  1423         s4o.print(";\n\n");
       
  1424       }
       
  1425       
       
  1426       if (!print_declaration) {
       
  1427         /* (A.6) Function Block inline function declaration for function invocation */
       
  1428         generate_c_inlinefcall_c *inlinedecl = new generate_c_inlinefcall_c(&s4o, symbol->fblock_name, symbol, FB_FUNCTION_PARAM"->");
       
  1429         symbol->fblock_body->accept(*inlinedecl);
       
  1430         delete inlinedecl;
       
  1431       }
       
  1432       
       
  1433       /* (B) Constructor */
       
  1434       /* (B.1) Constructor name... */
       
  1435       s4o.print(s4o.indent_spaces + "void ");
       
  1436       symbol->fblock_name->accept(print_base);
       
  1437       s4o.print(FB_INIT_SUFFIX);
       
  1438       s4o.print("(");
       
  1439     
       
  1440       /* first and only parameter is a pointer to the data */
       
  1441       symbol->fblock_name->accept(print_base);
       
  1442       s4o.print(" *");
       
  1443       s4o.print(FB_FUNCTION_PARAM);
       
  1444       s4o.print(", BOOL retain)");
       
  1445 
       
  1446       if (print_declaration) {
       
  1447         s4o.print(";\n");
       
  1448       } else {
       
  1449         s4o.print(" {\n");
       
  1450         s4o.indent_right();
       
  1451       
       
  1452         /* (B.2) Member initializations... */
       
  1453         s4o.print(s4o.indent_spaces);
       
  1454         vardecl = new generate_c_vardecl_c(&s4o,
       
  1455                                            generate_c_vardecl_c::constructorinit_vf,
       
  1456                                            generate_c_vardecl_c::input_vt    |
       
  1457                                            generate_c_vardecl_c::output_vt   |
       
  1458                                            generate_c_vardecl_c::inoutput_vt |
       
  1459                                            generate_c_vardecl_c::private_vt  |
       
  1460                                            generate_c_vardecl_c::located_vt  |
       
  1461                                            generate_c_vardecl_c::external_vt |
       
  1462                                            generate_c_vardecl_c::en_vt       |
       
  1463                                            generate_c_vardecl_c::eno_vt);
       
  1464         vardecl->print(symbol->var_declarations, NULL, FB_FUNCTION_PARAM"->");
       
  1465         delete vardecl;
       
  1466         s4o.print("\n");
       
  1467             
       
  1468         /* (B.3) Generate private internal variables for SFC */
       
  1469         sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol, FB_FUNCTION_PARAM"->");
       
  1470         sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::sfcinit_sd);
       
  1471         delete sfcdecl;
       
  1472       
       
  1473         s4o.indent_left();
       
  1474         s4o.print(s4o.indent_spaces + "}\n\n");
       
  1475       }    
       
  1476       
       
  1477       if (!print_declaration) {
       
  1478         /* (C) Function with FB body */
       
  1479         /* (C.1) Step definitions */
       
  1480         sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol, FB_FUNCTION_PARAM"->");
       
  1481         sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::stepdef_sd);
       
  1482       
       
  1483         /* (C.2) Action definitions */
       
  1484         sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::actiondef_sd);
       
  1485         delete sfcdecl;
       
  1486       }
       
  1487       
       
  1488       /* (C.3) Function declaration */
       
  1489       s4o.print("// Code part\n");
       
  1490       /* function interface */
       
  1491       s4o.print("void ");
       
  1492       symbol->fblock_name->accept(print_base);
       
  1493       s4o.print(FB_FUNCTION_SUFFIX);
       
  1494       s4o.print("(");
       
  1495       /* first and only parameter is a pointer to the data */
       
  1496       symbol->fblock_name->accept(print_base);
       
  1497       s4o.print(" *");
       
  1498       s4o.print(FB_FUNCTION_PARAM);
       
  1499       s4o.print(")");
       
  1500 
       
  1501       if (print_declaration) {
       
  1502         s4o.print(";\n");
       
  1503       } else {
       
  1504         s4o.print(" {\n");
       
  1505         s4o.indent_right();
       
  1506       
       
  1507         s4o.print(s4o.indent_spaces + "// Control execution\n");
       
  1508         s4o.print(s4o.indent_spaces + "if (!");
       
  1509         s4o.print(GET_VAR);
       
  1510         s4o.print("(");
       
  1511         s4o.print(FB_FUNCTION_PARAM);
       
  1512         s4o.print("->EN)) {\n");
       
  1513         s4o.indent_right();
       
  1514         s4o.print(s4o.indent_spaces);
       
  1515         s4o.print(SET_VAR);
       
  1516         s4o.print("(");
       
  1517         s4o.print(FB_FUNCTION_PARAM);
       
  1518         s4o.print("->,ENO,,__BOOL_LITERAL(FALSE));\n");
       
  1519         s4o.print(s4o.indent_spaces + "return;\n");
       
  1520         s4o.indent_left();
       
  1521         s4o.print(s4o.indent_spaces + "}\n");
       
  1522         s4o.print(s4o.indent_spaces + "else {\n");
       
  1523         s4o.indent_right();
       
  1524         s4o.print(s4o.indent_spaces);
       
  1525         s4o.print(SET_VAR);
       
  1526         s4o.print("(");
       
  1527         s4o.print(FB_FUNCTION_PARAM);
       
  1528         s4o.print("->,ENO,,__BOOL_LITERAL(TRUE));\n");
       
  1529         s4o.indent_left();
       
  1530         s4o.print(s4o.indent_spaces + "}\n");
       
  1531       
       
  1532         /* (C.4) Initialize TEMP variables */
       
  1533         /* function body */
       
  1534         s4o.print(s4o.indent_spaces + "// Initialise TEMP variables\n");
       
  1535         vardecl = new generate_c_vardecl_c(&s4o,
       
  1536                                            generate_c_vardecl_c::init_vf,
       
  1537                                            generate_c_vardecl_c::temp_vt);
       
  1538         vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
       
  1539         delete vardecl;
       
  1540         s4o.print("\n");
       
  1541       
       
  1542         /* (C.5) Function code */
       
  1543         generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->fblock_name, symbol, FB_FUNCTION_PARAM"->");
       
  1544         symbol->fblock_body->accept(generate_c_code);
       
  1545         print_end_of_block_label(s4o);
       
  1546         s4o.print(s4o.indent_spaces + "return;\n");
       
  1547         s4o.indent_left();
       
  1548         s4o.print(s4o.indent_spaces + "} // ");
       
  1549         symbol->fblock_name->accept(print_base);
       
  1550         s4o.print(FB_FUNCTION_SUFFIX);
       
  1551         s4o.print(s4o.indent_spaces + "() \n\n");
       
  1552       
       
  1553         /* (C.6) Step undefinitions */
       
  1554         sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol, FB_FUNCTION_PARAM"->");
       
  1555         sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::stepundef_sd);
       
  1556       
       
  1557         /* (C.7) Action undefinitions */
       
  1558         sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::actionundef_sd);
       
  1559         delete sfcdecl;
       
  1560       
       
  1561         s4o.indent_left();
       
  1562         s4o.print("\n\n\n\n");
       
  1563       }
       
  1564       return;
       
  1565     }
       
  1566     
       
  1567     
       
  1568     /************/
       
  1569     /* Programs */
       
  1570     /************/
       
  1571   public:
       
  1572     /* NOTE: The following function will be called twice:
       
  1573      *         1st time:  s4o will reference the .h file, and print_declaration=true
       
  1574      *                     Here, we generate the function prototypes...
       
  1575      *         2nd time:  s4o will reference the .c file, and print_declaration=false
       
  1576      *                     Here we generate the source code!
       
  1577      */
       
  1578     /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
       
  1579     //SYM_REF4(program_declaration_c, program_type_name, var_declarations, function_block_body, unused)
       
  1580     static void handle_program(program_declaration_c *symbol, stage4out_c &s4o, bool print_declaration) {
       
  1581       generate_c_vardecl_c     *vardecl;
       
  1582       generate_c_sfcdecl_c     *sfcdecl;
       
  1583       generate_c_base_c         print_base(&s4o);
       
  1584       TRACE("program_declaration_c");
       
  1585     
       
  1586       /* (A) Program data structure declaration... */
       
  1587       if (print_declaration) {      
       
  1588         /* (A.1) Data structure declaration */
       
  1589         s4o.print("// PROGRAM ");
       
  1590         symbol->program_type_name->accept(print_base);
       
  1591         s4o.print("\n// Data part\n");
       
  1592         s4o.print("typedef struct {\n");
       
  1593         s4o.indent_right();
       
  1594       
       
  1595         /* (A.2) Public variables: i.e. the program parameters... */
       
  1596         s4o.print(s4o.indent_spaces + "// PROGRAM Interface - IN, OUT, IN_OUT variables\n");
       
  1597         vardecl = new generate_c_vardecl_c(&s4o,
       
  1598                                            generate_c_vardecl_c::local_vf,
       
  1599                                            generate_c_vardecl_c::input_vt  |
       
  1600                                            generate_c_vardecl_c::output_vt |
       
  1601                                            generate_c_vardecl_c::inoutput_vt);
       
  1602         vardecl->print(symbol->var_declarations);
       
  1603         delete vardecl;
       
  1604         s4o.print("\n");
  1346   
  1605   
  1347   s4o.indent_left();
  1606         /* (A.3) Private internal variables */
  1348   
  1607         s4o.print(s4o.indent_spaces + "// PROGRAM private variables - TEMP, private and located variables\n");
  1349   s4o.print(")\n" + s4o.indent_spaces + "{\n");
  1608         vardecl = new generate_c_vardecl_c(&s4o,
  1350 
  1609                       generate_c_vardecl_c::local_vf,
  1351   /* (B) Function local variable declaration */
  1610                       generate_c_vardecl_c::temp_vt    |
  1352   /* (B.1) Variables declared in ST source code */
  1611                       generate_c_vardecl_c::private_vt |
  1353   s4o.indent_right();
  1612                       generate_c_vardecl_c::located_vt |
  1354   
  1613                       generate_c_vardecl_c::external_vt);
  1355   vardecl = new generate_c_vardecl_c(&s4o,
  1614         vardecl->print(symbol->var_declarations);
  1356                 generate_c_vardecl_c::localinit_vf,
  1615         delete vardecl;
  1357                 generate_c_vardecl_c::output_vt   |
  1616       
  1358                 generate_c_vardecl_c::inoutput_vt |
  1617         /* (A.4) Generate private internal variables for SFC */
  1359                 generate_c_vardecl_c::private_vt  |
  1618         sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol);
  1360                 generate_c_vardecl_c::eno_vt);
  1619         sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::sfcdecl_sd);
  1361   vardecl->print(symbol->var_declarations_list);
  1620         delete sfcdecl;
  1362   delete vardecl;
  1621         s4o.print("\n");
  1363 
  1622         
  1364   /* (B.2) Temporary variable for function's return value */
  1623         /* (A.5) Program data structure type name. */
  1365   /* It will have the same name as the function itself! */
  1624         s4o.indent_left();
  1366   s4o.print(s4o.indent_spaces);
  1625         s4o.print("} ");
  1367   symbol->type_name->accept(*this); /* return type */
  1626         symbol->program_type_name->accept(print_base);
  1368   s4o.print(" ");
  1627         s4o.print(";\n\n");
  1369   symbol->derived_function_name->accept(*this);
  1628       }
  1370   s4o.print(" = ");
  1629       
  1371   {
  1630       if (!print_declaration) {      
  1372     /* get the default value of this variable's type */
  1631         /* (A.6) Function Block inline function declaration for function invocation */
  1373     symbol_c *default_value = type_initial_value_c::get(symbol->type_name);
  1632         generate_c_inlinefcall_c *inlinedecl = new generate_c_inlinefcall_c(&s4o, symbol->program_type_name, symbol, FB_FUNCTION_PARAM"->");
  1374     if (default_value == NULL) ERROR;
  1633         symbol->function_block_body->accept(*inlinedecl);
  1375     initialization_analyzer_c initialization_analyzer(default_value);
  1634         delete inlinedecl;
  1376     switch (initialization_analyzer.get_initialization_type()) {
  1635       }
  1377       case initialization_analyzer_c::struct_it:
  1636     
  1378         {
  1637       /* (B) Constructor */
  1379           generate_c_structure_initialization_c *structure_initialization = new generate_c_structure_initialization_c(&s4o);
  1638       /* (B.1) Constructor name... */
  1380           structure_initialization->init_structure_default(symbol->type_name);
  1639       s4o.print(s4o.indent_spaces + "void ");
  1381           structure_initialization->init_structure_values(default_value);
  1640       symbol->program_type_name->accept(print_base);
  1382           delete structure_initialization;
  1641       s4o.print(FB_INIT_SUFFIX);
  1383         }
  1642       s4o.print("(");
  1384         break;
  1643     
  1385       case initialization_analyzer_c::array_it:
  1644       /* first and only parameter is a pointer to the data */
  1386         {
  1645       symbol->program_type_name->accept(print_base);
  1387           generate_c_array_initialization_c *array_initialization = new generate_c_array_initialization_c(&s4o);
  1646       s4o.print(" *");
  1388           array_initialization->init_array_size(symbol->type_name);
  1647       s4o.print(FB_FUNCTION_PARAM);
  1389           array_initialization->init_array_values(default_value);
  1648       s4o.print(", BOOL retain)");
  1390           delete array_initialization;
  1649 
  1391         }
  1650       if (print_declaration) {
  1392         break;
  1651         s4o.print(";\n");
  1393       default:
  1652       } else {
  1394         default_value->accept(*this);
  1653         s4o.print(" {\n");
  1395         break;
  1654         s4o.indent_right();
  1396     }
  1655       
  1397   }
  1656         /* (B.2) Member initializations... */
  1398   s4o.print(";\n\n");
  1657         s4o.print(s4o.indent_spaces);
  1399   
  1658         vardecl = new generate_c_vardecl_c(&s4o,
  1400   s4o.print(s4o.indent_spaces + "// Control execution\n");
  1659                                            generate_c_vardecl_c::constructorinit_vf,
  1401   s4o.print(s4o.indent_spaces + "if (!EN) {\n");
  1660                                            generate_c_vardecl_c::input_vt    |
  1402   s4o.indent_right();
  1661                                            generate_c_vardecl_c::output_vt   |
  1403   s4o.print(s4o.indent_spaces + "if (__ENO != NULL) {\n");
  1662                                            generate_c_vardecl_c::inoutput_vt |
  1404   s4o.indent_right();
  1663                                            generate_c_vardecl_c::private_vt  |
  1405   s4o.print(s4o.indent_spaces + "*__ENO = __BOOL_LITERAL(FALSE);\n");
  1664                                            generate_c_vardecl_c::located_vt  |
  1406   s4o.indent_left();
  1665                                            generate_c_vardecl_c::external_vt);
  1407   s4o.print(s4o.indent_spaces + "}\n");
  1666         vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
  1408   s4o.print(s4o.indent_spaces + "return ");
  1667         delete vardecl;
  1409   symbol->derived_function_name->accept(*this);
  1668         s4o.print("\n");
  1410   s4o.print(";\n");
  1669       
  1411   s4o.indent_left();
  1670         /* (B.3) Generate private internal variables for SFC */
  1412   s4o.print(s4o.indent_spaces + "}\n");
  1671         sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol, FB_FUNCTION_PARAM"->");
  1413 
  1672         sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::sfcinit_sd);
  1414   /* (C) Function body */
  1673         delete sfcdecl;
  1415   generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->derived_function_name, symbol);
  1674       
  1416   symbol->function_body->accept(generate_c_code);
  1675         s4o.indent_left();
  1417   
  1676         s4o.print(s4o.indent_spaces + "}\n\n");
  1418   print_end_of_block_label();
  1677       }
  1419   
  1678     
  1420   vardecl = new generate_c_vardecl_c(&s4o,
  1679       if (!print_declaration) {    
  1421                 generate_c_vardecl_c::foutputassign_vf,
  1680         /* (C) Function with PROGRAM body */
  1422                 generate_c_vardecl_c::output_vt   |
  1681         /* (C.1) Step definitions */
  1423                 generate_c_vardecl_c::inoutput_vt |
  1682         sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol, FB_FUNCTION_PARAM"->");
  1424                 generate_c_vardecl_c::eno_vt);
  1683         sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::stepdef_sd);
  1425   vardecl->print(symbol->var_declarations_list);
  1684       
  1426   delete vardecl;
  1685         /* (C.2) Action definitions */
  1427   
  1686         sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::actiondef_sd);
  1428   s4o.print(s4o.indent_spaces + "return ");
  1687         delete sfcdecl;
  1429   symbol->derived_function_name->accept(*this);
  1688       }
  1430   s4o.print(";\n");
  1689       
  1431   s4o.indent_left();
  1690       /* (C.3) Function declaration */
  1432   s4o.print(s4o.indent_spaces + "}\n\n\n");
  1691       s4o.print("// Code part\n");
  1433 
  1692       /* function interface */
  1434   return NULL;
  1693       s4o.print("void ");
  1435 }
  1694       symbol->program_type_name->accept(print_base);
  1436 
  1695       s4o.print(FB_FUNCTION_SUFFIX);
  1437 
  1696       s4o.print("(");
  1438 /* The remaining var_declarations_list_c, function_var_decls_c
  1697       /* first and only parameter is a pointer to the data */
  1439  * and var2_init_decl_list_c are handled in the generate_c_vardecl_c class
  1698       symbol->program_type_name->accept(print_base);
  1440  */
  1699       s4o.print(" *");
  1441 
  1700       s4o.print(FB_FUNCTION_PARAM);
  1442 
  1701       s4o.print(")");
  1443 /*****************************/
  1702 
  1444 /* B 1.5.2 - Function Blocks */
  1703       if (print_declaration) {
  1445 /*****************************/
  1704         s4o.print(";\n");
  1446 public:
  1705       } else {
  1447 /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
  1706         s4o.print(" {\n");
  1448 //SYM_REF4(function_block_declaration_c, fblock_name, var_declarations, fblock_body, unused)
  1707         s4o.indent_right();
  1449 void *visit(function_block_declaration_c *symbol) {
  1708           
  1450   generate_c_vardecl_c *vardecl;
  1709         /* (C.4) Initialize TEMP variables */
  1451   generate_c_sfcdecl_c *sfcdecl;
  1710         /* function body */
  1452   generate_c_typedecl_c *typedecl;
  1711         s4o.print(s4o.indent_spaces + "// Initialise TEMP variables\n");
  1453   generate_c_inlinefcall_c *inlinedecl;
  1712         vardecl = new generate_c_vardecl_c(&s4o,
  1454   TRACE("function_block_declaration_c");
  1713                                            generate_c_vardecl_c::init_vf,
  1455 
  1714                                            generate_c_vardecl_c::temp_vt);
  1456   /* (A) Function Block data structure declaration... */
  1715         vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
  1457   typedecl = new generate_c_typedecl_c(&s4o_incl);
  1716         delete vardecl;
  1458   /* (A.1) Data structure declaration */
  1717         s4o.print("\n");
  1459   s4o_incl.print("// FUNCTION_BLOCK ");
  1718       
  1460   symbol->fblock_name->accept(*typedecl);
  1719         /* (C.5) Function code */
  1461   s4o_incl.print("\n// Data part\n");
  1720         generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->program_type_name, symbol, FB_FUNCTION_PARAM"->");
  1462   s4o_incl.print("typedef struct {\n");
  1721         symbol->function_block_body->accept(generate_c_code);
  1463   s4o_incl.indent_right();
  1722         print_end_of_block_label(s4o);
  1464   /* (A.2) Public variables: i.e. the function parameters... */
  1723         s4o.print(s4o.indent_spaces + "return;\n");
  1465   s4o_incl.print(s4o_incl.indent_spaces + "// FB Interface - IN, OUT, IN_OUT variables\n");
  1724         s4o.indent_left();
  1466   vardecl = new generate_c_vardecl_c(&s4o_incl,
  1725         s4o.print(s4o.indent_spaces + "} // ");
  1467                                      generate_c_vardecl_c::local_vf,
  1726         symbol->program_type_name->accept(print_base);
  1468                                      generate_c_vardecl_c::input_vt    |
  1727         s4o.print(FB_FUNCTION_SUFFIX);
  1469                                      generate_c_vardecl_c::output_vt   |
  1728         s4o.print(s4o.indent_spaces + "() \n\n");
  1470                                      generate_c_vardecl_c::inoutput_vt |
  1729       
  1471                                      generate_c_vardecl_c::en_vt       |
  1730         /* (C.6) Step undefinitions */
  1472                                      generate_c_vardecl_c::eno_vt);
  1731         sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol, FB_FUNCTION_PARAM"->");
  1473   vardecl->print(symbol->var_declarations);
  1732         sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::stepundef_sd);
  1474   delete vardecl;
  1733         
  1475   s4o_incl.print("\n");
  1734         /* (C.7) Action undefinitions */
  1476   /* (A.3) Private internal variables */
  1735         sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::actionundef_sd); 
  1477   s4o_incl.print(s4o_incl.indent_spaces + "// FB private variables - TEMP, private and located variables\n");
  1736         delete sfcdecl;
  1478   vardecl = new generate_c_vardecl_c(&s4o_incl,
  1737       
  1479                                      generate_c_vardecl_c::local_vf,
  1738         s4o.indent_left();
  1480                                      generate_c_vardecl_c::temp_vt    |
  1739         s4o.print("\n\n\n\n");
  1481                                      generate_c_vardecl_c::private_vt |
  1740       }  
  1482                                      generate_c_vardecl_c::located_vt |
  1741       return;
  1483                                      generate_c_vardecl_c::external_vt);
  1742     }
  1484   vardecl->print(symbol->var_declarations);
       
  1485   delete vardecl;
       
  1486   
       
  1487   /* (A.4) Generate private internal variables for SFC */
       
  1488   sfcdecl = new generate_c_sfcdecl_c(&s4o_incl, symbol);
       
  1489   sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::sfcdecl_sd);
       
  1490   delete sfcdecl;
       
  1491   s4o_incl.print("\n");
       
  1492 
       
  1493   /* (A.5) Function Block data structure type name. */
       
  1494   s4o_incl.indent_left();
       
  1495   s4o_incl.print("} ");
       
  1496   symbol->fblock_name->accept(*typedecl);
       
  1497   s4o_incl.print(";\n\n");
       
  1498   delete typedecl;
       
  1499 
       
  1500   /* (A.6) Function Block inline function declaration for function invocation */
       
  1501   inlinedecl = new generate_c_inlinefcall_c(&s4o, symbol->fblock_name, symbol, FB_FUNCTION_PARAM"->");
       
  1502   symbol->fblock_body->accept(*inlinedecl);
       
  1503   delete inlinedecl;
       
  1504 
       
  1505   /* (B) Constructor */
       
  1506   /* (B.1) Constructor name... */
       
  1507   s4o.print(s4o.indent_spaces + "void ");
       
  1508   symbol->fblock_name->accept(*this);
       
  1509   s4o.print(FB_INIT_SUFFIX);
       
  1510   s4o.print("(");
       
  1511 
       
  1512   /* first and only parameter is a pointer to the data */
       
  1513   symbol->fblock_name->accept(*this);
       
  1514   s4o.print(" *");
       
  1515   s4o.print(FB_FUNCTION_PARAM);
       
  1516   s4o.print(", BOOL retain) {\n");
       
  1517   s4o.indent_right();
       
  1518 
       
  1519   /* (B.2) Member initializations... */
       
  1520   s4o.print(s4o.indent_spaces);
       
  1521   vardecl = new generate_c_vardecl_c(&s4o,
       
  1522                                      generate_c_vardecl_c::constructorinit_vf,
       
  1523                                      generate_c_vardecl_c::input_vt    |
       
  1524                                      generate_c_vardecl_c::output_vt   |
       
  1525                                      generate_c_vardecl_c::inoutput_vt |
       
  1526                                      generate_c_vardecl_c::private_vt  |
       
  1527                                      generate_c_vardecl_c::located_vt  |
       
  1528                                      generate_c_vardecl_c::external_vt |
       
  1529                                      generate_c_vardecl_c::en_vt       |
       
  1530                                      generate_c_vardecl_c::eno_vt);
       
  1531   vardecl->print(symbol->var_declarations, NULL, FB_FUNCTION_PARAM"->");
       
  1532   delete vardecl;
       
  1533   s4o.print("\n");
       
  1534 
       
  1535   sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol, FB_FUNCTION_PARAM"->");
       
  1536 
       
  1537   /* (B.3) Generate private internal variables for SFC */
       
  1538   sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::sfcinit_sd);
       
  1539 
       
  1540   s4o.indent_left();
       
  1541   s4o.print(s4o.indent_spaces + "}\n\n");
       
  1542 
       
  1543   
       
  1544   /* (C) Function with FB body */
       
  1545   /* (C.1) Step definitions */
       
  1546   sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::stepdef_sd);
       
  1547   
       
  1548   /* (C.2) Action definitions */
       
  1549   sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::actiondef_sd);
       
  1550 
       
  1551   /* (C.3) Function declaration */
       
  1552   s4o.print("// Code part\n");
       
  1553   /* function interface */
       
  1554   s4o.print("void ");
       
  1555   symbol->fblock_name->accept(*this);
       
  1556   s4o.print(FB_FUNCTION_SUFFIX);
       
  1557   s4o.print("(");
       
  1558   /* first and only parameter is a pointer to the data */
       
  1559   symbol->fblock_name->accept(*this);
       
  1560   s4o.print(" *");
       
  1561   s4o.print(FB_FUNCTION_PARAM);
       
  1562   s4o.print(") {\n");
       
  1563   s4o.indent_right();
       
  1564 
       
  1565   s4o.print(s4o.indent_spaces + "// Control execution\n");
       
  1566   s4o.print(s4o.indent_spaces + "if (!");
       
  1567   s4o.print(GET_VAR);
       
  1568   s4o.print("(");
       
  1569   s4o.print(FB_FUNCTION_PARAM);
       
  1570   s4o.print("->EN)) {\n");
       
  1571   s4o.indent_right();
       
  1572   s4o.print(s4o.indent_spaces);
       
  1573   s4o.print(SET_VAR);
       
  1574   s4o.print("(");
       
  1575   s4o.print(FB_FUNCTION_PARAM);
       
  1576   s4o.print("->,ENO,,__BOOL_LITERAL(FALSE));\n");
       
  1577   s4o.print(s4o.indent_spaces + "return;\n");
       
  1578   s4o.indent_left();
       
  1579   s4o.print(s4o.indent_spaces + "}\n");
       
  1580   s4o.print(s4o.indent_spaces + "else {\n");
       
  1581   s4o.indent_right();
       
  1582   s4o.print(s4o.indent_spaces);
       
  1583   s4o.print(SET_VAR);
       
  1584   s4o.print("(");
       
  1585   s4o.print(FB_FUNCTION_PARAM);
       
  1586   s4o.print("->,ENO,,__BOOL_LITERAL(TRUE));\n");
       
  1587   s4o.indent_left();
       
  1588   s4o.print(s4o.indent_spaces + "}\n");
       
  1589 
       
  1590   /* (C.4) Initialize TEMP variables */
       
  1591   /* function body */
       
  1592   s4o.print(s4o.indent_spaces + "// Initialise TEMP variables\n");
       
  1593   vardecl = new generate_c_vardecl_c(&s4o,
       
  1594                                      generate_c_vardecl_c::init_vf,
       
  1595                                      generate_c_vardecl_c::temp_vt);
       
  1596   vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
       
  1597   delete vardecl;
       
  1598   s4o.print("\n");
       
  1599 
       
  1600   /* (C.5) Function code */
       
  1601   generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->fblock_name, symbol, FB_FUNCTION_PARAM"->");
       
  1602   symbol->fblock_body->accept(generate_c_code);
       
  1603   print_end_of_block_label();
       
  1604   s4o.print(s4o.indent_spaces + "return;\n");
       
  1605   s4o.indent_left();
       
  1606   s4o.print(s4o.indent_spaces + "} // ");
       
  1607   symbol->fblock_name->accept(*this);
       
  1608   s4o.print(FB_FUNCTION_SUFFIX);
       
  1609   s4o.print(s4o.indent_spaces + "() \n\n");
       
  1610 
       
  1611   /* (C.6) Step undefinitions */
       
  1612   sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::stepundef_sd);
       
  1613 
       
  1614   /* (C.7) Action undefinitions */
       
  1615   sfcdecl->generate(symbol->fblock_body, generate_c_sfcdecl_c::actionundef_sd);
       
  1616 
       
  1617   delete sfcdecl;
       
  1618 
       
  1619   s4o.indent_left();
       
  1620   s4o.print("\n\n\n\n");
       
  1621 
       
  1622   return NULL;
       
  1623 }
       
  1624 
       
  1625 
       
  1626 /* The remaining temp_var_decls_c, temp_var_decls_list_c
       
  1627  * and non_retentive_var_decls_c are handled in the generate_c_vardecl_c class
       
  1628  */
       
  1629 
       
  1630 
       
  1631 /**********************/
       
  1632 /* B 1.5.3 - Programs */
       
  1633 /**********************/
       
  1634 
       
  1635 
       
  1636 
       
  1637 public:
       
  1638 /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
       
  1639 //SYM_REF4(program_declaration_c, program_type_name, var_declarations, function_block_body, unused)
       
  1640 void *visit(program_declaration_c *symbol) {
       
  1641   generate_c_vardecl_c *vardecl;
       
  1642   generate_c_sfcdecl_c *sfcdecl;
       
  1643   generate_c_typedecl_c *typedecl;
       
  1644   generate_c_inlinefcall_c *inlinedecl;
       
  1645   TRACE("program_declaration_c");
       
  1646 
       
  1647   /* (A) Program data structure declaration... */
       
  1648   typedecl = new generate_c_typedecl_c(&s4o_incl);
       
  1649   /* (A.1) Data structure declaration */
       
  1650   s4o_incl.print("// PROGRAM ");
       
  1651   symbol->program_type_name->accept(*typedecl);
       
  1652   s4o_incl.print("\n// Data part\n");
       
  1653   s4o_incl.print("typedef struct {\n");
       
  1654   s4o_incl.indent_right();
       
  1655 
       
  1656   /* (A.2) Public variables: i.e. the program parameters... */
       
  1657   s4o_incl.print(s4o_incl.indent_spaces + "// PROGRAM Interface - IN, OUT, IN_OUT variables\n");
       
  1658   vardecl = new generate_c_vardecl_c(&s4o_incl,
       
  1659                                      generate_c_vardecl_c::local_vf,
       
  1660                                      generate_c_vardecl_c::input_vt  |
       
  1661                                      generate_c_vardecl_c::output_vt |
       
  1662                                      generate_c_vardecl_c::inoutput_vt);
       
  1663   vardecl->print(symbol->var_declarations);
       
  1664   delete vardecl;
       
  1665   s4o_incl.print("\n");
       
  1666   /* (A.3) Private internal variables */
       
  1667   s4o_incl.print(s4o_incl.indent_spaces + "// PROGRAM private variables - TEMP, private and located variables\n");
       
  1668   vardecl = new generate_c_vardecl_c(&s4o_incl,
       
  1669                 generate_c_vardecl_c::local_vf,
       
  1670                 generate_c_vardecl_c::temp_vt    |
       
  1671                 generate_c_vardecl_c::private_vt |
       
  1672                 generate_c_vardecl_c::located_vt |
       
  1673                 generate_c_vardecl_c::external_vt);
       
  1674   vardecl->print(symbol->var_declarations);
       
  1675   delete vardecl;
       
  1676 
       
  1677   /* (A.4) Generate private internal variables for SFC */
       
  1678   sfcdecl = new generate_c_sfcdecl_c(&s4o_incl, symbol);
       
  1679   sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::sfcdecl_sd);
       
  1680   delete sfcdecl;
       
  1681   s4o_incl.print("\n");
       
  1682   
       
  1683   /* (A.5) Program data structure type name. */
       
  1684   s4o_incl.indent_left();
       
  1685   s4o_incl.print("} ");
       
  1686   symbol->program_type_name->accept(*typedecl);
       
  1687   s4o_incl.print(";\n\n");
       
  1688   delete typedecl;
       
  1689 
       
  1690   /* (A.6) Function Block inline function declaration for function invocation */
       
  1691   inlinedecl = new generate_c_inlinefcall_c(&s4o, symbol->program_type_name, symbol, FB_FUNCTION_PARAM"->");
       
  1692   symbol->function_block_body->accept(*inlinedecl);
       
  1693   delete inlinedecl;
       
  1694 
       
  1695   /* (B) Constructor */
       
  1696   /* (B.1) Constructor name... */
       
  1697   s4o.print(s4o.indent_spaces + "void ");
       
  1698   symbol->program_type_name->accept(*this);
       
  1699   s4o.print(FB_INIT_SUFFIX);
       
  1700   s4o.print("(");
       
  1701 
       
  1702   /* first and only parameter is a pointer to the data */
       
  1703   symbol->program_type_name->accept(*this);
       
  1704   s4o.print(" *");
       
  1705   s4o.print(FB_FUNCTION_PARAM);
       
  1706   s4o.print(", BOOL retain) {\n");
       
  1707   s4o.indent_right();
       
  1708 
       
  1709   /* (B.2) Member initializations... */
       
  1710   s4o.print(s4o.indent_spaces);
       
  1711   vardecl = new generate_c_vardecl_c(&s4o,
       
  1712                                      generate_c_vardecl_c::constructorinit_vf,
       
  1713                                      generate_c_vardecl_c::input_vt    |
       
  1714                                      generate_c_vardecl_c::output_vt   |
       
  1715                                      generate_c_vardecl_c::inoutput_vt |
       
  1716                                      generate_c_vardecl_c::private_vt  |
       
  1717                                      generate_c_vardecl_c::located_vt  |
       
  1718                                      generate_c_vardecl_c::external_vt);
       
  1719   vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
       
  1720   delete vardecl;
       
  1721   s4o.print("\n");
       
  1722 
       
  1723   sfcdecl = new generate_c_sfcdecl_c(&s4o, symbol, FB_FUNCTION_PARAM"->");
       
  1724 
       
  1725   /* (B.3) Generate private internal variables for SFC */
       
  1726   sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::sfcinit_sd);
       
  1727 
       
  1728   s4o.indent_left();
       
  1729   s4o.print(s4o.indent_spaces + "}\n\n");
       
  1730 
       
  1731   /* (C) Function with PROGRAM body */
       
  1732   /* (C.1) Step definitions */
       
  1733   sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::stepdef_sd);
       
  1734   
       
  1735   /* (C.2) Action definitions */
       
  1736   sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::actiondef_sd);
       
  1737 
       
  1738   /* (C.3) Function declaration */
       
  1739   s4o.print("// Code part\n");
       
  1740   /* function interface */
       
  1741   s4o.print("void ");
       
  1742   symbol->program_type_name->accept(*this);
       
  1743   s4o.print(FB_FUNCTION_SUFFIX);
       
  1744   s4o.print("(");
       
  1745   /* first and only parameter is a pointer to the data */
       
  1746   symbol->program_type_name->accept(*this);
       
  1747   s4o.print(" *");
       
  1748   s4o.print(FB_FUNCTION_PARAM);
       
  1749   s4o.print(") {\n");
       
  1750   s4o.indent_right();
       
  1751 
       
  1752   /* (C.4) Initialize TEMP variables */
       
  1753   /* function body */
       
  1754   s4o.print(s4o.indent_spaces + "// Initialise TEMP variables\n");
       
  1755   vardecl = new generate_c_vardecl_c(&s4o,
       
  1756                                      generate_c_vardecl_c::init_vf,
       
  1757                                      generate_c_vardecl_c::temp_vt);
       
  1758   vardecl->print(symbol->var_declarations, NULL,  FB_FUNCTION_PARAM"->");
       
  1759   delete vardecl;
       
  1760   s4o.print("\n");
       
  1761 
       
  1762   /* (C.5) Function code */
       
  1763   generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->program_type_name, symbol, FB_FUNCTION_PARAM"->");
       
  1764   symbol->function_block_body->accept(generate_c_code);
       
  1765   print_end_of_block_label();
       
  1766   s4o.print(s4o.indent_spaces + "return;\n");
       
  1767   s4o.indent_left();
       
  1768   s4o.print(s4o.indent_spaces + "} // ");
       
  1769   symbol->program_type_name->accept(*this);
       
  1770   s4o.print(FB_FUNCTION_SUFFIX);
       
  1771   s4o.print(s4o.indent_spaces + "() \n\n");
       
  1772 
       
  1773   /* (C.6) Step undefinitions */
       
  1774   sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::stepundef_sd);
       
  1775   
       
  1776   /* (C.7) Action undefinitions */
       
  1777   sfcdecl->generate(symbol->function_block_body, generate_c_sfcdecl_c::actionundef_sd);
       
  1778   
       
  1779   delete sfcdecl;
       
  1780 
       
  1781   s4o.indent_left();
       
  1782   s4o.print("\n\n\n\n");
       
  1783 
       
  1784   return NULL;
       
  1785 }
       
  1786 
       
  1787 }; /* generate_c_pous_c */
  1743 }; /* generate_c_pous_c */
  1788 
  1744 
       
  1745     
  1789 /***********************************************************************/
  1746 /***********************************************************************/
  1790 /***********************************************************************/
  1747 /***********************************************************************/
  1791 /***********************************************************************/
  1748 /***********************************************************************/
  1792 /***********************************************************************/
  1749 /***********************************************************************/
  1793 /***********************************************************************/
  1750 /***********************************************************************/
  2524 /***********************************************************************/
  2481 /***********************************************************************/
  2525 /***********************************************************************/
  2482 /***********************************************************************/
  2526 /***********************************************************************/
  2483 /***********************************************************************/
  2527 
  2484 
  2528 class generate_c_c: public iterator_visitor_c {
  2485 class generate_c_c: public iterator_visitor_c {
  2529   public:
       
  2530     typedef enum {
       
  2531       none_gm,
       
  2532       datatypes_gm,
       
  2533       pous_gm
       
  2534     } generate_mode_t;
       
  2535 
       
  2536   protected:
  2486   protected:
  2537     stage4out_c &s4o;
  2487     stage4out_c &s4o;
  2538     stage4out_c pous_s4o;
  2488     stage4out_c pous_s4o;
  2539     stage4out_c pous_incl_s4o;
  2489     stage4out_c pous_incl_s4o;
  2540     stage4out_c located_variables_s4o;
  2490     stage4out_c located_variables_s4o;
  2547     const char *current_name;
  2497     const char *current_name;
  2548     const char *current_builddir;
  2498     const char *current_builddir;
  2549 
  2499 
  2550     unsigned long long common_ticktime;
  2500     unsigned long long common_ticktime;
  2551 
  2501 
  2552     generate_mode_t current_mode;
       
  2553 
       
  2554   public:
  2502   public:
  2555     generate_c_c(stage4out_c *s4o_ptr, const char *builddir): 
  2503     generate_c_c(stage4out_c *s4o_ptr, const char *builddir): 
  2556             s4o(*s4o_ptr),
  2504             s4o(*s4o_ptr),
  2557             pous_s4o(builddir, "POUS", "c"),
  2505             pous_s4o(builddir, "POUS", "c"),
  2558             pous_incl_s4o(builddir, "POUS", "h"),
  2506             pous_incl_s4o(builddir, "POUS", "h"),
  2559             located_variables_s4o(builddir, "LOCATED_VARIABLES","h"),
  2507             located_variables_s4o(builddir, "LOCATED_VARIABLES","h"),
  2560             variables_s4o(builddir, "VARIABLES","csv"),
  2508             variables_s4o(builddir, "VARIABLES","csv"),
  2561             generate_c_datatypes(&pous_incl_s4o),
  2509             generate_c_datatypes(&pous_incl_s4o)
  2562             generate_c_pous(&pous_s4o, &pous_incl_s4o) {
  2510     {
  2563       current_builddir = builddir;
  2511       current_builddir = builddir;
  2564       current_configuration = NULL;
  2512       current_configuration = NULL;
  2565       current_mode = none_gm;
       
  2566     }
  2513     }
  2567             
  2514             
  2568     ~generate_c_c(void) {}
  2515     ~generate_c_c(void) {}
  2569 
  2516 
  2570 
  2517 
  2595 /* B 0 - Programming Model */
  2542 /* B 0 - Programming Model */
  2596 /***************************/
  2543 /***************************/
  2597     void *visit(library_c *symbol) {
  2544     void *visit(library_c *symbol) {
  2598       pous_incl_s4o.print("#ifndef __POUS_H\n#define __POUS_H\n\n#include \"accessor.h\"\n\n");
  2545       pous_incl_s4o.print("#ifndef __POUS_H\n#define __POUS_H\n\n#include \"accessor.h\"\n\n");
  2599 
  2546 
  2600       current_mode = datatypes_gm;
       
  2601       for(int i = 0; i < symbol->n; i++) {
       
  2602         symbol->elements[i]->accept(*this);
       
  2603       }
       
  2604 
       
  2605       current_mode = pous_gm;
       
  2606       for(int i = 0; i < symbol->n; i++) {
  2547       for(int i = 0; i < symbol->n; i++) {
  2607         symbol->elements[i]->accept(*this);
  2548         symbol->elements[i]->accept(*this);
  2608       }
  2549       }
  2609 
  2550 
  2610       pous_incl_s4o.print("#endif //__POUS_H\n");
  2551       pous_incl_s4o.print("#endif //__POUS_H\n");
  2635 /********************************/
  2576 /********************************/
  2636 /* B 1.3.3 - Derived data types */
  2577 /* B 1.3.3 - Derived data types */
  2637 /********************************/
  2578 /********************************/
  2638     /*  TYPE type_declaration_list END_TYPE */
  2579     /*  TYPE type_declaration_list END_TYPE */
  2639     void *visit(data_type_declaration_c *symbol) {
  2580     void *visit(data_type_declaration_c *symbol) {
  2640       switch (current_mode) {
  2581       symbol->accept(generate_c_datatypes);
  2641         case datatypes_gm:
       
  2642           symbol->accept(generate_c_datatypes);
       
  2643           break;
       
  2644         default:
       
  2645           break;
       
  2646       }
       
  2647       return NULL;
  2582       return NULL;
  2648     }
  2583     }
  2649 
  2584 
  2650 /**************************************/
  2585 /**************************************/
  2651 /* B.1.5 - Program organization units */
  2586 /* B.1.5 - Program organization units */
  2652 /**************************************/
  2587 /**************************************/
  2653 /***********************/
  2588 /***********************/
  2654 /* B 1.5.1 - Functions */
  2589 /* B 1.5.1 - Functions */
  2655 /***********************/
  2590 /***********************/
  2656     void *visit(function_declaration_c *symbol) {
  2591     void *visit(function_declaration_c *symbol) {
  2657       switch (current_mode) {
  2592       symbol->var_declarations_list->accept(generate_c_datatypes);
  2658         case datatypes_gm:
  2593       generate_c_pous_c::handle_function(symbol, pous_incl_s4o, true);
  2659           symbol->var_declarations_list->accept(generate_c_datatypes);
  2594       generate_c_pous_c::handle_function(symbol, pous_s4o,      false);
  2660           break;
       
  2661         case pous_gm:
       
  2662           symbol->accept(generate_c_pous);
       
  2663           break;
       
  2664         default:
       
  2665           break;
       
  2666       }
       
  2667       return NULL;
  2595       return NULL;
  2668     }
  2596     }
  2669     
  2597     
  2670 /*****************************/
  2598 /*****************************/
  2671 /* B 1.5.2 - Function Blocks */
  2599 /* B 1.5.2 - Function Blocks */
  2672 /*****************************/
  2600 /*****************************/
  2673     void *visit(function_block_declaration_c *symbol) {
  2601     void *visit(function_block_declaration_c *symbol) {
  2674         switch (current_mode) {
  2602       symbol->var_declarations->accept(generate_c_datatypes);
  2675           case datatypes_gm:
  2603       generate_c_pous_c::handle_function_block(symbol, pous_incl_s4o, true);
  2676             symbol->var_declarations->accept(generate_c_datatypes);
  2604       generate_c_pous_c::handle_function_block(symbol, pous_s4o,      false);
  2677             break;
  2605       return NULL;
  2678           case pous_gm:
       
  2679             symbol->accept(generate_c_pous);
       
  2680             break;
       
  2681           default:
       
  2682             break;
       
  2683         }
       
  2684         return NULL;
       
  2685     }
  2606     }
  2686     
  2607     
  2687 /**********************/
  2608 /**********************/
  2688 /* B 1.5.3 - Programs */
  2609 /* B 1.5.3 - Programs */
  2689 /**********************/    
  2610 /**********************/    
  2690     void *visit(program_declaration_c *symbol) {
  2611     void *visit(program_declaration_c *symbol) {
  2691         switch (current_mode) {
  2612       symbol->var_declarations->accept(generate_c_datatypes);
  2692           case datatypes_gm:
  2613       generate_c_pous_c::handle_program(symbol, pous_incl_s4o, true);
  2693             symbol->var_declarations->accept(generate_c_datatypes);
  2614       generate_c_pous_c::handle_program(symbol, pous_s4o,      false);
  2694             break;
  2615       return NULL;
  2695           case pous_gm:
       
  2696             symbol->accept(generate_c_pous);
       
  2697             break;
       
  2698           default:
       
  2699             break;
       
  2700         }
       
  2701         return NULL;
       
  2702     }
  2616     }
  2703     
  2617     
  2704 
  2618 
  2705 /********************************/
  2619 /********************************/
  2706 /* B 1.7 Configuration elements */
  2620 /* B 1.7 Configuration elements */
  2707 /********************************/
  2621 /********************************/
  2708     void *visit(configuration_declaration_c *symbol) {
  2622     void *visit(configuration_declaration_c *symbol) {
  2709       switch (current_mode) {
  2623       if (symbol->global_var_declarations != NULL)
  2710         case datatypes_gm:
  2624         symbol->global_var_declarations->accept(generate_c_datatypes);
  2711           if (symbol->global_var_declarations != NULL)
  2625       static int configuration_count = 0;
  2712             symbol->global_var_declarations->accept(generate_c_datatypes);
  2626 
  2713           break;
  2627       if (configuration_count++) {
  2714 
  2628         /* the first configuration is the one we will use!! */
  2715         case pous_gm:
  2629         STAGE4_ERROR(symbol, symbol, "A previous CONFIGURATION has already been declared (C code generation currently only allows a single configuration).");
  2716           static int configuration_count = 0;
  2630         ERROR;
  2717 
  2631       }
  2718           if (configuration_count++) {
  2632 
  2719             /* the first configuration is the one we will use!! */
  2633       current_configuration = symbol;
  2720             STAGE4_ERROR(symbol, symbol, "A previous CONFIGURATION has already been declared (C code generation currently only allows a single configuration).");
  2634 
  2721             ERROR;
  2635       {
  2722           }
  2636         calculate_common_ticktime_c calculate_common_ticktime;
  2723 
  2637         symbol->accept(calculate_common_ticktime);
  2724           current_configuration = symbol;
  2638         common_ticktime = calculate_common_ticktime.get_common_ticktime();
  2725 
  2639         if (common_ticktime == 0) {
  2726           {
  2640           STAGE4_ERROR(symbol, symbol, "You must define at least one periodic task (to set cycle period)!");
  2727             calculate_common_ticktime_c calculate_common_ticktime;
  2641           ERROR;
  2728             symbol->accept(calculate_common_ticktime);
  2642         }
  2729             common_ticktime = calculate_common_ticktime.get_common_ticktime();
  2643 
  2730             if (common_ticktime == 0) {
  2644         symbol->configuration_name->accept(*this);
  2731               STAGE4_ERROR(symbol, symbol, "You must define at least one periodic task (to set cycle period)!");
  2645         
  2732               ERROR;
  2646         stage4out_c config_s4o(current_builddir, current_name, "c");
  2733             }
  2647         stage4out_c config_incl_s4o(current_builddir, current_name, "h");
  2734 
  2648         generate_c_config_c generate_c_config(&config_s4o, &config_incl_s4o);
  2735             symbol->configuration_name->accept(*this);
  2649         symbol->accept(generate_c_config);
  2736             
  2650 
  2737             stage4out_c config_s4o(current_builddir, current_name, "c");
  2651         config_s4o.print("unsigned long long common_ticktime__ = ");
  2738             stage4out_c config_incl_s4o(current_builddir, current_name, "h");
  2652         config_s4o.print_long_long_integer(common_ticktime);
  2739             generate_c_config_c generate_c_config(&config_s4o, &config_incl_s4o);
  2653         config_s4o.print("; /*ns*/\n");
  2740             symbol->accept(generate_c_config);
  2654         config_s4o.print("unsigned long greatest_tick_count__ = ");
  2741 
  2655         config_s4o.print_long_integer(calculate_common_ticktime.get_greatest_tick_count());
  2742             config_s4o.print("unsigned long long common_ticktime__ = ");
  2656         config_s4o.print("; /*tick*/\n");
  2743             config_s4o.print_long_long_integer(common_ticktime);
  2657       }
  2744             config_s4o.print("; /*ns*/\n");
  2658 
  2745             config_s4o.print("unsigned long greatest_tick_count__ = ");
  2659       symbol->resource_declarations->accept(*this);
  2746             config_s4o.print_long_integer(calculate_common_ticktime.get_greatest_tick_count());
  2660 
  2747             config_s4o.print("; /*tick*/\n");
  2661       current_configuration = NULL;
  2748           }
       
  2749 
       
  2750           symbol->resource_declarations->accept(*this);
       
  2751 
       
  2752           current_configuration = NULL;
       
  2753           break;
       
  2754 
       
  2755         default:
       
  2756           break;
       
  2757       }
       
  2758       return NULL;
  2662       return NULL;
  2759     }
  2663     }
  2760 
  2664 
  2761     void *visit(resource_declaration_c *symbol) {
  2665     void *visit(resource_declaration_c *symbol) {
  2762       switch (current_mode) {
  2666       if (symbol->global_var_declarations != NULL)
  2763         case datatypes_gm:
  2667         symbol->global_var_declarations->accept(generate_c_datatypes);
  2764           if (symbol->global_var_declarations != NULL)
  2668       symbol->resource_name->accept(*this);
  2765             symbol->global_var_declarations->accept(generate_c_datatypes);
  2669       stage4out_c resources_s4o(current_builddir, current_name, "c");
  2766           break;
  2670       generate_c_resources_c generate_c_resources(&resources_s4o, current_configuration, symbol, common_ticktime);
  2767         case pous_gm:
  2671       symbol->accept(generate_c_resources);
  2768           symbol->resource_name->accept(*this);
       
  2769           {
       
  2770             stage4out_c resources_s4o(current_builddir, current_name, "c");
       
  2771             generate_c_resources_c generate_c_resources(&resources_s4o, current_configuration, symbol, common_ticktime);
       
  2772             symbol->accept(generate_c_resources);
       
  2773           }
       
  2774           break;
       
  2775         default:
       
  2776           break;
       
  2777       }
       
  2778       return NULL;
  2672       return NULL;
  2779     }
  2673     }
  2780 
  2674 
  2781     void *visit(single_resource_declaration_c *symbol) {
  2675     void *visit(single_resource_declaration_c *symbol) {
  2782       switch (current_mode) {
  2676       stage4out_c resources_s4o(current_builddir, "RESOURCE", "c");
  2783         case pous_gm:
  2677       generate_c_resources_c generate_c_resources(&resources_s4o, current_configuration, symbol, common_ticktime);
  2784           {
  2678       symbol->accept(generate_c_resources);
  2785             stage4out_c resources_s4o(current_builddir, "RESOURCE", "c");
       
  2786             generate_c_resources_c generate_c_resources(&resources_s4o, current_configuration, symbol, common_ticktime);
       
  2787             symbol->accept(generate_c_resources);
       
  2788           }
       
  2789           break;
       
  2790         default:
       
  2791           break;
       
  2792       }
       
  2793       return NULL;
  2679       return NULL;
  2794     }
  2680     }
  2795     
  2681     
  2796 };
  2682 };
  2797 
  2683