30 FD_DCG(
"CodeGenerator()::CodeGenerator()");
40 FD_DCG(
"CodeGenerator()::~CodeGenerator()");
41 if(pOutBuffer)
delete pOutBuffer;
45std::map< std::string,
CodeGenerator* (*)(
void) >* CodeGenerator::mpsRegistry=0;
49 if(!mpsRegistry) mpsRegistry =
new std::map< std::string,
CodeGenerator* (*)(
void) >;
50 (*mpsRegistry)[type]=newcg;
55 std::vector< std::string > res;
56 std::map< std::string,
CodeGenerator* (*)(
void) >::iterator rit;
57 for(rit=mpsRegistry->begin(); rit != mpsRegistry->end(); ++rit)
58 res.push_back(rit->first);
64 if(mpsRegistry->find(type)==mpsRegistry->end())
return 0;
65 return (*mpsRegistry)[type]();
70 FD_DCG(
"CodeGenerator()::Clear()");
80 FCG_VERB2(
"CodeGenerator::Generator(): from file " << rFileName);
81 TokenReader tr(rFileName);
88 FCG_VERB2(
"CodeGenerator::Generator(): found [" <<
mGenerators.back().Name() <<
"] " <<
89 "with #" <<
mGenerators.back().TransRelSize() <<
" transitions");
94 FCG_VERB2(
"CodeGenerator::Generator(): generator by reference");
98 FCG_VERB2(
"CodeGenerator::Generator(): found [" <<
mGenerators.back().Name() <<
"] " <<
99 "with #" <<
mGenerators.back().TransRelSize() <<
" transitions");
115void CodeGenerator::DoReadGenerators(TokenReader& rTr) {
117 std::string dirname=
"";
118 if(rTr.SourceMode()==TokenReader::File)
119 dirname=ExtractDirectory(rTr.FileName());
121 FD_DCG(
"CodeGenerator()::DoReadGenerators(tr): dirname " << dirname);
123 rTr.ReadBegin(
"Generators");
125 while(!rTr.Eos(
"Generators")) {
128 if(token.Type()==Token::String) {
129 Insert(PrependPath(dirname,token.StringValue()));
134 if(token.Type()==Token::Begin)
135 if(token.StringValue()==
"Generator") {
142 std::stringstream errstr;
143 errstr <<
"Invalid token" << rTr.FileLine();
144 throw Exception(
"CodeGenerator::DoReadGenerators", errstr.str(), 502);
146 rTr.ReadEnd(
"Generators");
153 FD_DCG(
"CodeGenerator::DoRead()");
154 std::string label=rLabel;
155 if(label==
"") label=
"CodeGenerator";
158 rTr.ReadBegin(label,token);
159 if(token.ExistsAttributeString(
"name"))
160 Name(token.AttributeStringValue(
"name"));
162 while(!rTr.Eos(label)) {
165 if(token.Type()==Token::Begin)
166 if(token.StringValue()==
"TargetConfiguration") {
167 rTr.ReadBegin(
"TargetConfiguration");
169 rTr.ReadEnd(
"TargetConfiguration");
173 if(token.Type()==Token::Begin)
174 if(token.StringValue()==
"Generators") {
175 DoReadGenerators(rTr);
176 FCG_VERB1(
"CodeGenerator::Generator(): found #" <<
Size() <<
" generators");
180 if(token.Type()==Token::Begin)
181 if(token.StringValue()==
"EventConfiguration") {
182 mAlphabet.Read(rTr,
"EventConfiguration");
183 FCG_VERB1(
"CodeGenerator::Events(): found event configuration for #" <<
mAlphabet.Size() <<
" events");
187 std::stringstream errstr;
188 errstr <<
"Invalid token" << rTr.FileLine();
189 throw Exception(
"CodeGenerator::DoRead", errstr.str(), 502);
201void CodeGenerator::DoWriteGenerators(TokenWriter& rTw)
const {
202 rTw.WriteBegin(
"Generators");
203 for(Idx i=0; i<
Size(); i++) {
213 rTw.WriteEnd(
"Generators");
221 std::string label=rLabel;
222 if(label==
"") label=
"CodeGenerator";
223 rTw.WriteBegin(label);
225 rTw.WriteBegin(
"TargetConfiguration");
227 rTw.WriteEnd(
"TargetConfiguration");
229 mAlphabet.Write(rTw,
"EventConfiguration");
231 DoWriteGenerators(rTw);
239 std::stringstream res;
240 res << COMPILEDES_VERSION <<
" (using " << faudes::VersionString() <<
")";
260 FCG_VERB0(
"CodeGenerator::Compile(): compile to internal representation");
265 FCG_VERB0(
"CodeGenerator::Compile(): done");
271 FD_DCG(
"CodeGenerator::DoCompile()");
274 for(
size_t git=0; git<
Size(); ++git) {
275 EventSet::Iterator eit=
At(git).AlphabetBegin();
276 for(; eit!=
At(git).AlphabetEnd(); ++eit) {
278 FCG_ERR(
"CodeGenerator::Compile(): event [" <<
EventName(*eit) <<
"] has unspecified execution semantics")
284 FCG_VERB0(
"CodeGenerator::Compile(): event configuration mismatch: #" << (
mAlphabet-
mUsedEvents).
Size() <<
" unused events");
287 EventSet::Iterator eit;
297 if(
mAlphabet.Attribute(*eit).Input())
continue;
298 if(
mAlphabet.Attribute(*eit).Timer())
continue;
299 if(
mAlphabet.Attribute(*eit).Output())
continue;
302 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: overall used events: #" <<
mUsedEvents.Size());
303 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: input events incl timer: #" <<
mInputEvents.Size());
304 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: output events: #" <<
mOutputEvents.Size());
305 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: internal events excl timer: #" <<
mInternalEvents.Size());
307 FD_DCG(
"CodeGenerator::DoCompile(): sorting events");
308 std::multimap<int, Idx> sortev;
312 if((prio<0) || (prio > 10000)) {
313 FCG_ERR(
"CodeGenerator::Compile(): priority out of range [0, 10000] for event [" <<
EventName(*eit) <<
"]");
319 sortev.insert(std::pair<int,Idx>(-prio,*eit));
322 FD_DCG(
"CodeGenerator::DoCompile(): set up bitaddress");
327 std::multimap<int, Idx>::iterator sit;
329 for(sit=sortev.begin(); sit!=sortev.end(); sit++) {
342 FCG_VERB1(
"CodeGenerator::Compile(): bitmask size #" <<
EventBitMaskSize() <<
" bits");
344 FD_DCG(
"CodeGenerator::DoCompie(): set up transition vector");
349 for(Idx gid=0; gid<
Size(); gid++) {
350 FD_DCG(
"CodeGenerator::DoCompile(): set up transition vector " << gid);
358 const Generator gen =
At(gid);
360 FCG_ERR(
"CodeGenerator::Complie(): generator must not be empty [" << gen.Name() <<
"]");
364 IndexSet::Iterator sit= gen.StatesBegin();
365 for(;sit!=gen.StatesEnd();++sit) {
366 vectoraddr[*sit]= (int) transvect.size();
367 faudesindex[(int) transvect.size()]= *sit;
368 TransSet::Iterator tit = gen.TransRelBegin(*sit);
369 TransSet::Iterator tit_end = gen.TransRelEnd(*sit);
370 for(;tit!=tit_end;++tit) {
371 transvect.push_back((
int) tit->Ev);
372 transvect.push_back((
int) tit->X2);
374 transvect.push_back(0);
377 for(
size_t vit=0; vit< transvect.size(); ++vit) {
378 int ev = transvect[vit];
381 int x2 = transvect[++vit];
383 transvect[vit]=vectoraddr[x2];
385 FCG_VERB0(
"CodeGenerator::Compile(): [" << gen.Name() <<
"] raw data for transition array #"
387 if(!usingvectoraddr) {
388 FCG_VERB0(
"CodeGenerator::Compile(): [" << gen.Name() <<
"] raw data for state-address array #"
391 FCG_VERB0(
"CodeGenerator::Compile(): [" << gen.Name() <<
"] using vector addresses as state indices");
400 if(!
mAlphabet.Attribute(*eit).Input())
continue;
401 const std::vector<AttributeCodeGeneratorEvent::InputTrigger>& triggers =
mAlphabet.Attribute(*eit).mTriggers;
402 for(
size_t i=0; i<triggers.size(); i++) {
403 if(triggers[i].mExe) {
404 std::string flagaddr=triggers[i].mAddress;
405 mFlags[flagaddr].mEvents.Insert(*eit);
406 mFlags[flagaddr].mAddress=flagaddr;
408 if((triggers[i].mNeg) || (triggers[i].mPos)) {
409 std::string lineaddr=triggers[i].mAddress;
411 if(
mLines[lineaddr].mStatic != triggers[i].mStatic)
412 FCG_ERR(
"CodeGenerator::Compile(): inconsistent static option on input line [" << lineaddr <<
"]");
414 mLines[lineaddr].mAddress=lineaddr;
415 if(triggers[i].mNeg)
mLines[lineaddr].mNegEvents.Insert(*eit);
416 if(triggers[i].mPos)
mLines[lineaddr].mPosEvents.Insert(*eit);
417 if(triggers[i].mNeg && triggers[i].mStatic)
mLines[lineaddr].mNegStatics.Insert(*eit);
418 if(triggers[i].mPos && triggers[i].mStatic)
mLines[lineaddr].mPosStatics.Insert(*eit);
419 mLines[lineaddr].mStatic=triggers[i].mStatic;
423 std::map<std::string, LineAddress>::iterator lit=
mLines.begin();
425 for(;lit!=
mLines.end();++lit) lit->second.mBitAddress=linecnt++;
426 FCG_VERB1(
"CodeGenerator::Compile(): monitoring #" <<
mLines.size() <<
" lines for edge detection");
434 if(!attr.
Timer())
continue;
439 mTimers[timerev].mAddress= timerev;
440 mTimers[timerev].mElapseEvent= timerev;
442 mTimers[timerev].mStartEvents= starts;
443 mTimers[timerev].mStopEvents= stops;
444 mTimers[timerev].mResetEvents= resets;
445 EventSet::Iterator ait;
446 ait = starts.Begin();
447 for(;ait!=starts.End();++ait)
450 for(;ait!=stops.End();++ait)
452 ait = resets.Begin();
453 for(;ait!=resets.End();++ait)
456 FCG_VERB1(
"CodeGenerator::Compile(): operating #" <<
mTimers.size() <<
" timers controlled by #" <<
mTimerActions.size() <<
" events");
463 if(!attr.
Output())
continue;
465 const std::vector<AttributeCodeGeneratorEvent::OutputAction>& actions =
mAlphabet.Attribute(*eit).
mActions;
466 for(
size_t i=0; i<actions.size(); i++) {
467 std::string actaddr=actions[i].mAddress;
473 FCG_VERB1(
"CodeGenerator::Compile(): operating #" <<
mActionAddresses.size() <<
" action primitives controlled by #" << evcn <<
" events");
483 FD_DCG(
"CodeGenerator::DoCompile(): ok");
489 std::map<Idx,int>::const_iterator sit;
507 std::map<int,Idx>::const_iterator sit;
516 std::vector<bool> res;
518 while(res.size()< vsize) res.push_back(
false);
521 if(baddr<0)
return res;
530 std::vector<bool> res;
532 while(res.size()< vsize) res.push_back(
false);
534 EventSet::Iterator eit;
535 for(eit=eset.Begin(); eit!=eset.End(); eit++) {
537 if(baddr<0)
continue;
553 for(;(shift<
mWordSize) && (bidx<vect.size()); shift++,bidx++)
554 if(vect[bidx]) res |= (1UL<<shift);
560 std::vector< word_t > res;
562 for(
size_t vidx=0; vidx < vect.size(); ++vidx) {
563 if(!vect[vidx])
continue;
578 std::map<Idx,int>::const_iterator sit;
587 std::map<int,Idx>::const_iterator sit;
667 FCG_VERB0(
"CodeGenerator::Generate(): generating code to \"[" <<
mOutMode <<
"]\"");
669 bool tmpstream=
false;
672 if(pOutBuffer!=0)
delete pOutBuffer;
673 pOutBuffer =
new cgp_streambuf(
mOutMode);
681 FCG_VERB0(
"CodeGenerator::Generate(): generated " <<
LineCount() <<
" lines of code.");
696 static std::string ems(
"");
697 if(!pOutBuffer)
return ems;
698 return pOutBuffer->Buffer();
702 if(!pOutBuffer)
return;
704 if(!strbuf.empty()) FCG_VERB1(
"CodeGenerator::OutputString(): setting non-trivial not implemented")
710 if(!pOutBuffer)
return;
711 pOutBuffer->Mute(mode!=
'*');
717 if(!pOutBuffer)
return;
719 pOutBuffer->Mute(mute);
737 if(!pOutBuffer)
return;
738 pOutBuffer->IndentInc();
743 if(!pOutBuffer)
return;
744 pOutBuffer->IndentDec();
749 if(!pOutBuffer)
return;
750 pOutBuffer->XmlTextEscape(on);
755 if(!pOutBuffer)
return;
756 pOutBuffer->XmlCdataEscape(on);
764 if(pOutBuffer->Mute())
775 if(!pOutBuffer)
return;
776 pOutBuffer->MuteVspace(on);
782 if(!pOutBuffer)
return std::string();
783 std::stringstream res;
784 res <<
"#" << pOutBuffer->LineCount();
785 return std::string(res.str());
790CodeGenerator::cgp_streambuf::cgp_streambuf(std::string mode) :
802 if(mode ==
"std::string") {
803 mMode =
"std::string";
807 else if(mode==
"std::cout") {
814 mpFOutStream =
new std::ofstream();
815 mpFOutStream->exceptions(std::ios::badbit|std::ios::failbit);
817 mpFOutStream->open(mode.c_str(), std::ios::out|std::ios::trunc);
819 catch (std::ios::failure&) {
820 std::stringstream errstr;
821 errstr <<
"Exception opening/writing file \""<< mode <<
"\"";
822 throw Exception(
"CodeGenerator::Generate()", errstr.str(), 1);
829CodeGenerator::cgp_streambuf::~cgp_streambuf() {
832 mpFOutStream->close();
838std::streambuf::int_type CodeGenerator::cgp_streambuf::overflow (int_type c) {
841 if(c == EOF)
return EOF;
845 if(mMuteVspace && (c==
'\n') && (mBuffer.size()==0))
return c;
848 mBuffer.push_back(c);
857 for(;scnt>0;--scnt) mBuffer.push_back(
' ');
863 { mBuffer +=
"<";
return c;}
865 { mBuffer +=
">";
return c;}
867 { mBuffer +=
"&";
return c;}
869 { mBuffer +=
"'";
return c;}
871 { mBuffer +=
""";
return c;}
875 if((c==
'>') && (mBuffer.size()>=2))
876 if(mBuffer.at(mBuffer.size()-1) ==
']')
877 if(mBuffer.at(mBuffer.size()-2) ==
']')
878 mBuffer +=
"]]><![CDATA[";
881 mBuffer.push_back(c);
887void CodeGenerator::cgp_streambuf::Flush() {
889 if(!pOutStream)
return;
892 (*pOutStream) << mBuffer;
893 (*pOutStream) << std::flush;
894 }
catch(std::ios::failure&) {
895 std::stringstream errstr;
896 errstr <<
"Exception writing to file \""<< mMode <<
"\"";
897 throw Exception(
"CodeGenerator::Generate()", errstr.str(), 1);
904const std::string& CodeGenerator::cgp_streambuf::Buffer(){
909void CodeGenerator::cgp_streambuf::Clear(
void){
917int CodeGenerator::cgp_streambuf::LineCount() {
924void CodeGenerator::cgp_streambuf::IndentInc() {
929void CodeGenerator::cgp_streambuf::IndentDec() {
934void CodeGenerator::cgp_streambuf::XmlTextEscape(
bool on) {
941void CodeGenerator::cgp_streambuf::XmlCdataEscape(
bool on) {
948void CodeGenerator::cgp_streambuf::Mute(
bool on) {
954bool CodeGenerator::cgp_streambuf::Mute() {
959void CodeGenerator::cgp_streambuf::MuteVspace(
bool on) {
Code-generator common base class.
Event attributes for the purpose of code generation.
TimeConstraint mTimeConstraint
Timer definition (indicate timer event iff mInitialValue non-empty)
std::vector< OutputAction > mActions
List of actions to perform (output events only)
EventSet mResetEvents
Events that reset this timer.
std::string mInitialValue
Initial value (literal to allow for advanced units, empty string for "not a timer")
EventSet mStopEvents
Events that stop this timer.
EventSet mStartEvents
Events that start this timer.
Code-generation common base.
std::string mOutMode
output file name (base)
virtual std::string LineCount(void)
LineFeed (convenience support for derived classes)
char mMuteMode
current output mode
std::string EventName(Idx index) const
Faudes-event name lookup.
virtual void LineFeed(int lines=1)
LineFeed (convenience support for derived classes)
virtual void XmlCdataEscape(bool on)
XmlCdataEscape (escape "]]>")
virtual const std::string & Name(void) const
Get objects's name (reimplementing base faudes::Type)
std::map< Idx, int > mEventBitAddress
mapping from faudes event idx to bit address (descending priority, range 0 .
int EventBitAddress(Idx idx)
Get event bit-address from faudes Idx (consecutive, starts at 0)
const TimedGenerator & At(int i) const
Direct access for read-only access of generators.
LineIterator LinesEnd()
Access to line records by iterator.
static std::vector< std::string > Registry(void)
Access registry contents.
std::vector< bool > EventBitMask(Idx idx)
Get vector representation for a single faudes event Idx.
std::vector< int > mWordAddressVector
Look-up table to map a bit-address to the word-index.
std::vector< word_t > mBitMaskVector
Look-up table to map a bit-address to the word-bitmask.
int mLastInputEvent
highest bit-address with input (or timer) event (-1 for none)
virtual void XmlTextEscape(bool on)
XmlTextEscape (escape "<", ">", "&", "\"" and "'")
virtual void MuteComments(bool on)
Mute comments (convenience support for derived classes)
std::vector< std::map< int, Idx > > mStateFaudesIndex
mapping from vector state idx to faudes index
virtual void DoReadTargetConfiguration(TokenReader &rTr)
Reads global configuration from TokenReader, excl.
std::map< std::string, ActionAddress >::iterator ActionAddressIterator
Access to action record by iterator.
virtual void DoGenerate(void)=0
pure virtual interface to code generation
std::ostream * pErrStream
error stream
std::string mRecentMutedComment
recent muted comment
std::vector< std::vector< int > > mTransitionVector
compiled transition-sets, represented as vectors of integers with 0 as separator
EventSet mInternalEvents
used events that are configured as internal events (excl.
int mLastOutputEvent
highest bit-address with output event (-1 for none)
FlagIterator FlagsBegin()
Access to flag records by iterator.
int EventBitMaskSize(void)
Get overall number of events.
static CodeGenerator * New(const std::string &type)
Instantiate by identifier (returns 0 on unknown class)
TimerIterator TimersBegin()
Access to timer records by iterator.
static void Register(const std::string &type, CodeGenerator *(*newcg)(void))
Insert derived class in the registry.
virtual void IndentInc()
Indentation (convenience support for derived classes)
virtual ~CodeGenerator(void)
Destructor.
EventSet mOutputEvents
used events that are configured as outputs
TimerIterator TimersEnd()
Access to timer records by iterator.
Idx EventIndex(const std::string &rName) const
Faudes-event index lookup.
std::map< std::string, LineAddress > mLines
input event generation
Idx EventFaudesIdx(int idx)
Get faudes Idx from target Idx (aka from bit-address + 1)
TimerActionIterator TimerActionsBegin()
Access to timer records by iterator.
int mWordSize
compressed boolean capacity of target type word
std::map< int, Idx > mEventFaudesIdx
mapping from bit address to faudes event idx
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Writes the configuration to TokenWriter, see faudes Type for public wrappers.
virtual void MuteMode(char mode)
Set current mute mode.
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Read the configuration from TokenReader, see faudes Type for public wrappers.
std::ostream * pOutStream
output stream
std::vector< TimedGenerator > mGenerators
list of executors
bool mMuteComments
mute comments
virtual Idx StateFaudesIdx(size_t git, int idx)
Get faudes state index (refer to vector representation as default, overload in CodePrimitives)
virtual int EventTargetIdx(Idx idx)
Get target event Idx from faudes Idx (use bit-address + 1)
LineIterator LinesBegin()
Access to line records by iterator.
int mVerbLevel
diagnpstic-output level
void Insert(const std::string &file)
Add a Generator from file.
int mIntegerSize
compressed boolean capacity of target type integer
std::map< std::string, ActionAddress > mActionAddresses
action addresses
EventSet mInputEvents
used events that are configured as inputs (incl timer)
FlagIterator FlagsEnd()
Access to flag records by iterator.
std::map< std::string, TimerConfiguration >::iterator TimerIterator
Access to timer records by iterator.
virtual std::ostream & Output(void)
Output stream.
std::map< std::string, TimerAction > mTimerActions
timer actions by event name
virtual void MuteCond(char mode)
Set mode condition.
std::vector< word_t > WordVectorFromBitVector(const std::vector< bool > &vect)
Convert boolean vector to word array.
std::map< std::string, LineAddress >::iterator LineIterator
Access to line records by iterator.
void Verbose(int level, std::ostream *altout=0)
Set verbosity level.
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 void DoCompile(void)
virtual hook to input parameter compilation
std::vector< std::map< Idx, int > > mStateVectorAddress
mapping from faudes state idx to vector index
virtual void Compile(void)
Compile input data for alternative representation.
cgEventSet mAlphabet
event configuration by attributes
virtual void Comment(const std::string &text)
Write a comment (reimplement in derived classes, call base)
word_t WordFromBitVector(const std::vector< bool > &vect, int wordindex)
Extract individual word from boolean vector.
CodeGenerator(void)
Constructor.
const std::string & OutputString(void)
Get accumulated output as string.
virtual void Clear(void)
Clear all data.
const std::vector< int > & TransitionVector(size_t git)
Get target state index (refer to vector representation as default, overload in CodePrimitives)
std::vector< std::string > mGeneratorNames
list of filenames when generator are read from file
std::vector< bool > mUsingVectorAddressStates
configuration of state indexing per generator
Idx Size(void) const
Number of generators.
virtual int StateTargetIdx(size_t git, Idx idx)
Get target state index (refer to vector representation as default, overload in CodePrimitives)
std::map< std::string, TimerConfiguration > mTimers
timer definitions
virtual void Generate(void)
Generate code.
std::map< std::string, FlagExpression >::iterator FlagIterator
Access to flag records by iterator.
virtual void IndentDec()
Indentation (convenience support for derived classes)
ActionAddressIterator ActionAddressesEnd()
Access to action addresses by iterator.
TimerActionIterator TimerActionsEnd()
Access to timer records by iterator.
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
Write global configuration to TokenWriter, excl.
ActionAddressIterator ActionAddressesBegin()
Access to action addresses by iterator.
std::map< std::string, FlagExpression > mFlags
input event generation
unsigned long word_t
Code-generator internal data type of target words.
EventSet mUsedEvents
configured events that are referred to by some generator
std::map< std::string, TimerAction >::iterator TimerActionIterator
Access to timer records by iterator.