CompileDES  3.13
Executable-Code Generation from Synchronised libFAUDES Automata
cgp_plcoxml.cpp
Go to the documentation of this file.
1 
3 /*
4  FAU Discrete Event Systems Library (libFAUDES)
5 
6  Copyright (C) 2010, 2016, 2017 Thomas Moor
7 
8 */
9 
10 // my includes
11 #include "cgp_plcoxml.h"
12 #include <ctime>
13 
14 
15 /*
16 ******************************************************************
17 ******************************************************************
18 ******************************************************************
19 
20 PlcoxmlCodeGenerator implementation --- class
21 
22 ******************************************************************
23 ******************************************************************
24 ******************************************************************
25 */
26 
27 
28 // Register derived class
30 
31 
32 // PlcoxmlCodeGenerator(void)
34  FD_DCG("PlcoxmlCodeGenerator(" << this << ")::PlcoxmlCodeGenerator()");
35 }
36 
37 
38 // PlcoxmlCodeGenerator(void)
40  FD_DCG("PlcoxmlCodeGenerator(" << this << ")::~PlcoxmlCodeGenerator()");
41 }
42 
43 
44 // clear
46  FD_DCG("PlcoxmlCodeGenerator::Clear()");
47  // call base
49  // my output format defaults
50  mIecSchemeVersion="v2.01";
51  mIecToolVendor="FGDES/LRT";
55  mIecTextElement="cdata";
56  // my code defaults
58 }
59 
60 //DoReadTargetConfiguration(rTr)
62  FD_DCG("PlcoxmlCodeGenerator::DoReadTargetConfiguration()");
63  // base
65  // Plcoxml option
66  Token token;
67  if(rTr.ExistsBegin("IecSchemeVersion")) {
68  rTr.ReadBegin("IecSchemeVersion",token);
69  mIecSchemeVersion= token.AttributeStringValue("val");
70  rTr.ReadEnd("IecSchemeVersion");
71  }
72  if(rTr.ExistsBegin("IecToolVendor")) {
73  rTr.ReadBegin("IecToolVendor",token);
74  mIecToolVendor= token.AttributeStringValue("val");
75  rTr.ReadEnd("IecToolVendor");
76  }
77  if(rTr.ExistsBegin("IecContentAuthor")) {
78  rTr.ReadBegin("IecContentAuthor",token);
79  mIecContentAuthor= token.AttributeStringValue("val");
80  rTr.ReadEnd("IecContentAuthor");
81  }
82  if(rTr.ExistsBegin("IecContentOrganization")) {
83  rTr.ReadBegin("IecContenetOrganization",token);
84  mIecContentOrganization= token.AttributeStringValue("val");
85  rTr.ReadEnd("IecContentOrganization");
86  }
87  if(rTr.ExistsBegin("IecContentVersion")) {
88  rTr.ReadBegin("IecContentVersion",token);
89  mIecContentVersion= token.AttributeStringValue("val");
90  rTr.ReadEnd("IecContentVersion");
91  }
92  if(rTr.ExistsBegin("IecTextElement")) {
93  rTr.ReadBegin("IecTextElement",token);
94  mIecTextElement= token.AttributeStringValue("val");
95  rTr.ReadEnd("IecTextElement");
96  }
97 }
98 
99 //DoWriteTargetConfiguration(rTw)
101  FD_DCG("PlcoxmlCodeGenerator::DoWriteTargetConfiguration()");
102  // base
104  // iec code option
105  Token token;
106  token.SetEmpty("IecSchemeVersion");
107  token.InsAttributeString("val",mIecSchemeVersion);
108  rTw.Write(token);
109  token.SetEmpty("IecToolVendor");
110  token.InsAttributeString("val",mIecToolVendor);
111  rTw.Write(token);
112  if(mIecContentAuthor.size()>0) {
113  token.SetEmpty("IecContentAuthor");
114  token.InsAttributeString("val",mIecContentAuthor);
115  rTw.Write(token);
116  }
117  if(mIecContentOrganization.size()>0) {
118  token.SetEmpty("IecContentCompany");
119  token.InsAttributeString("val",mIecContentOrganization);
120  }
121  if(mIecContentVersion.size()>0) {
122  rTw.Write(token);
123  token.SetEmpty("IecContentVersion");
124  token.InsAttributeString("val",mIecContentVersion);
125  }
126  if(mIecTextElement.size()>0) {
127  rTw.Write(token);
128  token.SetEmpty("IecTextElement");
129  token.InsAttributeString("val",mIecTextElement);
130  rTw.Write(token);
131  }
132 }
133 
134 
135 
136 /*
137 ******************************************************************
138 ******************************************************************
139 ******************************************************************
140 
141 PlcoxmlGenerator implementation --- code organisation
142 
143 ******************************************************************
144 ******************************************************************
145 ******************************************************************
146 */
147 
148 // DoGenerate()
150  // report on missconfig
151  if((mIecSchemeVersion!="v2.01") && (mIecSchemeVersion!="v1.01"))
152  FCG_ERR("PlcoxmlCodeGenerator::DoGenerate(): xml scheme \"" << mIecSchemeVersion << "\" not supported");
153  if((mIecTextElement !="xhtml") && (mIecTextElement !="cdata") && (mIecTextElement !=""))
154  FCG_ERR("PlcoxmlCodeGenerator::DoGenerate(): xml text element \"" << mIecTextElement << "\" not supported");
155  // report on missconfig
156  if(mName.size()==0)
157  FCG_ERR("PlcoxmlCodeGenerator::DoGenerate(): xml format requires a project name");
158  // report on missconfig
159  if(mLiteralCyclic.size()!=0)
160  FCG_ERR("PlcoxmlCodeGenerator::DoGenerate(): literal insert to cyclic function not supported by this target");
161  if(mLiteralPrepend.size()!=0)
162  FCG_ERR("PlcoxmlCodeGenerator::DoGenerate(): literal prepend not supported by this target");
163  if(mLiteralAppend.size()!=0)
164  FCG_ERR("PlcoxmlCodeGenerator::DoGenerate(): literal append not supported by this target");
165  // cut and paste from base
166  mBitarrays.clear();
167  // set up time string
168  time_t now_time;
169  struct tm* now_tm;
170  time (&now_time);
171  now_tm = localtime(&now_time);
172  char now_str[25];
173  snprintf(now_str,24,"%4d-%02d-%02dT%02d:%02d:%02d",now_tm->tm_year+1900,now_tm->tm_mon+1,now_tm->tm_mday,now_tm->tm_hour,now_tm->tm_min,now_tm->tm_sec);
174  std::string datestr(now_str);
175  std::string verstr=COMPILEDES_VERSION;
176  // doit: produce XML encoding
177  Output() << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
178  // doit: open XML project element
179  if(mIecSchemeVersion=="v1.01") {
180  Output() << "<project" << std::endl;
181  Output() << " xmlns=\"http://www.plcopen.org/xml/tc6.xsd\"" << std::endl;
182  Output() << " xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"" << std::endl;
183  Output() << " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" << std::endl;
184  Output() << " xsi:schemaLocation=\"http://www.plcopen.org/xml/tc6.xsd http://www.plcopen.org/xml/tc6.xsd\" >" << std::endl;
185  } else if(mIecSchemeVersion=="v2.01") {
186  Output() << "<project" << std::endl;
187  Output() << " xmlns=\"http://www.plcopen.org/xml/tc6_0201\"" << std::endl;
188  Output() << " xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"" << std::endl;
189  Output() << " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" << std::endl;
190  Output() << " xsi:schemaLocation=\"http://www.plcopen.org/xml/tc6_0201 http://www.plcopen.org/xml/tc6.xsd\" >" << std::endl;
191  } else {
192  Output() << "<project>" << std::endl;
193  }
194  // doit: empty XML fileHeader element
195  Output() << "<fileHeader" << std::endl;
196  Output() << " companyName=\"" << mIecToolVendor << "\"" << std::endl;
197  Output() << " creationDateTime=\"" << datestr << "\"" << std::endl;
198  Output() << " productName=\"CompileDES\"" << std::endl;
199  Output() << " productVersion=\"" << verstr << "\" />" << std::endl;
200  // doit: open XML contentHeader element
201  Output() << "<contentHeader" << std::endl;
202  Output() << " name=\"" << mName << "\"";
203  if(mIecContentAuthor.size()>0) Output() << std::endl << " author=\"" << mIecContentAuthor << "\"";
204  if(mIecContentOrganization.size()>0) Output() << std::endl << " organization=\"" << mIecContentOrganization << "\"";
205  if(mIecContentVersion.size()>0) Output() << std::endl << " version=\"" << mIecContentVersion << "\"";
206  Output() << " >" << std::endl;
207  // doit: complete XML coordinateInfo element
208  Output() << " <coordinateInfo>" << std::endl;
209  Output() << " <fbd><scaling x=\"1\" y=\"1\"/></fbd>" << std::endl;
210  Output() << " <ld><scaling x=\"1\" y=\"1\"/></ld>" << std::endl;
211  Output() << " <sfc><scaling x=\"1\" y=\"1\"/></sfc>" << std::endl;
212  Output() << " </coordinateInfo>" << std::endl;
213  // doit: close XML header element
214  Output() << "</contentHeader>" << std::endl;
215  // doit: open XML types element
216  Output() << "<types>" << std::endl;
217  // doit: empty XML dataTypes element
218  Output() << "<dataTypes />" << std::endl;
219  // doit: open XML pous element
220  Output() << "<pous>" << std::endl;
223  Output() << "</pous>" << std::endl;
224  Output() << "</types>" << std::endl;
225  // doit: void XML instances element
226  Output() << "<instances>" << std::endl;
227  Output() << " <configurations />" << std::endl;
228  Output() << "</instances>" << std::endl;
229  // doit: close XML open elements
230  Output() << "</project>" << std::endl;
231 }
232 
234  // open XML my function block element
235  Output() << "<pou name=\"" << mPrefix << "cyclic_fb" << "\" pouType=\"functionBlock\">" << std::endl;
236  // open XML my interface element
237  Output() << "<interface>" << std::endl;
238  IndentInc();
240  IndentDec();
241  // close XML interface element
242  Output() << "</interface>" << std::endl;
243  // open XML my body element
244  Output() << "<body>" << std::endl;
245  Output() << "<ST>" << std::endl;
246  XmlBeginPlainText();
247  Output() << std::endl;
248  DoGenerateBody();
249  XmlEndPlainText();
250  Output() << std::endl;
251  // close XML open elements
252  Output() << "</ST>" << std::endl;
253  Output() << "</body>" << std::endl;
254  Output() << "</pou>" << std::endl;
255 }
256 
257 
258 // code blocks: cyclic function block (interface)
260  // have counts
261  int pio = CountImportPhysicalIo();
262  int sio = CountImportSymbolicIo();
263  // interface: arguments
264  MuteComments(true);
265  MuteVspace(true);
266  Output() << "<inputVars retain=\"false\">" << std::endl;
267  IndentInc();
268  DeclareReset();
269  IndentDec();
270  Output() << "</inputVars>" << std::endl;
271  MuteComments(false);
272  MuteVspace(false);
273  // interface: return value
274  MuteComments(true);
275  MuteVspace(true);
276  Output() << "<outputVars retain=\"false\">" << std::endl;
277  IndentInc();
278  DeclareStatus();
282  IndentDec();
283  Output() << "</outputVars>" << std::endl;
284  MuteComments(false);
285  MuteVspace(false);
286  // interface: local variables
287  MuteComments(true);
288  MuteVspace(true);
289  Output() << "<localVars retain=\"false\">" << std::endl;
290  IndentInc();
295  DeclareTimers();
296  DeclareAux();
299  if((mIecDeclarePhysical=="VAR") && (pio>0))
301  DeclareSystime();
302  IndentDec();
303  Output() << "</localVars>" << std::endl;
304  MuteVspace(false);
305  MuteComments(false);
306  // interface: extern variables
307  MuteComments(true);
308  MuteVspace(true);
309  if(mIecDeclarePhysical=="VAR_EXTERNAL") {
310  if(pio+sio>0) {
311  Output() << "<externalVars>" << std::endl;
312  IndentInc();
313  if(sio>0) DeclareImportSymbolicIo();
314  if(pio>0) DeclareImportPhysicalIo();
315  IndentDec();
316  Output() << "</externalVars>" << std::endl;
317  }
318  } else {
319  if(sio>0) {
320  Output() << "<externalVars>" << std::endl;
321  IndentInc();
323  IndentDec();
324  Output() << "</externalVars>" << std::endl;
325  }
326  }
327  MuteVspace(false);
328  MuteComments(false);
329 }
330 
331 
332 // code blocks: cyclic function block (body)
334  Comment("************************************************");
335  Comment("CodeGenerator: Target IEC 61131 Structured Text ");
336  Comment("************************************************");
337  LineFeed(2);
338  Comment(std::string("CompileDES ") + VersionString());
339  Comment(std::string("Configuration: ") + Name());
340  LineFeed(2+1);
341  LiteralCyclic();
343  DecrementTimers();
345  LineFeed(1+2);
346  Comment("************************************************");
347  Comment("CodeGenerator: Generated Code Ends Here ");
348  Comment("************************************************");
349 }
350 
351 
353  LineIterator lit=LinesBegin();
354  for(;lit!=LinesEnd();++lit) {
355  std::string lineaddr= lit->second.mAddress;
356  if(lineaddr.size()<1) continue; // paranoia
357  if(lineaddr.at(0)=='%') {
358  Output() << "<variable name=\"\" address=\"" << lineaddr << "\">";
359  LineFeed();
360  IndentInc();
361  Output() << "<type> <BOOL /> </type>";
362  LineFeed();
363  XmlDocumentation("physical input");
364  LineFeed();
365  IndentDec();
366  Output() << "</variable>";
367  LineFeed();
368  }
369  }
371  for(;ait!=ActionAddressesEnd();++ait) {
372  if(!ait->second.mSetClr) continue;
373  std::string actaddr= ait->second.mAddress;
374  if(actaddr.size()<1) continue; // paranoia
375  if(actaddr.at(0)=='%') {
376  Output() << "<variable name=\"\" address=\"" << actaddr << "\">";
377  LineFeed();
378  IndentInc();
379  Output() << "<type> <BOOL /> </type>";
380  LineFeed();
381  XmlDocumentation("physical output");
382  LineFeed();
383  IndentDec();
384  Output() << "</variable>";
385  LineFeed();
386  }
387  }
388 }
389 
390 
391 // code blocks: functions to host lookup tables
393  if(mEventNameLookup) {
394  // open XML my function block element
395  Output() << "<pou name=\"" << mPrefix << "event_lookup_f" << "\" pouType=\"function\">" << std::endl;
396  // open XML my interface element
397  Output() << "<interface>" << std::endl;
398  IndentInc();
399  // interface: return type
400  Output() << "<returnType> <string /> </returnType>" << std::endl;
401  // interface: argument
402  Output() << "<inputVars retain=\"false\">" << std::endl;
403  Output() << " <variable name=\"IDX\">" << std::endl;
404  Output() << " <type> <" << mIntegerType << " /> </type>" << std::endl;
405  Output() << " ";
406  XmlDocumentation("event index");
407  Output() << std::endl;
408  Output() << " </variable>" << std::endl;
409  Output() << "</inputVars>" << std::endl;
410  // interface: local variables
411  MuteComments(true);
412  MuteVspace(true);
413  Output() << "<localVars retain=\"false\" constant=\"true\">" << std::endl;
414  IndentInc();
416  IndentDec();
417  Output() << "</localVars>" << std::endl;
418  MuteVspace(false);
419  MuteComments(false);
420  IndentDec();
421  // close XML interface element
422  Output() << "</interface>" << std::endl;
423  // open XML my body element
424  Output() << "<body>" << std::endl;
425  Output() << "<ST>" << std::endl;
426  XmlBeginPlainText();
427  Output() << mPrefix <<"event_lookup_f" << " := " << mPrefix << "event_lookup[IDX]" << ";";
428  Output() << std::endl;
429  XmlEndPlainText();
430  // close XML open elements
431  Output() << "</ST>" << std::endl;
432  Output() << "</body>" << std::endl;
433  Output() << "</pou>" << std::endl;
434  }
435  if(mStateNameLookup) {
436  // open XML my function block element
437  Output() << "<pou name=\"" << mPrefix << "state_lookup_f" << "\" pouType=\"function\">" << std::endl;
438  // open XML my interface element
439  Output() << "<interface>" << std::endl;
440  IndentInc();
441  // interface: return type
442  Output() << "<returnType> <string /> </returnType>" << std::endl;
443  // interface: argument
444  Output() << "<inputVars retain=\"false\">" << std::endl;
445  Output() << " <variable name=\"GID\">" << std::endl;
446  Output() << " <type> <" << mIntegerType << " /> </type>" << std::endl;
447  Output() << " ";
448  XmlDocumentation("generator id");
449  Output() << std::endl;
450  Output() << " </variable>" << std::endl;
451  Output() << " <variable name=\"IDX\">" << std::endl;
452  Output() << " <type> <" << mIntegerType << " /> </type>" << std::endl;
453  Output() << " ";
454  XmlDocumentation("state index");
455  Output() << std::endl;
456  Output() << " </variable>" << std::endl;
457  Output() << "</inputVars>" << std::endl;
458  // interface: local variables
459  MuteComments(true);
460  MuteVspace(true);
461  Output() << "<localVars retain=\"false\" constant=\"true\">" << std::endl;
462  IndentInc();
464  IndentDec();
465  Output() << "</localVars>" << std::endl;
466  MuteVspace(false);
467  MuteComments(false);
468  IndentDec();
469  // close XML interface element
470  Output() << "</interface>" << std::endl;
471  // open XML my body element
472  Output() << "<body>" << std::endl;
473  Output() << "<ST>" << std::endl;
474  XmlBeginPlainText();
475  Output() << mPrefix << "state_lookup_f:='';";
476  LineFeed();
477  Output() << "CASE GID OF";
478  LineFeed();
479  for(size_t gid=0; gid<Size(); ++gid) {
480  if(!mHasStateNames[gid]) continue;
481  Output() << ToStringInteger(gid) << ": "
482  << mPrefix <<"state_lookup_f" << " := " << mPrefix << "state_lookup_" << ToStringInteger(gid) << "[IDX]" << ";";
483  LineFeed();
484  }
485  Output() << "END_CASE;";
486  LineFeed();
487  Output() << "IF LEN(" << mPrefix << "state_lookup_f) = 0 THEN";
488  LineFeed();
489  Output() << " " << mPrefix <<"state_lookup_f" << " := CONCAT('s'," << mIntegerType << "_TO_STRING(IDX))" << ";";
490  LineFeed();
491  Output() << "END_IF;";
492  Output() << std::endl;
493  XmlEndPlainText();
494  // close XML open elements
495  Output() << "</ST>" << std::endl;
496  Output() << "</body>" << std::endl;
497  Output() << "</pou>" << std::endl;
498  }
499 }
500 
501 
502 /*
503 ******************************************************************
504 ******************************************************************
505 ******************************************************************
506 
507 PlcoxmlCodeGenerator implementation --- code primitives
508 
509 ******************************************************************
510 ******************************************************************
511 ******************************************************************
512 */
513 
514 // switch to/from plain text
515 void PlcoxmlCodeGenerator::XmlBeginPlainText() {
516  if(mIecTextElement=="xhtml") {
517  Output() << "<xhtml xmlns=\"http://www.w3.org/1999/xhtml\">";
518  XmlTextEscape(true);
519  } else if(mIecTextElement=="cdata") {
520  Output() << "<![CDATA[";
521  XmlCdataEscape(true);
522  } else {
523  XmlTextEscape(true);
524  }
525 };
526 
527 // switch to/from plain text
528 void PlcoxmlCodeGenerator::XmlEndPlainText() {
529  if(mIecTextElement=="xhtml") {
530  XmlTextEscape(false);
531  Output() << "</xhtml>";
532  } else if(mIecTextElement=="cdata") {
533  XmlCdataEscape(false);
534  Output() << "]]>";
535  } else {
536  XmlTextEscape(false);
537  }
538 };
539 
540 
541 // switch to/from plain text
542 void PlcoxmlCodeGenerator::XmlDocumentation(const std::string& text) {
543  Output() << "<documentation>";
544  XmlBeginPlainText();
545  Output() << text;
546  XmlEndPlainText();
547  Output() << "</documentation>";
548 };
549 
550 // generate code: declare template
551 void PlcoxmlCodeGenerator::VariableDeclare(const std::string& laddr, const std::string& ltype){
552  Output() << "<variable name=\"" << laddr << "\">";
553  LineFeed();
554  IndentInc();
555  if((ltype == mIntegerType) || (ltype == mWordType) || (ltype == "BOOL") || (ltype == "TIME")) {
556  Output() << "<type> <" << ltype << " /> </type>";
557  } else if((ltype == "TON") || (ltype == "STRING")) {
558  Output() << "<type> <derived name=\"" << ltype << "\" /> </type>";
559  } else {
560  FCG_ERR("PlcoxmlCodeGenerator::VariableDeclare(): unsupported type [" << ltype << "]");
561  }
562  LineFeed();
563  XmlDocumentation(RecentComment());
564  LineFeed();
565  IndentDec();
566  Output() << "</variable>";
567  LineFeed();
568 }
569 
570 // generate code: declare template with initialiser
571 void PlcoxmlCodeGenerator::VariableDeclare(const std::string& laddr, const std::string& ltype, const std::string& lval){
572  Output() << "<variable name=\"" << laddr << "\">";
573  LineFeed();
574  IndentInc();
575  if((ltype == mIntegerType) || (ltype == mWordType) || (ltype == "BOOL") || (ltype == "TIME")) {
576  Output() << "<type> <" << ltype << " /> </type>";
577  } else {
578  FCG_ERR("PlcoxmlCodeGenerator::VariableDeclare(): unsupported type [" << ltype << "]");
579  }
580  LineFeed();
581  Output() << "<initialValue> <simpleValue value=\"" << lval << "\" /> </initialValue>";
582  LineFeed();
583  XmlDocumentation(RecentComment());
584  LineFeed();
585  IndentDec();
586  Output() << "</variable>";
587  LineFeed();
588 }
589 
590 
591 
592 // generate code: const-int-array
593 void PlcoxmlCodeGenerator::CintarrayDeclare(const AA& address, int offset, const std::vector<int>& val) {
594  if(val.size()==0) {
595  FCG_ERR("PlcoxmlCodeGenerator::Cintarray(): ignoring empty const vector");
596  return;
597  }
598  if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
599  FCG_ERR("PlcoxmlCodeGenerator::Cintarray(): const vector exceeds addres range");
600  return;
601  }
602  Output() << "<variable name=\"" << TargetAddress(address) << "\">";
603  LineFeed();
604  IndentInc();
605  Output() << "<type>";
606  LineFeed();
607  Output() << " <array>";
608  LineFeed();
609  Output() << " <dimension lower=\"" << offset << "\" upper=\"" << val.size()+offset-1 << "\" />";
610  LineFeed();
611  Output() << " <baseType> <" << mIntegerType << " /> </baseType>";
612  LineFeed();
613  Output() << " </array>";
614  LineFeed();
615  Output() << "</type>";
616  LineFeed();
617  Output() << "<initialValue> ";
618  LineFeed();
619  Output() << " <arrayValue> ";
620  LineFeed();
621  for(size_t i=0; i<val.size(); ++i) {
622  Output() << " <value> <simpleValue value=\"" << IntegerConstant(val[i]) << "\" /> </value>";
623  LineFeed();
624  }
625  Output() << " </arrayValue> ";
626  LineFeed();
627  Output() << "</initialValue> ";
628  LineFeed();
629  XmlDocumentation(RecentComment());
630  LineFeed();
631  IndentDec();
632  Output() << "</variable>";
633  LineFeed();
634 }
635 
636 // generate code: const-word-array
637 void PlcoxmlCodeGenerator::CwordarrayDeclare(const AA& address, int offset, const std::vector<word_t>& val) {
638  if(val.size()==0) {
639  FCG_ERR("PlcoxmlCodeGenerator::Cwordarray(): ignoring empty const vector");
640  return;
641  }
642  if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
643  FCG_ERR("PlcoxmlCodeGenerator::Cwordarray(): const vector exceeds addres range");
644  return;
645  }
646  Output() << "<variable name=\"" << TargetAddress(address) << "\">";
647  LineFeed();
648  IndentInc();
649  Output() << "<type>";
650  LineFeed();
651  Output() << " <array>";
652  LineFeed();
653  Output() << " <dimension lower=\"" << offset << "\" upper=\"" << val.size()+offset-1 << "\" />";
654  LineFeed();
655  Output() << " <baseType> <" << mWordType << " /> </baseType>";
656  LineFeed();
657  Output() << " </array>";
658  LineFeed();
659  Output() << "</type>";
660  LineFeed();
661  Output() << "<initialValue> ";
662  LineFeed();
663  Output() << " <arrayValue> ";
664  LineFeed();
665  for(size_t i=0; i<val.size(); ++i) {
666  Output() << " <value> <simpleValue value=\"" << WordConstant(val[i]) << "\" /> </value>";
667  LineFeed();
668  }
669  Output() << " </arrayValue> ";
670  LineFeed();
671  Output() << "</initialValue> ";
672  LineFeed();
673  XmlDocumentation(RecentComment());
674  LineFeed();
675  IndentDec();
676  Output() << "</variable>";
677  LineFeed();
678 }
679 
680 
681 // generate code: const-str-array
682 void PlcoxmlCodeGenerator::CstrarrayDeclare(const AA& address, int offset, const std::vector<std::string>& val) {
683  if(val.size()==0) {
684  FCG_ERR("PlcoxmlCodeGenerator::Cstrarray(): ignoring empty const vector");
685  return;
686  }
687  if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
688  FCG_ERR("PlcoxmlCodeGenerator::Cstrarray(): const vector exceeds address range");
689  return;
690  }
691  // figure string size
692  size_t len=0;
693  for(size_t i=0; i<val.size(); ++i)
694  if(val[i].size()>len) len=val[i].size();
695  // generate code
696  Output() << "<variable name=\"" << TargetAddress(address) << "\">";
697  LineFeed();
698  IndentInc();
699  Output() << "<type>";
700  LineFeed();
701  Output() << " <array>";
702  LineFeed();
703  Output() << " <dimension lower=\"" << offset << "\" upper=\"" << val.size()+offset-1 << "\" />";
704  LineFeed();
705  Output() << " <baseType> <string length=\"" << ToStringInteger(len) << "\" /> </baseType>";
706  LineFeed();
707  Output() << " </array>";
708  LineFeed();
709  Output() << "</type>";
710  LineFeed();
711  Output() << "<initialValue> ";
712  LineFeed();
713  Output() << " <arrayValue> ";
714  LineFeed();
715  for(size_t i=0; i<val.size(); ++i) {
716  Output() << " <value> <simpleValue value=\"";
717  XmlTextEscape(true); // use Xml escape
718  std::string dat=StringConstant(val[i]); // use iec string escape
719  // dat = dat.substr(1,dat.size()-2); // strip delimiting single quotes [codesys does not like this]
720  Output() << dat;
721  XmlTextEscape(false);
722  Output()<< "\" /> </value>";
723  LineFeed();
724  }
725  Output() << " </arrayValue> ";
726  LineFeed();
727  Output() << "</initialValue> ";
728  LineFeed();
729  XmlDocumentation(RecentComment());
730  LineFeed();
731  IndentDec();
732  Output() << "</variable>";
733  LineFeed();
734 }
735 
736 // generate code: int-array
737 void PlcoxmlCodeGenerator::IntarrayDeclare(const AA& address, int offset, const std::vector<int>& val) {
738  CintarrayDeclare(address,offset,val);
739 }
740 
741 // generate code: int-array
742 void PlcoxmlCodeGenerator::IntarrayDeclare(const AA& address, int offset, int len) {
743  if(len==0) {
744  FCG_ERR("PlcoxmlCodeGenerator::Intarray(): ignoring empty const vector");
745  return;
746  }
747  if(len+offset >= (1LL << (mIntegerSize-1))) {
748  FCG_ERR("PlcoxmlCodeGenerator::Intarray(): const vector exceeds addres range");
749  return;
750  }
751  Output() << "<variable name=\"" << TargetAddress(address) << "\">";
752  LineFeed();
753  IndentInc();
754  Output() << "<type>";
755  LineFeed();
756  Output() << " <array>";
757  LineFeed();
758  Output() << " <dimension lower=\"" << offset << "\" upper=\"" << len+offset-1 << "\" />";
759  LineFeed();
760  Output() << " <baseType> <" << mIntegerType << " /> </baseType>";
761  LineFeed();
762  Output() << " </array>";
763  LineFeed();
764  Output() << "</type>";
765  LineFeed();
766  XmlDocumentation(RecentComment());
767  LineFeed();
768  IndentDec();
769  Output() << "</variable>";
770  LineFeed();
771 }
772 
773 
774 // generate code: word-array
775 void PlcoxmlCodeGenerator::WordarrayDeclare(const AA& address, int offset, const std::vector<word_t>& val) {
776  CwordarrayDeclare(address,offset,val);
777 }
778 
779 // generate code: word-array
780 void PlcoxmlCodeGenerator::WordarrayDeclare(const AA& address, int offset, int len) {
781  if(len==0) {
782  FCG_ERR("PlcoxmlCodeGenerator::Wordarray(): ignoring empty const vector");
783  return;
784  }
785  if(len+offset >= (1LL << (mIntegerSize-1))) {
786  FCG_ERR("PlcoxmlCodeGenerator::Wordarray(): const vector exceeds addres range");
787  return;
788  }
789  Output() << "<variable name=\"" << TargetAddress(address) << "\">";
790  LineFeed();
791  IndentInc();
792  Output() << "<type>";
793  LineFeed();
794  Output() << " <array>";
795  LineFeed();
796  Output() << " <dimension lower=\"" << offset << "\" upper=\"" << len+offset-1 << "\" />";
797  LineFeed();
798  Output() << " <baseType> <" << mWordType << " /> </baseType>";
799  LineFeed();
800  Output() << " </array>";
801  LineFeed();
802  Output() << "</type>";
803  LineFeed();
804  XmlDocumentation(RecentComment());
805  LineFeed();
806  IndentDec();
807  Output() << "</variable>";
808  LineFeed();
809 }
810 
811 
#define FAUDES_REGISTERCODEGENERATOR(ftype, ctype)
Class registration macro.
Code-generator PlcOpen XML (IEC 61131-3 ST)
virtual void LineFeed(int lines=1)
LineFeed (convenience support for derived classes)
virtual void XmlCdataEscape(bool on)
XmlCdataEscape (escape "]]>")
LineIterator LinesEnd()
Access to line records by iterator.
virtual void XmlTextEscape(bool on)
XmlTextEscape (escape "<", ">", "&", "\"" and "'")
virtual void MuteComments(bool on)
Mute comments (convenience support for derived classes)
std::string RecentComment(void)
Recent muted comment (convenience support for derived classes)
std::map< std::string, LineAddress >::iterator LineIterator
Access to line records by iterator.
virtual void IndentInc()
Indentation (convenience support for derived classes)
LineIterator LinesBegin()
Access to line records by iterator.
int mIntegerSize
compressed boolean capacity of target type integer
virtual std::ostream & Output(void)
Output stream.
virtual void MuteVspace(bool on)
Mute empty lines (convenience support for derived classes)
static std::string VersionString(void)
Version (refers to macro COMPILEDES_VERSION, defined in cgp_codegenerator.h)
virtual const std::string & Name(void) const
Get objects's name (reimplementing base faudes::Type)
Idx Size(void) const
Number of generators.
virtual void IndentDec()
Indentation (convenience support for derived classes)
ActionAddressIterator ActionAddressesEnd()
Access to action addresses by iterator.
std::map< std::string, ActionAddress >::iterator ActionAddressIterator
Access to action record by iterator.
ActionAddressIterator ActionAddressesBegin()
Access to action addresses by iterator.
std::string mName
faudes object name (aka project name)
Abstract address; see also Absstract_Addresses.
virtual void DeclareSmallCarray(void)
Declare bit-mask loop-ups.
virtual void DoGenerateResetCode(void)
cut-and-paste template for code snippet assembly
virtual void DeclareReset(void)
Declare "reset".
virtual void DeclareStatus(void)
Declare "status".
std::string mLiteralPrepend
extra code to prepend
virtual void DeclareRecentEvent(void)
Declare "recent_event".
virtual void DeclareAux(void)
Declare variables local to the provided snippets, e.g. helpers for bit-mask computation.
bool mEventNameLookup
code option: event name lookup
virtual void DeclareEventNameLookup(void)
Declare symbolic name lookup tables.
std::map< std::string, bitarray_rec > mBitarrays
Record of all declared bit-arrays.
bool mStateNameLookup
code option: state name lookup
virtual void DeclareParallelState(void)
Declare "parallel_state".
std::string mIntegerType
target data type for integer
virtual void DeclareLoopState(void)
Declare loop state, i.e. line levels, loop flag.
virtual void DoGenerateCyclicCode(void)
cut-and-paste template for code snippet assembly
std::string mWordType
target data type for word
virtual void DeclareLargeCarray(void)
Declare compiled transition relations.
virtual void DeclareStateNameLookup(void)
Declare symbolic name lookup tables.
std::string mLiteralAppend
extra code to prepend
std::vector< bool > mHasStateNames
record per generator whether there is a lookup table
virtual void DeclarePendingEvents(void)
Declare "pending_events" and "enabled_events".
std::string mPrefix
universal prefix (pseudo name space)
Implementation of primitives by IEC 61131 ST.
virtual void DoReadTargetConfiguration(TokenReader &rTr)
File i/o.
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
File i/o.
virtual void Clear(void)
Clear all data.
virtual void DeclareSystime(void)
generate code: conditionals
virtual AX StringConstant(const std::string &val)
generate code: conditionals
virtual void Comment(const std::string &text)
generate code: conditionals
virtual AX IntegerConstant(int val)
generate code: conditionals
virtual void DecrementTimers(void)
code snippet
std::string mLiteralCyclic
option: extra cyclic code
virtual void DeclareImportSymbolicIo(void)
generate code: conditionals
virtual std::string TargetAddress(const AA &address)
abstract address conversion
virtual int CountImportPhysicalIo(void)
generate code: conditionals
virtual void DeclareTimers(void)
generate code: conditionals
bool mHasIecTimeOperators
option: overloaded operators for time maths
virtual AX WordConstant(word_t val)
generate code: conditionals
virtual int CountImportSymbolicIo(void)
generate code: conditionals
std::string mIecDeclarePhysical
option: formal declaration of io lines
virtual void LiteralCyclic(void)
generate code: conditionals
Target PlcOpen XML (IEC 61131-3 ST)
Definition: cgp_plcoxml.h:91
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
File i/o.
virtual void WordarrayDeclare(const AA &address, int offset, int len)
generate code: conditionals
std::string mIecSchemeVersion
option: plcopen-xml version "v1.01" or "v2.01"
Definition: cgp_plcoxml.h:125
void DoGenerate(void)
code generation hook (overall)
std::string mIecToolVendor
option: xml entry file header "company"
Definition: cgp_plcoxml.h:128
void DoGenerateInterface(void)
code generation (cyclic function, interface)
PlcoxmlCodeGenerator(void)
Constructor.
Definition: cgp_plcoxml.cpp:33
std::string mIecContentAuthor
option: xml entry content header "author"
Definition: cgp_plcoxml.h:131
virtual void DeclareImportPhysicalIo(void)
generate code: conditionals
std::string mIecContentOrganization
option: xml entry content header "company"
Definition: cgp_plcoxml.h:134
void DoGenerateBody(void)
code generation (cyclicg function, st body)
virtual ~PlcoxmlCodeGenerator(void)
Explicit destructor.
Definition: cgp_plcoxml.cpp:39
virtual void Clear(void)
Clear all data.
Definition: cgp_plcoxml.cpp:45
void DoGenerateFunction(void)
code generation hook (cyclic function)
virtual void IntarrayDeclare(const AA &address, int offset, int len)
generate code: conditionals
void DoGenerateLookups(void)
code generation hook (symbolic name lookup functions)
std::string mIecTextElement
option: plain text xml-element "cdata", "xhtml", or "pre"
Definition: cgp_plcoxml.h:140
virtual void CintarrayDeclare(const AA &address, int offset, const std::vector< int > &val)
generate code: conditionals
virtual void DoReadTargetConfiguration(TokenReader &rTr)
File i/o.
Definition: cgp_plcoxml.cpp:61
std::string mIecContentVersion
option: xml entry content header "version"
Definition: cgp_plcoxml.h:137
virtual void CwordarrayDeclare(const AA &address, int offset, const std::vector< word_t > &val)
generate code: conditionals
virtual void VariableDeclare(const std::string &ladd, const std::string &ltype)
generate code: conditionals
virtual void CstrarrayDeclare(const AA &address, int offset, const std::vector< std::string > &val)
generate code: conditionals