CompileDES  3.12
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.
virtual void DoGenerateCyclicCode(void)
cut-and-paste template for code snippet assembly
Idx Size(void) const
Number of generators.
void DoGenerate(void)
code generation hook (overall)
Code-generator PlcOpen XML (IEC 61131-3 ST)
virtual void WordarrayDeclare(const AA &address, int offset, int len)
generate code: conditionals
std::string mIecContentVersion
option: xml entry content header "version"
Definition: cgp_plcoxml.h:137
virtual void DeclareStatus(void)
Declare "status".
LineIterator LinesEnd()
Access to line records by iterator.
virtual void DeclareRecentEvent(void)
Declare "recent_event".
virtual void LiteralCyclic(void)
generate code: conditionals
virtual void XmlCdataEscape(bool on)
XmlCdataEscape (escape "]]>")
void DoGenerateInterface(void)
code generation (cyclic function, interface)
std::string mIecContentOrganization
option: xml entry content header "company"
Definition: cgp_plcoxml.h:134
virtual std::ostream & Output(void)
Output stream.
virtual void DoGenerateResetCode(void)
cut-and-paste template for code snippet assembly
virtual void VariableDeclare(const std::string &ladd, const std::string &ltype)
generate code: conditionals
Implementation of primitives by IEC 61131 ST.
virtual void CstrarrayDeclare(const AA &address, int offset, const std::vector< std::string > &val)
generate code: conditionals
virtual void LineFeed(int lines=1)
LineFeed (convenience support for derived classes)
virtual std::string TargetAddress(const AA &address)
abstract address conversion
virtual AX StringConstant(const std::string &val)
generate code: conditionals
std::string mLiteralCyclic
option: extra cyclic code
virtual void MuteComments(bool on)
Mute comments (convenience support for derived classes)
std::string mLiteralAppend
extra code to prepend
std::string mName
faudes object name (aka project name)
virtual AX IntegerConstant(int val)
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 DeclareSmallCarray(void)
Declare bit-mask loop-ups.
virtual void CwordarrayDeclare(const AA &address, int offset, const std::vector< word_t > &val)
generate code: conditionals
virtual void DoReadTargetConfiguration(TokenReader &rTr)
File i/o.
Definition: cgp_plcoxml.cpp:61
virtual void DeclareAux(void)
Declare variables local to the provided snippets, e.g. helpers for bit-mask computation.
void DoGenerateLookups(void)
code generation hook (symbolic name lookup functions)
virtual void DeclareLargeCarray(void)
Declare compiled transition relations.
void DoGenerateFunction(void)
code generation hook (cyclic function)
virtual void DeclareImportSymbolicIo(void)
generate code: conditionals
virtual void DeclareReset(void)
Declare "reset".
void DoGenerateBody(void)
code generation (cyclicg function, st body)
virtual void DeclareTimers(void)
generate code: conditionals
virtual void IndentInc()
Indentation (convenience support for derived classes)
virtual void Clear(void)
Clear all data.
Definition: cgp_plcoxml.cpp:45
virtual void IntarrayDeclare(const AA &address, int offset, int len)
generate code: conditionals
static std::string VersionString(void)
Version (refers to macro COMPILEDES_VERSION, defined in cgp_codegenerator.h)
std::string mIntegerType
target data type for integer
virtual void DeclareStateNameLookup(void)
Declare symbolic name lookup tables.
virtual void DeclareParallelState(void)
Declare "parallel_state".
virtual const std::string & Name(void) const
Get objects&#39;s name (reimplementing base faudes::Type)
int mIntegerSize
compressed boolean capacity of target type integer
virtual AX WordConstant(word_t val)
generate code: conditionals
std::map< std::string, ActionAddress >::iterator ActionAddressIterator
Access to action record by iterator.
std::string mWordType
target data type for word
virtual void DeclareLoopState(void)
Declare loop state, i.e. line levels, loop flag.
bool mEventNameLookup
code option: event name lookup
std::string mIecDeclarePhysical
option: formal declaration of io lines
std::string RecentComment(void)
Recent muted comment (convenience support for derived classes)
virtual void DeclarePendingEvents(void)
Declare "pending_events" and "enabled_events".
std::string mIecContentAuthor
option: xml entry content header "author"
Definition: cgp_plcoxml.h:131
std::string mIecSchemeVersion
option: plcopen-xml version "v1.01" or "v2.01"
Definition: cgp_plcoxml.h:125
virtual void XmlTextEscape(bool on)
XmlTextEscape (escape "<", ">", "&", "\"" and "&#39;")
virtual int CountImportSymbolicIo(void)
generate code: conditionals
ActionAddressIterator ActionAddressesBegin()
Access to action addresses by iterator.
virtual void DeclareEventNameLookup(void)
Declare symbolic name lookup tables.
std::string mIecTextElement
option: plain text xml-element "cdata", "xhtml", or "pre"
Definition: cgp_plcoxml.h:140
virtual void Clear(void)
Clear all data.
Abstract address; see also Absstract_Addresses.
virtual int CountImportPhysicalIo(void)
generate code: conditionals
bool mStateNameLookup
code option: state name lookup
virtual void CintarrayDeclare(const AA &address, int offset, const std::vector< int > &val)
generate code: conditionals
ActionAddressIterator ActionAddressesEnd()
Access to action addresses by iterator.
std::string mPrefix
universal prefix (pseudo name space)
virtual ~PlcoxmlCodeGenerator(void)
Explicit destructor.
Definition: cgp_plcoxml.cpp:39
virtual void IndentDec()
Indentation (convenience support for derived classes)
virtual void DeclareSystime(void)
generate code: conditionals
std::map< std::string, LineAddress >::iterator LineIterator
Access to line records by iterator.
bool mHasIecTimeOperators
option: overloaded operators for time maths
std::string mIecToolVendor
option: xml entry file header "company"
Definition: cgp_plcoxml.h:128
virtual void DoReadTargetConfiguration(TokenReader &rTr)
File i/o.
virtual void DecrementTimers(void)
code snippet
std::map< std::string, bitarray_rec > mBitarrays
Record of all declared bit-arrays.
std::string mLiteralPrepend
extra code to prepend
LineIterator LinesBegin()
Access to line records by iterator.
virtual void Comment(const std::string &text)
generate code: conditionals
virtual void MuteVspace(bool on)
Mute empty lines (convenience support for derived classes)
virtual void DeclareImportPhysicalIo(void)
generate code: conditionals
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
File i/o.
PlcoxmlCodeGenerator(void)
Constructor.
Definition: cgp_plcoxml.cpp:33
std::vector< bool > mHasStateNames
record per generator whether there is a lookup table