30 FD_DCG(
"CodeGenerator()::CodeGenerator()");
40 FD_DCG(
"CodeGenerator()::~CodeGenerator()");
41 if(pOutBuffer)
delete pOutBuffer;
45 std::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");
115 void 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(PrependDirectory(dirname,token.StringValue()));
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)) {
166 if(token.StringValue()==
"TargetConfiguration") {
167 rTr.ReadBegin(
"TargetConfiguration");
169 rTr.ReadEnd(
"TargetConfiguration");
174 if(token.StringValue()==
"Generators") {
175 DoReadGenerators(rTr);
176 FCG_VERB1(
"CodeGenerator::Generator(): found #" <<
Size() <<
" generators");
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);
201 void 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;
260 FCG_VERB0(
"CodeGenerator::Compile(): compile to internal representation");
263 FCG_VERB0(
"CodeGenerator::Compile(): done");
269 FD_DCG(
"CodeGenerator::DoCompile()");
272 for(
size_t git=0; git<
Size(); ++git) {
273 EventSet::Iterator eit=
At(git).AlphabetBegin();
274 for(; eit!=
At(git).AlphabetEnd(); ++eit) {
276 FCG_ERR(
"CodeGenerator::Compile(): event [" <<
EventName(*eit) <<
"] has unspecified execution semantics")
282 FCG_VERB0(
"CodeGenerator::Compile(): event configuration mismatch: #" << (
mAlphabet-
mUsedEvents).
Size() <<
" unused events");
285 EventSet::Iterator eit;
295 if(
mAlphabet.Attribute(*eit).Input())
continue;
296 if(
mAlphabet.Attribute(*eit).Timer())
continue;
297 if(
mAlphabet.Attribute(*eit).Output())
continue;
300 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: overall used events: #" <<
mUsedEvents.Size());
301 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: input events incl timer: #" <<
mInputEvents.Size());
302 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: output events: #" <<
mOutputEvents.Size());
303 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: internal events excl timer: #" <<
mInternalEvents.Size());
305 FD_DCG(
"CodeGenerator::DoCompile(): sorting events");
306 std::multimap<int, Idx> sortev;
310 if((prio<0) || (prio > 10000)) {
311 FCG_ERR(
"CodeGenerator::Compile(): priority out of range [0, 10000] for event [" <<
EventName(*eit) <<
"]");
317 sortev.insert(std::pair<int,Idx>(-prio,*eit));
320 FD_DCG(
"CodeGenerator::DoCompile(): set up bitaddress");
325 std::multimap<int, Idx>::iterator sit;
327 for(sit=sortev.begin(); sit!=sortev.end(); sit++) {
340 FCG_VERB1(
"CodeGenerator::Compile(): bitmask size #" <<
EventBitMaskSize() <<
" bits");
342 FD_DCG(
"CodeGenerator::DoCompie(): set up transition vector");
347 for(Idx gid=0; gid<
Size(); gid++) {
348 FD_DCG(
"CodeGenerator::DoCompile(): set up transition vector " << gid);
355 const Generator gen =
At(gid);
357 FCG_ERR(
"CodeGenerator::Complie(): generator must not be empty [" << gen.Name() <<
"]");
361 statevect.resize(gen.MaxStateIndex()+1,0);
362 IndexSet::Iterator sit= gen.StatesBegin();
363 for(;sit!=gen.StatesEnd();++sit) {
364 targetindex[*sit]= (int) transvect.size();
365 statevect[*sit] = (int) transvect.size();
366 faudesindex[(int) transvect.size()]= *sit;
367 TransSet::Iterator tit = gen.TransRelBegin(*sit);
368 TransSet::Iterator tit_end = gen.TransRelEnd(*sit);
369 for(;tit!=tit_end;++tit) {
370 transvect.push_back((
int) tit->Ev);
371 transvect.push_back((
int) tit->X2);
373 transvect.push_back(0);
376 for(
size_t vit=0; vit< transvect.size(); ++vit) {
377 int ev = transvect[vit];
380 int x2 = transvect[++vit];
381 transvect[vit]=targetindex[x2];
383 FCG_VERB0(
"CodeGenerator::Compile(): raw data for generator [" << gen.Name() <<
"] amounts to #"
391 if(!
mAlphabet.Attribute(*eit).Input())
continue;
392 const std::vector<AttributeCodeGeneratorEvent::InputTrigger>& triggers =
mAlphabet.Attribute(*eit).mTriggers;
393 for(
size_t i=0; i<triggers.size(); i++) {
394 if(triggers[i].mExe) {
395 std::string flagaddr=triggers[i].mAddress;
396 mFlags[flagaddr].mEvents.Insert(*eit);
397 mFlags[flagaddr].mAddress=flagaddr;
399 if((triggers[i].mNeg) || (triggers[i].mPos)) {
400 std::string lineaddr=triggers[i].mAddress;
402 if(
mLines[lineaddr].mStatic != triggers[i].mStatic)
403 FCG_ERR(
"CodeGenerator::Compile(): inconsistent static option on input line [" << lineaddr <<
"]");
405 mLines[lineaddr].mAddress=lineaddr;
406 if(triggers[i].mNeg)
mLines[lineaddr].mNegEvents.Insert(*eit);
407 if(triggers[i].mPos)
mLines[lineaddr].mPosEvents.Insert(*eit);
408 if(triggers[i].mNeg && triggers[i].mStatic)
mLines[lineaddr].mNegStatics.Insert(*eit);
409 if(triggers[i].mPos && triggers[i].mStatic)
mLines[lineaddr].mPosStatics.Insert(*eit);
410 mLines[lineaddr].mStatic=triggers[i].mStatic;
414 std::map<std::string, LineAddress>::iterator lit=
mLines.begin();
416 for(;lit!=
mLines.end();++lit) lit->second.mBitAddress=linecnt++;
417 FCG_VERB1(
"CodeGenerator::Compile(): monitoring #" <<
mLines.size() <<
" lines for edge detection");
425 if(!attr.
Timer())
continue;
430 mTimers[timerev].mAddress= timerev;
431 mTimers[timerev].mElapseEvent= timerev;
433 mTimers[timerev].mStartEvents= starts;
434 mTimers[timerev].mStopEvents= stops;
435 mTimers[timerev].mResetEvents= resets;
436 EventSet::Iterator ait;
437 ait = starts.Begin();
438 for(;ait!=starts.End();++ait)
441 for(;ait!=stops.End();++ait)
443 ait = resets.Begin();
444 for(;ait!=resets.End();++ait)
447 FCG_VERB1(
"CodeGenerator::Compile(): operating #" <<
mTimers.size() <<
" timers controlled by #" <<
mTimerActions.size() <<
" events");
454 if(!attr.
Output())
continue;
456 const std::vector<AttributeCodeGeneratorEvent::OutputAction>& actions =
mAlphabet.Attribute(*eit).mActions;
457 for(
size_t i=0; i<actions.size(); i++) {
458 std::string actaddr=actions[i].mAddress;
464 FCG_VERB1(
"CodeGenerator::Compile(): operating #" <<
mActionAddresses.size() <<
" action primitives controlled by #" << evcn <<
" events");
474 FD_DCG(
"CodeGenerator::DoCompile(): ok");
480 std::map<Idx,int>::const_iterator sit;
498 std::map<int,Idx>::const_iterator sit;
507 std::vector<bool> res;
509 while(res.size()< vsize) res.push_back(
false);
512 if(baddr<0)
return res;
521 std::vector<bool> res;
523 while(res.size()< vsize) res.push_back(
false);
525 EventSet::Iterator eit;
526 for(eit=eset.Begin(); eit!=eset.End(); eit++) {
528 if(baddr<0)
continue;
544 for(;(shift<
mWordSize) && (bidx<vect.size()); shift++,bidx++)
545 if(vect[bidx]) res |= (1UL<<shift);
551 std::vector< word_t > res;
553 for(
size_t vidx=0; vidx < vect.size(); ++vidx) {
554 if(!vect[vidx])
continue;
568 std::map<Idx,int>::const_iterator sit;
576 std::map<int,Idx>::const_iterator sit;
656 FCG_VERB0(
"CodeGenerator::Generate(): generating code to \"[" <<
mOutMode <<
"]\"");
658 bool tmpstream=
false;
661 if(pOutBuffer!=0)
delete pOutBuffer;
662 pOutBuffer =
new cgp_streambuf(
mOutMode);
670 FCG_VERB0(
"CodeGenerator::Generate(): generated " <<
LineCount() <<
" lines of code.");
685 static std::string ems(
"");
686 if(!pOutBuffer)
return ems;
687 return pOutBuffer->Buffer();
691 if(!pOutBuffer)
return;
693 if(!strbuf.empty()) FCG_VERB1(
"CodeGenerator::OutputString(): setting non-trivial not implemented")
699 if(!pOutBuffer)
return;
700 pOutBuffer->Mute(mode!=
'*');
706 if(!pOutBuffer)
return;
708 pOutBuffer->Mute(mute);
726 if(!pOutBuffer)
return;
727 pOutBuffer->IndentInc();
732 if(!pOutBuffer)
return;
733 pOutBuffer->IndentDec();
738 if(!pOutBuffer)
return;
739 pOutBuffer->XmlTextEscape(on);
744 if(!pOutBuffer)
return;
745 pOutBuffer->XmlCdataEscape(on);
753 if(pOutBuffer->Mute())
764 if(!pOutBuffer)
return;
765 pOutBuffer->MuteVspace(on);
771 if(!pOutBuffer)
return std::string();
772 std::stringstream res;
773 res <<
"#" << pOutBuffer->LineCount();
774 return std::string(res.str());
779 CodeGenerator::cgp_streambuf::cgp_streambuf(std::string mode) :
791 if(mode ==
"std::string") {
792 mMode =
"std::string";
796 else if(mode==
"std::cout") {
803 mpFOutStream =
new std::ofstream();
804 mpFOutStream->exceptions(std::ios::badbit|std::ios::failbit);
806 mpFOutStream->open(mode.c_str(), std::ios::out|std::ios::trunc);
808 catch (std::ios::failure&) {
809 std::stringstream errstr;
810 errstr <<
"Exception opening/writing file \""<< mode <<
"\"";
811 throw Exception(
"CodeGenerator::Generate()", errstr.str(), 1);
818 CodeGenerator::cgp_streambuf::~cgp_streambuf() {
821 mpFOutStream->close();
827 std::streambuf::int_type CodeGenerator::cgp_streambuf::overflow (int_type c) {
830 if(c == EOF)
return EOF;
834 if(mMuteVspace && (c==
'\n') && (mBuffer.size()==0))
return c;
837 mBuffer.push_back(c);
846 for(;scnt>0;--scnt) mBuffer.push_back(
' ');
852 { mBuffer +=
"<";
return c;}
854 { mBuffer +=
">";
return c;}
856 { mBuffer +=
"&";
return c;}
858 { mBuffer +=
"'";
return c;}
860 { mBuffer +=
""";
return c;}
864 if((c==
'>') && (mBuffer.size()>=2))
865 if(mBuffer.at(mBuffer.size()-1) ==
']')
866 if(mBuffer.at(mBuffer.size()-2) ==
']')
867 mBuffer +=
"]]><![CDATA[";
870 mBuffer.push_back(c);
876 void CodeGenerator::cgp_streambuf::Flush() {
878 if(!pOutStream)
return;
881 (*pOutStream) << mBuffer;
882 (*pOutStream) << std::flush;
883 }
catch(std::ios::failure&) {
884 std::stringstream errstr;
885 errstr <<
"Exception writing to file \""<< mMode <<
"\"";
886 throw Exception(
"CodeGenerator::Generate()", errstr.str(), 1);
893 const std::string& CodeGenerator::cgp_streambuf::Buffer(){
937 void CodeGenerator::cgp_streambuf::Mute(
bool on) {
943 bool CodeGenerator::cgp_streambuf::Mute() {