35 void usage(
const std::string& rMessage=
"") {
38 std::cerr << rMessage << std::endl;
39 std::cout <<
"" << std::endl;
42 std::cerr << std::endl;
43 std::cerr <<
"utility to generates c code from an rti-file to " << std::endl;
44 std::cerr <<
"1) register faudes-types and -functions with the run-time interface," << std::endl;
45 std::cerr <<
"2) extract c declarations for bindings interface code." << std::endl;
46 std::cerr << std::endl;
47 std::cerr <<
"usage:" << std::endl;
48 std::cerr <<
" rti2code [-swig|-loader] <rti input file> <output basename>" << std::endl;
49 std::cerr <<
" rti2code -merge <rti input files> <output rti-file>" << std::endl;
50 std::cerr << std::endl;
51 std::cerr <<
"[note: the -loader flag will produce .h/.cpp files to instantiate prototypes" << std::endl;
52 std::cerr <<
"[note: the -swig flag will produce a .i file for swig include" << std::endl;
53 std::cerr <<
"[note: the -flat flag circumvents an issue with SWIG pre 4.1.0]" << std::endl;
62 int main(
int argc,
char *argv[]) {
72 for(; pos<argc; pos++) {
73 std::string option(argv[pos]);
75 if((option==
"-?") || (option==
"--help")) {
80 if(option==
"-loader") {
95 if(option==
"-merge") {
100 if(option.c_str()[0]==
'-') {
101 usage(
"unknown option "+ option);
109 if(merge && (loader || swig)) {
110 usage(
"mismatching options: either merge or code generation");
112 if(!merge && !(loader || swig)) {
113 usage(
"mismatching options: either merge or code generation");
116 usage(
"mismatching options: flat is only applicable to swig");
118 if(merge && (argc-pos <2)) {
119 usage(
"mismatching agruments: to few files to merge");
121 if(!merge && (argc-pos !=2)) {
122 usage(
"mismatching agruments: need one source and one destination for code generation");
128 for(; pos< argc-1; pos++) {
133 if(std::string(argv[argc-1]) !=
"-") {
145 std::ofstream rtiheader;
146 std::ofstream rticode;
147 std::ofstream swigheader;
149 rtiheader.open((std::string(argv[pos])+
".h").c_str(), std::ios::out);
150 rticode.open((std::string(argv[pos])+
".cpp").c_str(), std::ios::out);
153 swigheader.open((std::string(argv[pos])+
".i").c_str(), std::ios::out);
158 rtiheader <<
"/* rti2code: autogenerated libFAUDES rti registration: ";
160 rticode <<
"/* rti2code: autogenerated libFAUDES rti registration: ";
164 swigheader <<
"/* rti2code: autogenerated libFAUDES swig bindings declarations: ";
170 rticode <<
"namespace faudes {" << std::endl;
171 rticode <<
"/* Auto-register faudes types */" << std::endl;
180 std::string ctype=tit->second->CType();
181 std::string ftype=tit->second->Name();
183 if(ctype==
"")
continue;
185 size_t pos=ctype.find(
"faudes::");
186 if(pos!=std::string::npos)
187 ctype=ctype.substr(std::string(
"faudes::").length());
189 if(!tit->second->AutoRegistered())
continue;
191 std::cout <<
"rti2code: generating auto-registration code for \"" << ftype <<
"\"" << std::endl;
193 std::string rtiname = std::string(
"gRti") +
ToStringInteger(tcnt) +
"Register" + ftype;
194 rticode <<
"AutoRegisterType<" << ctype <<
"> " << rtiname <<
"(\"" << ftype <<
"\");";
195 rticode << std::endl;
197 if(tit->second->ElementTag()!=
"") {
198 rtiname = std::string(
"gRti") +
ToStringInteger(tcnt) +
"ElementTag" + ftype;
199 rticode <<
"AutoRegisterElementTag<" << ctype <<
"> " << rtiname <<
"(\"" << ftype <<
200 "\", \"" << tit->second->ElementTag() <<
"\");";
201 rticode << std::endl;
204 if(tit->second->ElementType()!=
"") {
205 rtiname = std::string(
"gRti") +
ToStringInteger(tcnt) +
"ElementType" + ftype;
206 rticode <<
"AutoRegisterElementType<" << ctype <<
"> " << rtiname <<
"(\"" << ftype <<
207 "\", \"" << tit->second->ElementType() <<
"\");";
208 rticode << std::endl;
215 rticode <<
"} // namespace" << std::endl;
220 rtiheader <<
"namespace faudes {" << std::endl;
221 rtiheader <<
"void LoadRegisteredTypes(void);" << std::endl;
222 rtiheader <<
"} // namespace" << std::endl;
227 rticode <<
"namespace faudes {" << std::endl;
228 rticode <<
"/* Register faudes types */" << std::endl;
229 rticode <<
"void LoadRegisteredTypes(void) {" << std::endl;
237 std::string ctype=tit->second->CType();
239 if(ctype==
"")
continue;
241 size_t pos=ctype.find(
"faudes::");
242 if(pos!=std::string::npos)
243 ctype=ctype.substr(std::string(
"faudes::").length());
245 std::cout <<
"rti2code: generating registration code for \"" << tit->second->Name() <<
"\"" << std::endl;
247 rticode <<
" TypeRegistry::G()->Insert<" << ctype <<
">(\"" << tit->second->Name() <<
"\");";
248 rticode << std::endl;
254 rticode <<
"}" << std::endl;
255 rticode <<
"} // namespace" << std::endl;
261 rtiheader <<
"namespace faudes {" << std::endl;
262 rtiheader <<
"void LoadRegisteredFunctions(void);" << std::endl;
263 rtiheader <<
"} // namespace" << std::endl;
268 rticode <<
"namespace faudes {" << std::endl;
269 rticode <<
"/* Register faudes functions */" << std::endl;
270 rticode <<
"void LoadRegisteredFunctions(void) {" << std::endl;
275 rtiheader <<
"namespace faudes {" << std::endl;
285 std::string ctype=fdef->
CType();
286 std::string fname = fdef->
Name();
288 if(ctype==
"")
continue;
290 size_t pos=ctype.find(
"faudes::");
291 if(pos!=std::string::npos)
292 ctype=ctype.substr(std::string(
"faudes::").length());
295 std::cout <<
"rti2cocde: function registration: " << fname <<
": no signatures" << std::endl;
299 std::vector< std::vector<std::string> > cparams;
300 std::vector< std::vector<Parameter::ParamAttr> > cattrib;
301 std::vector< std::vector<bool> > cretval;
309 for(
int j=0; j<sigi.
Size(); j++) {
311 std::string ftype=sigi.
At(j).
Type();
315 if(fcret) retcount++;
327 if(retcount>1)
break;
329 size_t pos=ctype.find(
"faudes::");
330 if(pos!=std::string::npos)
331 ctype=ctype.substr(std::string(
"faudes::").length());
333 cparams.at(i).push_back(ctype);
334 cattrib.at(i).push_back(fattr);
335 cretval.at(i).push_back(fcret);
338 if((
int) cparams.at(i).size()!=sigi.
Size()) {
339 std::cout <<
"rti2code: function registration: " << fname <<
": cannot interpret signature "
340 << sigi.
Name() << std::endl;
346 std::cout <<
"rti2code: generating rti wrapper for \"" << fdef->
Name() <<
"\"" <<
347 " #" << cparams.size() <<
" variants" << std::endl;
348 std::string rtiname = std::string(
"Rti") +
ToStringInteger(fcnt) + ctype;
351 rticode <<
" FunctionRegistry::G()->Insert<" << rtiname <<
">(\"" << fname <<
"\");" << std::endl;
355 rtiheader <<
"/* Function class for C++ function " << ctype <<
"*/" << std::endl;
356 rtiheader <<
"class " << rtiname <<
" : public Function { " << std::endl;
357 rtiheader <<
"public:" << std::endl;
358 rtiheader <<
" using Function::operator=;" << std::endl;
359 rtiheader << rtiname <<
"(const FunctionDefinition* fdef) : Function(fdef) {};" << std::endl;
360 rtiheader <<
"virtual Function* New(void) const { return new " << rtiname <<
"(pFuncDef); };" << std::endl;
361 rtiheader <<
"protected:" << std::endl;
365 for(
unsigned int i=0; i<cparams.size(); i++)
366 for(
unsigned int j=0; j<cparams.at(i).size(); j++)
367 rtiheader << cparams.at(i).at(j) <<
"* " <<
"mP_" << i <<
"_" << j <<
";" << std::endl;
371 rtiheader <<
"virtual bool DoTypeCheck(int n) {" << std::endl;
372 rtiheader <<
" bool res=false;" << std::endl;
373 rtiheader <<
" switch(mVariantIndex) { "<< std::endl;
374 for(
unsigned int i=0; i<cparams.size(); i++) {
375 rtiheader <<
" case " << i <<
": { // variant " << fdef->
Variant(i).
Name() << std::endl;
376 rtiheader <<
" switch(n) { "<< std::endl;
377 for(
unsigned int j=0; j<cparams.at(i).size(); j++) {
378 rtiheader <<
" case " << j <<
": ";
379 rtiheader <<
" res=DoTypeCast<" << cparams.at(i).at(j) <<
">(" << j <<
", mP_" << i <<
"_" << j <<
"); ";
380 rtiheader <<
"break; "<< std::endl;
382 rtiheader <<
" default: break; " << std::endl;
383 rtiheader <<
" } "<< std::endl;
384 rtiheader <<
" break; "<< std::endl;
385 rtiheader <<
" } "<< std::endl;
387 rtiheader <<
" default: break; " << std::endl;
388 rtiheader <<
" } "<< std::endl;
389 rtiheader <<
" return res;" << std::endl;
390 rtiheader <<
"};" << std::endl;
394 rtiheader <<
"virtual void DoExecute(void) {" << std::endl;
398 rtiheader <<
" switch(mVariantIndex) { "<< std::endl;
399 for(
unsigned int i=0; i<cparams.size(); i++) {
400 rtiheader <<
" case " << i <<
": { // variant " << fdef->
Variant(i).
Name() << std::endl;
403 for(
unsigned int j=0; j<cparams.at(i).size(); j++) {
404 if(!cretval.at(i).at(j))
continue;
406 if(cparams.at(i).at(j) ==
"Integer") {
407 rtiheader <<
"*(mP_" << i <<
"_" << j <<
"->CReference()) = ";
410 if(cparams.at(i).at(j) ==
"Boolean") {
411 rtiheader <<
"*(mP_" << i <<
"_" << j <<
"->CReference()) = ";
414 if(cparams.at(i).at(j) ==
"String") {
415 rtiheader <<
"*(mP_" << i <<
"_" << j <<
"->CReference()) = ";
418 rtiheader <<
"*mP_" << i <<
"_" << j <<
" = ";
421 rtiheader << ctype <<
"(";
424 for(
unsigned int j=0; j<cparams.at(i).size(); j++) {
425 if(cretval.at(i).at(j))
continue;
426 if((parpos++)!=0) rtiheader <<
" ,";
428 if(cparams.at(i).at(j) ==
"Integer") {
429 rtiheader <<
"*(mP_" << i <<
"_" << j <<
"->CReference())";
432 if(cparams.at(i).at(j) ==
"Boolean") {
433 rtiheader <<
"*(mP_" << i <<
"_" << j <<
"->CReference())";
436 if(cparams.at(i).at(j) ==
"String") {
437 rtiheader <<
"*(mP_" << i <<
"_" << j <<
"->CReference())";
440 rtiheader <<
"*mP_" << i <<
"_" << j;
442 rtiheader <<
"); break; };" << std::endl;
445 rtiheader <<
" default: break; " << std::endl;
446 rtiheader <<
" }; "<< std::endl;
448 rtiheader <<
"}; "<< std::endl;
450 rtiheader <<
"};" << std::endl;
455 swigheader <<
"/* faudes-function \"" << fname <<
"\" */" << std::endl;
460 std::string plugin=fdef->
PlugIn();
461 swigheader <<
"#if " <<
"( SwigModule == \"Swig" << plugin <<
"\")";
463 swigheader << std::endl;
469 swigheader <<
"%rename(" << fname <<
") " << ctype <<
";" << std::endl;
474 std::vector< std::string > lfdefs;
475 std::vector< std::string > lrtypes;
476 std::vector< std::string > lhelp;
478 for(
unsigned int i=0; i<cparams.size(); i++) {
480 std::string lrtype=
"void";
481 for(
unsigned int j=0; j<cparams.at(i).size(); j++) {
482 if(!cretval.at(i).at(j))
continue;
484 if(cparams.at(i).at(j) ==
"Integer") {
488 if(cparams.at(i).at(j) ==
"Boolean") {
492 if(cparams.at(i).at(j) ==
"String") {
493 lrtype=
"std::string";
496 lrtype = cparams.at(i).at(j);
500 lrtypes.push_back(lrtype);
502 std::string lfdef = ctype +
"(";
505 for(
unsigned int j=0; j<cparams.at(i).size(); j++) {
506 if(cretval.at(i).at(j))
continue;
507 if((parpos++)!=0) lfdef +=
", ";
512 if(cparams.at(i).at(j) ==
"Integer") {
513 lfdef +=
"long int&";
516 if(cparams.at(i).at(j) ==
"Boolean") {
520 if(cparams.at(i).at(j) ==
"String") {
521 lfdef +=
"std::string&";
524 lfdef += cparams.at(i).at(j) +
"&";
526 if(cparams.at(i).at(j) ==
"Boolean" || cparams.at(i).at(j) ==
"String"
527 || cparams.at(i).at(j) ==
"Integer")
533 lfdefs.push_back(lfdef);
535 std::string luasig =
" " + fname +
"(";
536 bool leftcomma =
false;
537 bool rightcomma =
false;
538 for(
unsigned int j=0; j<cparams.at(i).size(); j++) {
540 if(cparams.at(i).at(j) ==
"Boolean" || cparams.at(i).at(j) ==
"String"
541 || cparams.at(i).at(j) ==
"Integer")
543 if(leftcomma) luasig =
"," + luasig;
545 luasig=cparams.at(i).at(j) + luasig;
550 if(rightcomma) luasig +=
", ";
552 luasig += sigi.
At(j).
Str();
558 std::string topic= fdef->
PlugIn();
560 if(topic==
"CoreFaudes") {
564 if(topic.length()>0) topic.at(0)=toupper(topic.at(0));
565 if(key1.length()>0) key1.at(0)=toupper(key1.at(0));
566 lhelp.push_back(
"SwigHelpEntry(\"" + topic +
"\", \"" + key1 +
"\", \"" +
573 for(
unsigned int i=1; i<lfdefs.size();i++) {
576 if(lfdefs.at(i)==lfdefs.at(j))
break;
579 if(lrtypes.at(j)==
"void")
580 {lfdefs[j]=
"";
continue;}
581 if(lrtypes.at(i)==
"void")
582 {lfdefs[i]=
"";
continue;}
587 for(
unsigned int i=0; i<lfdefs.size(); i++) {
588 if(lfdefs.at(i)==
"")
continue;
589 swigheader << lrtypes.at(i) <<
" " << lfdefs.at(i) <<
";" << std::endl;
591 if(lhelp.at(i)==
"")
continue;
592 swigheader << lhelp.at(i) <<
";" << std::endl;
594 std::cout <<
"rti2code: generating swig interface for function \"" << fdef->
Name() <<
"\"" <<
595 " #" << lcount <<
" variants" << std::endl;
599 swigheader <<
"#endif " << std::endl;
601 swigheader << std::endl;
609 rtiheader <<
"} // namespace" << std::endl;
614 rticode <<
"}" << std::endl;
615 rticode <<
"} // namespace" << std::endl;
const std::string & Name(void) const
std::string KeywordAt(int pos) const
const std::string & PlugIn(void) const
const std::string & TextDoc(void) const
const std::string & CType(void) const
const Signature & Variant(const std::string &rName) const
int VariantsSize(void) const
static FunctionRegistry * G()
std::map< std::string, FunctionDefinition * >::const_iterator Iterator
void MergeDocumentation(TokenReader &rTr)
Iterator Begin(void) const
std::string Str(void) const
const std::string & Type(void) const
const ParamAttr & Attribute(void) const
const std::string & Name(void) const
const Parameter & At(int n) const
void MergeDocumentation(TokenReader &rTr)
const TypeDefinition & Definition(const std::string &rTypeName) const
static TypeRegistry * G()
bool Exists(const std::string &rName) const
std::map< std::string, TypeDefinition * >::const_iterator Iterator
void SaveRegistry(const std::string &rPath)
void LoadRegistry(const std::string &rPath)
std::string VersionString()
std::string PluginsString()
std::string ToStringInteger(Int number)
int main(int argc, char *argv[])
void usage(const std::string &rMessage="")