CompileDES  3.09
Executable-Code Generation from Synchronised libFAUDES Automata
cgp_embeddedc.cpp
Go to the documentation of this file.
1 
3 /*
4  FAU Discrete Event Systems Library (libFAUDES)
5 
6  Copyright (C) 2010, 2016 Thomas Moor
7 
8 */
9 
10 // my includes
11 #include "cgp_embeddedc.h"
12 
13 
14 /*
15 ******************************************************************
16 ******************************************************************
17 ******************************************************************
18 
19 EmbeddedcCodeGenerator implementation
20 
21 ******************************************************************
22 ******************************************************************
23 ******************************************************************
24 */
25 
26 // Register derived class
28 
29 
30 // EmbeddedcCodeGenerator(void)
32  FD_DCG("EmbeddedcCodeGenerator(" << this << ")::EmbeddedcCodeGenerator()");
33 }
34 
35 
36 // EmbeddedcCodeGenerator(void)
38  FD_DCG("EmbeddedcCodeGenerator(" << this << ")::~EmbeddedcCodeGenerator()");
39 }
40 
41 // clear
43  FD_DCG("EmbeddedcCodeGenerator::Clear()");
44  // call base
46  // my flavor of defaults
47  mPrefix="fcg_";
48  mWordType="unsigned char";
49  mWordSize=8;
50  mIntegerType="int";
51  mIntegerSize=16;
52 }
53 
54 //DoReadTargetConfiguration(rTr)
56  FD_DCG("EmbeddedcCodeGenerator::DoReadTargetConfiguration()");
57  // base
59 }
60 
61 //DoWriteTargetConfiguration(rTw)
63  FD_DCG("EmbeddedcCodeGenerator::DoWriteTargetConfiguration()");
64  // base
66 }
67 
68 // DoCompile()
70  // call base
72  // my preferences
74  FCG_VERB1("EmbeddedcCodeGenerator::Compile(): prefer compiled bitmasks over bit-address maths");
75  mBitAddressArithmetic = false;
76  }
77 }
78 
79 
80 // DoGenerate()
82  FD_DCG("EmbeddedcCodeGenerator(" << this << ")::DoGenerate()");
83  // cut and paste from base
84  mBitarrays.clear();
85  // say hello
86  Comment("************************************************");
87  Comment("CodeGenerator: Target Embedded C ");
88  Comment("************************************************");
89  LineFeed(1);
90  Comment(std::string("CompileDES ") + VersionString());
91  Comment(std::string("Configuration: ") + Name());
92  LineFeed(2+1);
93  // base class snippets
96  // cyclic function
97  LineFeed(2);
98  Output() << "void " << mPrefix << "cyclic(void) { ";
99  LineFeed();
102  Output() << "}; /* end function " << mPrefix << "cyclic() */";
103  LineFeed();
104  LineFeed(2+1);
105  // extra: provide timer decrement interface to host application
106  DecrementTimers();
107  // snippets
108  LiteralAppend();
109  Comment("************************************************");
110  Comment("CodeGenerator: Generated Code Ends Here ");
111  Comment("************************************************");
112 }
113 
114 
115 
116 // code blocks: organise time decrement as function to be periodically
117 // invoked by the host application
119  // timer update function
120  if(TimersBegin()!=TimersEnd()) {
121  Comment("************************************************");
122  Comment("* update timer states *");
123  Comment("************************************************");
124  LineFeed(2);
125  Output() << "void " << mPrefix <<"timerdec(int dec) { ";
126  LineFeed();
127  IndentInc();
128  TimerIterator tit= TimersBegin();
129  for(;tit!=TimersEnd();++tit) {
130  Output() << "if( " << TargetAddress(AA("timer_" + tit->second.mAddress + "_run")) << " ) "
131  << TargetAddress(AA("timer_" + tit->second.mAddress + "_cnt")) << " -= dec;";
132  LineFeed();
133  }
134  IndentDec();
135  Output() << "};";
136  LineFeed();
137  LineFeed(1+2);
138  }
139 }
140 
141 // generate code
143  if((mEventExecutionHook!="") || (mStateUpdateHook!="")) {
144  Comment("call hooks");
145  if(mEventExecutionHook!="") {
146  std::string hook = mEventExecutionHook + "(" + TargetExpression(AA("exec_event")) + ");";
147  Output() << hook;
148  LineFeed(1);
149  }
150  if(mStateUpdateHook!="") {
151  std::string hook = mStateUpdateHook + "(" + TargetAddress(AA("parallel_state")) + ");";
152  Output() << hook;
153  LineFeed(1);
154  }
155  LineFeed(1);
156  }
157 }
158 
159 // generate code
160 void EmbeddedcCodeGenerator::Comment(const std::string& text) {
161  // write comment
162  if(!mMuteComments) {
163  Output() << "/* " << text << " */";
164  LineFeed();
165  }
166  // call base to record muted comments
168 }
169 
170 // address transformation
171 std::string EmbeddedcCodeGenerator::TargetAddress(const AA& address) {
172  // should so some mangeling to replace non-ascii / funny characters
173  std::string res=mPrefix+address;
174  return res;
175 }
176 
177 // address transformation
179  return AX(TargetAddress(address));
180 }
181 
182 // generate code: integer
183 void EmbeddedcCodeGenerator::IntegerDeclare(const AA& address){
184  Output() << "static " << mIntegerType << " " << TargetAddress(address) << ";";
185  LineFeed();
186 }
187 
188 // generate code: integer
189 void EmbeddedcCodeGenerator::IntegerDeclare(const AA& address, int val){
190  Output() << "static " << mIntegerType << " " << TargetAddress(address) << "=" << val << ";";
191  LineFeed();
192 }
193 
194 // generate code: integer
195 void EmbeddedcCodeGenerator::IntegerAssign(const AA& address, int val){
196  Output() << TargetAddress(address) << " = " << IntegerConstant(val) << ";";
197  LineFeed();
198 }
199 
200 // generate code: integer
201 void EmbeddedcCodeGenerator::IntegerAssign(const AA& address, const AX& expression){
202  Output() << TargetAddress(address) << " = " << expression << ";";
203  LineFeed();
204 }
205 
206 // generate code: integer
207 void EmbeddedcCodeGenerator::IntegerIncrement(const AA& address, int val) {
208  if(val==1)
209  Output() << TargetAddress(address) << "++;";
210  else if(val==-1)
211  Output() << TargetAddress(address) << "--;";
212  else if(val!=0)
213  Output() << TargetAddress(address) << " += " << IntegerConstant(val) << ";";
214  if(val!=0)
215  LineFeed();
216 }
217 
218 // integer maths
219 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::IntegerQuotient(const AX& expression, int val) {
220  return AX(expression + " / " + IntegerConstant(val));
221 }
222 
223 // integer maths
224 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::IntegerRemainder(const AX& expression, int val) {
225  return AX(expression + " % " + IntegerConstant(val));
226 }
227 
228 // integer maths
229 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerBitmask(const AX& expression) {
230  return AX("(" + WordConstant(1) + " << " + expression + ")" );
231 }
232 
233 // integer compare
234 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsEq(const AA& address, int val) {
235  return AX(TargetAddress(address) + " == " + IntegerConstant(val));
236 }
237 
238 // integer compare
239 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsEq(const AA& address, const AX& expression) {
240  return AX(TargetAddress(address) + " == " + expression);
241 }
242 
243 // integer compare
244 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsNotEq(const AA& address, const AX& expression) {
245  return AX(TargetAddress(address) + " != " + expression);
246 }
247 
248 // integer compare
249 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsNotEq(const AA& address, int val) {
250  return AX(TargetAddress(address) + " != " + IntegerConstant(val));
251 }
252 
253 // integer compare
254 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsGreater(const AA& address, int val) {
255  return AX(TargetAddress(address) + " > " + IntegerConstant(val));
256 }
257 
258 // integer compare
259 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsLess(const AA& address, int val) {
260  return AX(TargetAddress(address) + " < " + IntegerConstant(val));
261 }
262 
263 // integer maths
264 bool EmbeddedcCodeGenerator::HasIntmaths(void) {
265  return true;
266 }
267 
268 // generate code: integer
269 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerConstant(int val) {
270  AX res(ToStringInteger(val));
271  if(mIntegerType == "char") return res;
272  if(mIntegerType == "int8_t") return res;
273  if(mIntegerType == "int") return res;
274  if(mIntegerType == "int16_t") return res;
275  if(mIntegerType == "long") return AX(res + "L");
276  if(mIntegerType == "int32_t") return AX(res + "L");
277  if(mIntegerType == "long long") return AX(res + "LL");
278  FCG_ERR("EmbeddedcCodeGenerator: unsupported integer data type [" << mIntegerType << "]");
279  return res;
280 }
281 
282 // generate code: word
283 void EmbeddedcCodeGenerator::WordDeclare(const AA& address){
284  Output() << "static " << mWordType << " " << TargetAddress(address) << ";";
285  LineFeed();
286 }
287 
288 // generate code: word
289 void EmbeddedcCodeGenerator::WordDeclare(const AA& address, word_t val){
290  Output() << "static " << mWordType << " " << TargetAddress(address) << "=" << val << ";";
291  LineFeed();
292 }
293 
294 // generate code: word
295 void EmbeddedcCodeGenerator::WordAssign(const AA& address, word_t val){
296  Output() << TargetAddress(address) << " = " << WordConstant(val) << ";";
297  LineFeed();
298 }
299 
300 // generate code: word
301 void EmbeddedcCodeGenerator::WordAssign(const AA& address, const AX& expression){
302  Output() << TargetAddress(address) << " = " << expression << ";";
303  LineFeed();
304 }
305 
306 // generate code: word
307 void EmbeddedcCodeGenerator::WordOr(const AA& address, word_t val) {
308  Output() << TargetAddress(address) << " |= " << WordConstant(val) << ";";
309  LineFeed();
310 }
311 
312 // generate code: word
313 void EmbeddedcCodeGenerator::WordOr(const AA& address, const AX& expression) {
314  Output() << TargetAddress(address) << " |= " << expression << ";";
315  LineFeed();
316 }
317 
318 // generate code: word
319 void EmbeddedcCodeGenerator::WordOr(const AA& address, const AA& op1, const AA& op2) {
320  Output() << TargetAddress(address) << " = " << TargetExpression(op1) << " | " << TargetExpression(op2) << ";";
321  LineFeed();
322 }
323 
324 // generate code: word
325 void EmbeddedcCodeGenerator::WordOr(const AA& address, const AA& op1, word_t op2) {
326  Output() << TargetAddress(address) << " = " << TargetExpression(op1) << " | " << WordConstant(op2) << ";";
327  LineFeed();
328 }
329 
330 // generate code: word
331 void EmbeddedcCodeGenerator::WordAnd(const AA& address, word_t val) {
332  Output() << TargetAddress(address) << " &= " << WordConstant(val) << ";";
333  LineFeed();
334 }
335 
336 // generate code: word
337 void EmbeddedcCodeGenerator::WordAnd(const AA& address, const AX& expression) {
338  Output() << TargetAddress(address) << " &= " << expression << ";";
339  LineFeed();
340 }
341 
342 // generate code: word
343 void EmbeddedcCodeGenerator::WordAnd(const AA& address, const AA& op1, const AA& op2) {
344  Output() << TargetAddress(address) << " = " << TargetExpression(op1) << " & " << TargetExpression(op2) << ";";
345  LineFeed();
346 }
347 
348 // generate code: word
349 void EmbeddedcCodeGenerator::WordAnd(const AA& address, const AA& op1, word_t op2) {
350  Output() << TargetAddress(address) << " = " << TargetExpression(op1) << " & " << WordConstant(op2) << ";";
351  LineFeed();
352 }
353 
354 // generate code: word
355 void EmbeddedcCodeGenerator::WordNand(const AA& address, const AX& expression) {
356  Output() << TargetAddress(address) << " &= ~(" << expression << ");";
357  LineFeed();
358 }
359 
360 // generate code: word
361 CodePrimitives::AX EmbeddedcCodeGenerator::WordIsBitSet(const AA& address, int idx) {
362  return AX("( " + TargetAddress(address) + " & " + WordConstant(0x01<<idx) + " ) != 0");
363 }
364 
365 // generate code: word
366 CodePrimitives::AX EmbeddedcCodeGenerator::WordIsBitClr(const AA& address, int idx) {
367  return AX("( " + TargetAddress(address) + " & " + WordConstant(0x01<<idx) + " ) == 0");
368 }
369 
370 // generate code: word
371 CodePrimitives::AX EmbeddedcCodeGenerator::WordIsMaskSet(const AA& address, word_t mask) {
372  return AX("( " + TargetAddress(address) + " & " + WordConstant(mask) + " ) != 0");
373 }
374 
375 // generate code: conditionals
376 CodePrimitives::AX EmbeddedcCodeGenerator::WordIsEq(const AA& address, word_t val) {
377  return AX(TargetAddress(address) + " == " + WordConstant(val));
378 }
379 
380 // generate code: conditionals
381 CodePrimitives::AX EmbeddedcCodeGenerator::WordIsNotEq(const AA& address, word_t val) {
382  return AX(TargetAddress(address) + " != " + WordConstant(val));
383 }
384 
385 // generate code: word
386 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::WordConstant(word_t val) {
387  AX res;
388  std::stringstream sstr;
389  sstr << "0x" << std::setbase(16) << std::setfill('0');
390  // special case: zero
391  if(val==0) sstr << std::setw(2);
392  // special case: char
393  if(mWordType == "unsigned char") { sstr << std::setw(2); val &=0xff; }
394  // do stream
395  if(mWordType == "unsigned char") sstr << val;
396  else if(mWordType == "uint8_t") sstr << ((uint8_t) val) << "U";
397  else if(mWordType == "unsigned short") sstr << ((unsigned short) val) << "U";
398  else if(mWordType == "unsigned int") sstr << ((unsigned int) val) << "U";
399  else if(mWordType == "uint16_t") sstr << ((uint16_t) val) << "U";
400  else if(mWordType == "unsigned long") sstr << ((unsigned long) val) << "UL";
401  else if(mWordType == "uint32_t") sstr << ((uint32_t) val) << "UL";
402  else if(mWordType == "unsigned long long") sstr << ((unsigned long long) val) << "ULL";
403  else FCG_ERR("EmbeddedcCodeGenerator: unsupported word data type [" << mWordType <<"]");
404  sstr >> res;
405  return res;
406 }
407 
408 // generate code: string constant
409 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::StringConstant(const std::string& val) {
410  AX res;
411  res.append(1,'\"');
412  for(std::size_t i=0; i<val.length(); ++i) {
413  char c=val.at(i);
414  // terminate
415  if(c==0) break;
416  // quote double quote
417  if(c=='"') { res.append("\\\""); continue; }
418  // quote back slash
419  if(c=='\\') { res.append("\\\\"); continue; }
420  // printable ascii
421  if((c>=0x20) && (c<0x7f)) { res.append(1,c); continue; };
422  // error on other (alternative: use octal encoding to support utf8)
423  FCG_ERR("EmbeddedcCodeGenerator: non-printable ascii or other encoding unsupported [" << val <<"]");
424  }
425  res.append(1,'\"');
426  return res;
427 }
428 
429 // const-int array (Embedded C only helper)
430 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::IntarrayConstant(const std::vector<int>& val) {
431  std::stringstream strstr;
432  int newline=20;
433  if(val.size()<25) newline=25;
434  strstr << "{ " ;
435  size_t vit=0;
436  while(true) {
437  if(vit==val.size()) break;
438  strstr << IntegerConstant(val[vit]);
439  ++vit;
440  if(vit==val.size()) break;
441  strstr << ", ";
442  newline--;
443  if(newline==0) {
444  strstr << std::endl << " ";
445  newline=20;
446  }
447  }
448  strstr << " }";
449  return AX(strstr.str());
450 }
451 
452 // const-int-array
453 void EmbeddedcCodeGenerator::CintarrayDeclare(const AA& address, const std::vector<int>& val) {
454  if(val.size()==0) {
455  FCG_ERR("EmbeddedcCodeGenerator::Cintarray(): ignoring empty const vector");
456  return;
457  }
458  if(val.size()>= (1ULL << (mIntegerSize-1))) {
459  FCG_ERR("EmbeddedcCodeGenerator::Cintarray(): const vector exceeds addres range");
460  return;
461  }
462  Output() << "const " << mIntegerType << " " << TargetAddress(address) << "[] = ";
463  LineFeed();
464  IndentInc();
465  Output() << IntarrayConstant(val) << ";";
466  LineFeed();
467  IndentDec();
468 }
469 
470 // int array access by const
471 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CintarrayAccess(const AA& address, int index) {
472  return AA(address + "[" + ToStringInteger(index) + "]");
473 };
474 
475 // int array access by expression
476 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CintarrayAccess(const AA& address, const AA& indexaddr){
477  return AA(address + "[" + TargetAddress(indexaddr) + "]");
478 };
479 
480 // tell parent class about this feature
481 bool EmbeddedcCodeGenerator::HasCintarray(void) {
482  return true;
483 };
484 
485 
486 // const-word array (Embedded C only helper)
487 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::WordarrayConstant(const std::vector<word_t>& val) {
488  std::stringstream strstr;
489  int newline=20;
490  if(val.size()<25) newline=25;
491  strstr << "{ " ;
492  size_t vit=0;
493  while(true) {
494  if(vit==val.size()) break;
495  strstr << WordConstant(val[vit]);
496  ++vit;
497  if(vit==val.size()) break;
498  strstr << ", ";
499  newline--;
500  if(newline==0) {
501  strstr << std::endl << " ";
502  newline=20;
503  }
504  }
505  strstr << " }";
506  return AX(strstr.str());
507 }
508 
509 // const-word-array
510 void EmbeddedcCodeGenerator::CwordarrayDeclare(const AA& address, const std::vector<word_t>& val) {
511  if(val.size()==0) {
512  FCG_ERR("EmbeddedcCodeGenerator::Cwordarray(): ignoring empty const vector");
513  return;
514  }
515  if(val.size()>= (1ULL << (mIntegerSize-1))) {
516  FCG_ERR("EmbeddedcCodeGenerator::Cwordarray(): const vector exceeds addres range");
517  return;
518  }
519  Output() << "const " << mWordType << " " << TargetAddress(address) << "[] = ";
520  IndentInc();
521  Output() << WordarrayConstant(val) << ";";
522  LineFeed();
523  IndentDec();
524 }
525 
526 // word-array access by const
527 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CwordarrayAccess(const AA& address, int index) {
528  return AA(address + "[" + ToStringInteger(index) + "]");
529 };
530 
531 // word array access by expression
532 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CwordarrayAccess(const AA& address, const AA& indexaddr){
533  return AA(address + "[" + TargetAddress(indexaddr) + "]");
534 };
535 
536 // tell parent class about this feature
537 bool EmbeddedcCodeGenerator::HasCwordarray(void) {
538  return true;
539 };
540 
541 // int-array
542 void EmbeddedcCodeGenerator::IntarrayDeclare(const AA& address, const std::vector<int>& val) {
543  if(val.size()==0) {
544  FCG_ERR("EmbeddedcCodeGenerator::Intarray(): ignoring empty const vector");
545  return;
546  }
547  if(val.size()>= (1ULL << (mIntegerSize-1))) {
548  FCG_ERR("EmbeddedcCodeGenerator::Intarray(): vector exceeds address range");
549  return;
550  }
551  Output() << mIntegerType << " " << TargetAddress(address) << "[] = ";
552  IndentInc();
553  Output() << IntarrayConstant(val) << ";";
554  LineFeed();
555  IndentDec();
556 }
557 
558 // int-array
559 void EmbeddedcCodeGenerator::IntarrayDeclare(const AA& address, int len) {
560  if(len==0) {
561  FCG_ERR("EmbeddedcCodeGenerator::Intarray(): ignoring empty const vector");
562  return;
563  }
564  if(len>= (1LL << (mIntegerSize-1))) {
565  FCG_ERR("EmbeddedcCodeGenerator::Intarray(): const vector exceeds address range");
566  return;
567  }
568  Output() << mIntegerType << " " << TargetAddress(address) << "[" << IntegerConstant(len) << "];";
569  LineFeed();
570 }
571 
572 // int-array access by const
574  return AA(address + "[" + ToStringInteger(index) + "]");
575 };
576 
577 // int array access by expression
579  return AA(address + "[" + TargetAddress(indexaddr) + "]");
580 };
581 
582 // tell parent class about this feature
584  return true;
585 };
586 
587 // word-array
588 void EmbeddedcCodeGenerator::WordarrayDeclare(const AA& address, const std::vector<word_t>& val) {
589  if(val.size()==0) {
590  FCG_ERR("EmbeddedcCodeGenerator::Wordarray(): ignoring empty const vector");
591  return;
592  }
593  if(val.size()>= (1ULL << (mIntegerSize-1))) {
594  FCG_ERR("EmbeddedcCodeGenerator::Wordarray(): const vector exceeds addres range");
595  return;
596  }
597  Output() << mWordType << " " << TargetAddress(address) << "[] = ";
598  IndentInc();
599  Output() << WordarrayConstant(val) << ";";
600  LineFeed();
601  IndentDec();
602 }
603 
604 // word-array
605 void EmbeddedcCodeGenerator::WordarrayDeclare(const AA& address, int len) {
606  if(len==0) {
607  FCG_ERR("EmbeddedcCodeGenerator::Wordarray(): ignoring empty const vector");
608  return;
609  }
610  if(len>= (1LL << (mIntegerSize-1))) {
611  FCG_ERR("EmbeddedcCodeGenerator::Wordarray(): const vector exceeds addres range");
612  return;
613  }
614  Output() << mWordType << " " << TargetAddress(address) << "[" << IntegerConstant(len) << "];";
615  LineFeed();
616 }
617 
618 // word-array access by const
619 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::WordarrayAccess(const AA& address, int index) {
620  return AA(address + "[" + ToStringInteger(index) + "]");
621 };
622 
623 // word array access by expression
624 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::WordarrayAccess(const AA& address, const AA& indexaddr){
625  return AA(address + "[" + TargetAddress(indexaddr) + "]");
626 };
627 
628 // tell parent class about this feature
629 bool EmbeddedcCodeGenerator::HasWordarray(void) {
630  return true;
631 };
632 
633 // literal const-string array (Embedded C only helper)
634 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::StrarrayConstant(const std::vector<std::string>& val) {
635  std::stringstream strstr;
636  int newline;
637  if(val.size()<4) {
638  newline=4;
639  strstr << "{ ";
640  } else {
641  newline=1;
642  strstr << "{" << std::endl;
643  }
644  size_t vit=0;
645  while(true) {
646  if(vit==val.size()) break;
647  strstr << StringConstant(val[vit]);
648  ++vit;
649  if(vit==val.size()) break;
650  strstr << ", ";
651  newline--;
652  if(newline==0) {
653  strstr << std::endl;
654  newline=1;
655  }
656  }
657  strstr << " }";
658  return AX(strstr.str());
659 }
660 
661 // const string array
662 void EmbeddedcCodeGenerator::CstrarrayDeclare(const AA& address, const std::vector<std::string>& val) {
663  if(val.size()==0) {
664  FCG_ERR("EmbeddedcCodeGenerator::Cstrarrayy(): ignoring empty string array");
665  return;
666  }
667  if(val.size()>= (1ULL << (mIntegerSize-1))) {
668  FCG_ERR("EmbeddedcCodeGenerator::Cstrarray(): string array exceeds address range");
669  return;
670  }
671  Output() << "const char*" << " " << TargetAddress(address) << "[] = ";
672  IndentInc();
673  Output() << StrarrayConstant(val) << ";";
674  LineFeed();
675  IndentDec();
676 };
677 
678 // const string array
679 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CstrarrayAccess(const AA& address, int index) {
680  return AA(address + "[" + ToStringInteger(index) + "]");
681 };
682 
683 // const string array
684 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CstrarrayAccess(const AA& address, const AA& indexaddr){
685  return AA(address + "[" + TargetAddress(indexaddr) + "]");
686 };
687 
688 // tell parent about this feature
689 bool EmbeddedcCodeGenerator::HasCstrarray(void) {
690  return true;
691 };
692 
693 
694 // generate code: conditionals
695 void EmbeddedcCodeGenerator::IfTrue(const AX& expression) {
696  Output() << "if( " << expression << " ) {";
697  LineFeed();
698  IndentInc();
699 }
700 
701 // generate code: conditionals
702 void EmbeddedcCodeGenerator::IfFalse(const AX& expression) {
703  Output() << "if( ! ( " << expression << " ) ) {";
704  LineFeed();
705  IndentInc();
706 }
707 
708 // generate code: conditionals
709 void EmbeddedcCodeGenerator::IfWord(const AX& expression) {
710  Output() << "if( " << expression << " ) {";
711  LineFeed();
712  IndentInc();
713 }
714 
715 // generate code: conditionals
716 void EmbeddedcCodeGenerator::IfElse(void) {
717  IndentDec();
718  Output() << "} else {";
719  LineFeed();
720  IndentInc();
721 }
722 
723 // generate code: conditionals
724 void EmbeddedcCodeGenerator::IfElseIfTrue(const AX& expression) {
725  IndentDec();
726  Output() << "} else if( " << expression << " ) {";
727  LineFeed();
728  IndentInc();
729 }
730 
731 // generate code: conditionals
732 void EmbeddedcCodeGenerator::IfEnd(void) {
733  IndentDec();
734  Output() << "};";
735  LineFeed();
736 }
737 
738 // switch control
739 void EmbeddedcCodeGenerator::SwitchBegin(const AA& address){
740  Output() << "switch(" << TargetAddress(address) << ") {";
741  LineFeed();
742 }
743 
744 // switch control
745 void EmbeddedcCodeGenerator::SwitchCase(const AA& address, int val){
746  (void) address;
747  Output() << "case " << IntegerConstant(val) << ":";
748  LineFeed();
749  IndentInc();
750 }
751 
752 // switch control
753 void EmbeddedcCodeGenerator::SwitchCases(const AA& address, int from, int to){
754  // simplify to singleton
755  if(from==to) {
756  SwitchCase(address, from);
757  return;
758  }
759  // do range (quiet for empty)
760  for(int val=from; val<=to; ++val) {
761  Output() << "case " << IntegerConstant(val) << ":";
762  LineFeed();
763  }
764  IndentInc();
765 }
766 
767 // switch control
768 void EmbeddedcCodeGenerator::SwitchCases(const AA& address, const std::set< int >& vals){
769  (void) address;
770  // do set (quiet for empty)
771  std::set< int >::const_iterator vit=vals.begin();
772  for(; vit!=vals.end(); ++ vit) {
773  Output() << "case " << IntegerConstant(*vit) << ":";
774  LineFeed();
775  }
776  IndentInc();
777 }
778 
779 // switch control
780 void EmbeddedcCodeGenerator::SwitchBreak(void){
781  Output() << "break;";
782  LineFeed();
783  IndentDec();
784 }
785 
786 // switch control
787 void EmbeddedcCodeGenerator::SwitchEnd(void){
788  Output() << "default:";
789  LineFeed();
790  IndentInc();
791  Output() << "break;";
792  LineFeed();
793  IndentDec();
794  Output() << "};";
795  LineFeed();
796 }
797 
798 // switch control
799 bool EmbeddedcCodeGenerator::HasMultiCase(void) {
800  return true;
801 }
802 
803 // loops
804 void EmbeddedcCodeGenerator::LoopBegin(void) {
805  Output() << "while(1) {";
806  LineFeed();
807  IndentInc();
808 }
809 
810 // loops
811 void EmbeddedcCodeGenerator::LoopBreak(const AX& expression) {
812  Output() << "if( " << expression << " ) break;";
813  LineFeed();
814 }
815 
816 
817 // loops
818 void EmbeddedcCodeGenerator::LoopEnd(void) {
819  IndentDec();
820  Output() << "};";
821  LineFeed();
822 }
823 
824 void EmbeddedcCodeGenerator::FunctionReturn(void) {
825  Output() << "return;";
826  LineFeed();
827 }
828 
829 
830 // timer
831 void EmbeddedcCodeGenerator::TimerDeclare(const AA& address, const std::string& litval) {
832  // read/check ftu time format
833  char* next;
834  const char* first = litval.c_str();
835  strtol(first,&next,10);
836  bool err=false;
837  if(*next!='f') err=true;
838  if(!err) if(*(++next)!='t') err=true;
839  if(!err) if(*(++next)!='u') err=true;
840  if(!err) if(*(++next)!=0) err=true;
841  if(err) {
842  FCG_ERR("EmbeddedcCodeGenerator: missmatched time literal "+ litval);
843  }
844  Output() << "static int " << TargetAddress(AA("timer_"+address+"_cnt")) << ";";
845  LineFeed();
846  Output() << "static char " << TargetAddress(AA("timer_"+address+"_run")) << ";";
847  LineFeed();
848 }
849 void EmbeddedcCodeGenerator::TimerStart(const AA& address) {
850  Output() << TargetAddress(AA("timer_"+address+"_run")) << " = 1;";
851  LineFeed();
852 }
853 void EmbeddedcCodeGenerator::TimerStop(const AA& address) {
854  Output() << TargetAddress(AA("timer_"+address+"_run")) << " = 0;";
855  LineFeed();
856 }
857 void EmbeddedcCodeGenerator::TimerReset(const AA& address, const std::string& litval) {
858  int val=(int) strtol(litval.c_str(),NULL,10);
859  Output() << TargetAddress(AA("timer_"+address+"_cnt")) << " = " << IntegerConstant(val) << ";";
860  LineFeed();
861 }
862 CodePrimitives::AX EmbeddedcCodeGenerator::TimerIsElapsed(const AA& address) {
863  return AX(TargetAddress(AA("timer_"+address+"_run")) + " && (" + TargetAddress(AA("timer_"+address+"_cnt")) + " <= 0)");
864 }
865 
866 
867 // output actions
868 void EmbeddedcCodeGenerator::RunActionSet(const std::string& address) {
869  Output() << address << " = 1;" ;
870  LineFeed();
871 }
872 void EmbeddedcCodeGenerator::RunActionClr(const std::string& address) {
873  Output() << address << " = 0;" ;
874  LineFeed();
875 }
876 void EmbeddedcCodeGenerator::RunActionExe(const AX& expression) {
877  Output() << expression << ";";
878  LineFeed();
879 }
880 
881 
882