CompileDES  3.09
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: function 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" << " := 'out_of_range';";
476  LineFeed();
477  Output() << "CASE GID OF";
478  LineFeed();
479  for(size_t gid=0; gid<Size(); ++gid) {
480  if(mHasStateNames[gid])
481  Output() << ToStringInteger(gid) << ": "
482  << mPrefix <<"state_lookup_f" << " := " << mPrefix << "state_lookup_" << ToStringInteger(gid) << "[IDX]" << ";";
483  else
484  Output() << ToStringInteger(gid) << ": "
485  << mPrefix <<"state_lookup_f" << " := CONCAT('s'," << mIntegerType << "_TO_STRING(IDX))" << ";";
486  LineFeed();
487  }
488  Output() << "END_CASE;";
489  Output() << std::endl;
490  XmlEndPlainText();
491  // close XML open elements
492  Output() << "</ST>" << std::endl;
493  Output() << "</body>" << std::endl;
494  Output() << "</pou>" << std::endl;
495  }
496 }
497 
498 
499 /*
500 ******************************************************************
501 ******************************************************************
502 ******************************************************************
503 
504 PlcoxmlCodeGenerator implementation --- code primitives
505 
506 ******************************************************************
507 ******************************************************************
508 ******************************************************************
509 */
510 
511 // switch to/from plain text
512 void PlcoxmlCodeGenerator::XmlBeginPlainText() {
513  if(mIecTextElement=="xhtml") {
514  Output() << "<xhtml xmlns=\"http://www.w3.org/1999/xhtml\">";
515  XmlTextEscape(true);
516  } else if(mIecTextElement=="cdata") {
517  Output() << "<![CDATA[";
518  XmlCdataEscape(true);
519  } else {
520  XmlTextEscape(true);
521  }
522 };
523 
524 // switch to/from plain text
525 void PlcoxmlCodeGenerator::XmlEndPlainText() {
526  if(mIecTextElement=="xhtml") {
527  XmlTextEscape(false);
528  Output() << "</xhtml>";
529  } else if(mIecTextElement=="cdata") {
530  XmlCdataEscape(false);
531  Output() << "]]>";
532  } else {
533  XmlTextEscape(false);
534  }
535 };
536 
537 
538 // switch to/from plain text
539 void PlcoxmlCodeGenerator::XmlDocumentation(const std::string& text) {
540  Output() << "<documentation>";
541  XmlBeginPlainText();
542  Output() << text;
543  XmlEndPlainText();
544  Output() << "</documentation>";
545 };
546 
547 // generate code: declare template
548 void PlcoxmlCodeGenerator::VariableDeclare(const std::string& laddr, const std::string& ltype){
549  Output() << "<variable name=\"" << laddr << "\">";
550  LineFeed();
551  IndentInc();
552  if((ltype == mIntegerType) || (ltype == mWordType) || (ltype == "BOOL") || (ltype == "TIME")) {
553  Output() << "<type> <" << ltype << " /> </type>";
554  } else if((ltype == "TON") || (ltype == "STRING")) {
555  Output() << "<type> <derived name=\"" << ltype << "\" /> </type>";
556  } else {
557  FCG_ERR("PlcoxmlCodeGenerator::VariableDeclare(): unsupported type [" << ltype << "]");
558  }
559  LineFeed();
560  XmlDocumentation(RecentComment());
561  LineFeed();
562  IndentDec();
563  Output() << "</variable>";
564  LineFeed();
565 }
566 
567 // generate code: declare template with initialiser
568 void PlcoxmlCodeGenerator::VariableDeclare(const std::string& laddr, const std::string& ltype, const std::string& lval){
569  Output() << "<variable name=\"" << laddr << "\">";
570  LineFeed();
571  IndentInc();
572  if((ltype == mIntegerType) || (ltype == mWordType) || (ltype == "BOOL") || (ltype == "TIME")) {
573  Output() << "<type> <" << ltype << " /> </type>";
574  } else {
575  FCG_ERR("PlcoxmlCodeGenerator::VariableDeclare(): unsupported type [" << ltype << "]");
576  }
577  LineFeed();
578  Output() << "<initialValue> <simpleValue value=\"" << lval << "\" /> </initialValue>";
579  LineFeed();
580  XmlDocumentation(RecentComment());
581  LineFeed();
582  IndentDec();
583  Output() << "</variable>";
584  LineFeed();
585 }
586 
587 
588 
589 // generate code: const-int-array
590 void PlcoxmlCodeGenerator::CintarrayDeclare(const AA& address, const std::vector<int>& val) {
591  if(val.size()==0) {
592  FCG_ERR("PlcoxmlCodeGenerator::Cintarray(): ignoring empty const vector");
593  return;
594  }
595  if(val.size()>= (1ULL << (mIntegerSize-1))) {
596  FCG_ERR("PlcoxmlCodeGenerator::Cintarray(): const vector exceeds addres range");
597  return;
598  }
599  Output() << "<variable name=\"" << TargetAddress(address) << "\">";
600  LineFeed();
601  IndentInc();
602  Output() << "<type>";
603  LineFeed();
604  Output() << " <array>";
605  LineFeed();
606  Output() << " <dimension lower=\"0\" upper=\"" << val.size()-1 << "\" />";
607  LineFeed();
608  Output() << " <baseType> <" << mIntegerType << " /> </baseType>";
609  LineFeed();
610  Output() << " </array>";
611  LineFeed();
612  Output() << "</type>";
613  LineFeed();
614  Output() << "<initialValue> ";
615  LineFeed();
616  Output() << " <arrayValue> ";
617  LineFeed();
618  for(size_t i=0; i<val.size(); ++i) {
619  Output() << " <value> <simpleValue value=\"" << IntegerConstant(val[i]) << "\" /> </value>";
620  LineFeed();
621  }
622  Output() << " </arrayValue> ";
623  LineFeed();
624  Output() << "</initialValue> ";
625  LineFeed();
626  XmlDocumentation(RecentComment());
627  LineFeed();
628  IndentDec();
629  Output() << "</variable>";
630  LineFeed();
631 }
632 
633 // generate code: const-word-array
634 void PlcoxmlCodeGenerator::CwordarrayDeclare(const AA& address, const std::vector<word_t>& val) {
635  if(val.size()==0) {
636  FCG_ERR("PlcoxmlCodeGenerator::Cwordarray(): ignoring empty const vector");
637  return;
638  }
639  if(val.size()>= (1ULL << (mIntegerSize-1))) {
640  FCG_ERR("PlcoxmlCodeGenerator::Cwordarray(): const vector exceeds addres range");
641  return;
642  }
643  Output() << "<variable name=\"" << TargetAddress(address) << "\">";
644  LineFeed();
645  IndentInc();
646  Output() << "<type>";
647  LineFeed();
648  Output() << " <array>";
649  LineFeed();
650  Output() << " <dimension lower=\"0\" upper=\"" << val.size()-1 << "\" />";
651  LineFeed();
652  Output() << " <baseType> <" << mWordType << " /> </baseType>";
653  LineFeed();
654  Output() << " </array>";
655  LineFeed();
656  Output() << "</type>";
657  LineFeed();
658  Output() << "<initialValue> ";
659  LineFeed();
660  Output() << " <arrayValue> ";
661  LineFeed();
662  for(size_t i=0; i<val.size(); ++i) {
663  Output() << " <value> <simpleValue value=\"" << WordConstant(val[i]) << "\" /> </value>";
664  LineFeed();
665  }
666  Output() << " </arrayValue> ";
667  LineFeed();
668  Output() << "</initialValue> ";
669  LineFeed();
670  XmlDocumentation(RecentComment());
671  LineFeed();
672  IndentDec();
673  Output() << "</variable>";
674  LineFeed();
675 }
676 
677 
678 // generate code: const-str-array
679 void PlcoxmlCodeGenerator::CstrarrayDeclare(const AA& address, const std::vector<std::string>& val) {
680  if(val.size()==0) {
681  FCG_ERR("PlcoxmlCodeGenerator::Cstrarray(): ignoring empty const vector");
682  return;
683  }
684  if(val.size()>= (1ULL << (mIntegerSize-1))) {
685  FCG_ERR("PlcoxmlCodeGenerator::Cstrarray(): const vector exceeds address range");
686  return;
687  }
688  // figure string size
689  size_t len=0;
690  for(size_t i=0; i<val.size(); ++i)
691  if(val[i].size()>len) len=val[i].size();
692  // generate code
693  Output() << "<variable name=\"" << TargetAddress(address) << "\">";
694  LineFeed();
695  IndentInc();
696  Output() << "<type>";
697  LineFeed();
698  Output() << " <array>";
699  LineFeed();
700  Output() << " <dimension lower=\"0\" upper=\"" << val.size()-1 << "\" />";
701  LineFeed();
702  Output() << " <baseType> <string length=\"" << ToStringInteger(len) << "\" /> </baseType>";
703  LineFeed();
704  Output() << " </array>";
705  LineFeed();
706  Output() << "</type>";
707  LineFeed();
708  Output() << "<initialValue> ";
709  LineFeed();
710  Output() << " <arrayValue> ";
711  LineFeed();
712  for(size_t i=0; i<val.size(); ++i) {
713  Output() << " <value> <simpleValue value=\"";
714  XmlTextEscape(true); // use Xml escape
715  std::string dat=StringConstant(val[i]); // use iec string escape
716  // dat = dat.substr(1,dat.size()-2); // strip delimiting single quotes [codesys does not like this]
717  Output() << dat;
718  XmlTextEscape(false);
719  Output()<< "\" /> </value>";
720  LineFeed();
721  }
722  Output() << " </arrayValue> ";
723  LineFeed();
724  Output() << "</initialValue> ";
725  LineFeed();
726  XmlDocumentation(RecentComment());
727  LineFeed();
728  IndentDec();
729  Output() << "</variable>";
730  LineFeed();
731 }
732 
733 // generate code: int-array
734 void PlcoxmlCodeGenerator::IntarrayDeclare(const AA& address, const std::vector<int>& val) {
735  CintarrayDeclare(address,val);
736 }
737 
738 // generate code: int-array
739 void PlcoxmlCodeGenerator::IntarrayDeclare(const AA& address, int len) {
740  if(len==0) {
741  FCG_ERR("PlcoxmlCodeGenerator::Intarray(): ignoring empty const vector");
742  return;
743  }
744  if(len>= (1LL << (mIntegerSize-1))) {
745  FCG_ERR("PlcoxmlCodeGenerator::Intarray(): const vector exceeds addres range");
746  return;
747  }
748  Output() << "<variable name=\"" << TargetAddress(address) << "\">";
749  LineFeed();
750  IndentInc();
751  Output() << "<type>";
752  LineFeed();
753  Output() << " <array>";
754  LineFeed();
755  Output() << " <dimension lower=\"0\" upper=\"" << len-1 << "\" />";
756  LineFeed();
757  Output() << " <baseType> <" << mIntegerType << " /> </baseType>";
758  LineFeed();
759  Output() << " </array>";
760  LineFeed();
761  Output() << "</type>";
762  LineFeed();
763  XmlDocumentation(RecentComment());
764  LineFeed();
765  IndentDec();
766  Output() << "</variable>";
767  LineFeed();
768 }
769 
770 
771 // generate code: word-array
772 void PlcoxmlCodeGenerator::WordarrayDeclare(const AA& address, const std::vector<word_t>& val) {
773  CwordarrayDeclare(address,val);
774 }
775 
776 // generate code: word-array
777 void PlcoxmlCodeGenerator::WordarrayDeclare(const AA& address, int len) {
778  if(len==0) {
779  FCG_ERR("PlcoxmlCodeGenerator::Wordarray(): ignoring empty const vector");
780  return;
781  }
782  if(len>= (1LL << (mIntegerSize-1))) {
783  FCG_ERR("PlcoxmlCodeGenerator::Wordarray(): const vector exceeds addres range");
784  return;
785  }
786  Output() << "<variable name=\"" << TargetAddress(address) << "\">";
787  LineFeed();
788  IndentInc();
789  Output() << "<type>";
790  LineFeed();
791  Output() << " <array>";
792  LineFeed();
793  Output() << " <dimension lower=\"0\" upper=\"" << len-1 << "\" />";
794  LineFeed();
795  Output() << " <baseType> <" << mWordType << " /> </baseType>";
796  LineFeed();
797  Output() << " </array>";
798  LineFeed();
799  Output() << "</type>";
800  LineFeed();
801  XmlDocumentation(RecentComment());
802  LineFeed();
803  IndentDec();
804  Output() << "</variable>";
805  LineFeed();
806 }
807 
808