libFAUDES

Sections

Index

rti2code.cpp

Go to the documentation of this file.
00001 /** rti2code.cpp  Utility to generate registry initialisation code from rti files */
00002 
00003 /* FAU Discrete Event Systems Library (libfaudes)
00004 
00005 Copyright (C) 2009 Ruediger Berndt
00006 Copyright (C) 2009 Thomas Moor
00007 
00008 This library is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU Lesser General Public
00010 License as published by the Free Software Foundation; either
00011 version 2.1 of the License, or (at your option) any later version.
00012 
00013 This library is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 Lesser General Public License for more details.
00017 
00018 You should have received a copy of the GNU Lesser General Public
00019 License along with this library; if not, write to the Free Software
00020 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00021    
00022 
00023 #include <string>
00024 #include <iostream>
00025 #include <fstream>
00026 #include "corefaudes.h"
00027 
00028 
00029 using namespace faudes;
00030 
00031 int main(int argc, char *argv[]) {
00032 
00033   // simple command line
00034   if(argc != 3) {
00035     std::cerr << "rti2code: " << FDVersionString()  << std::endl;
00036     std::cerr << std::endl;
00037     std::cerr << "utility to generates c code from an rti-file to " << std::endl;
00038     std::cerr << "1) register faudes-types and -functions with the run-time interface," << std::endl;
00039     std::cerr << "2) extract c declarations for luabindings interface code." << std::endl;
00040     std::cerr << std::endl;
00041     std::cerr << "usage: rti2code <rti input file> <output basename>" << std::endl;
00042     exit(1);
00043   }
00044 
00045   // load registry 
00046   LoadRegistry(argv[1]);
00047 
00048   // code output streams
00049   std::ofstream rtiheader;
00050   rtiheader.open((std::string(argv[argc-1])+".h").c_str(), std::ios::out);
00051   std::ofstream rticode;
00052   rticode.open((std::string(argv[argc-1])+".cpp").c_str(), std::ios::out);
00053   std::ofstream luaheader;
00054   luaheader.open((std::string(argv[argc-1])+".i").c_str(), std::ios::out);
00055 
00056   // introduce myself
00057   rtiheader << "/* rti2code: autogenerated libFAUDES rti registration: "; 
00058   rtiheader << FDVersionString() << " "  << FDPluginsString() << " */" << std::endl << std::endl; 
00059   rticode   << "/* rti2code: autogenerated libFAUDES rti registration: "; 
00060   rticode   << FDVersionString() << " "  << FDPluginsString() << " */" << std::endl << std::endl; 
00061   luaheader << "/* rti2code: autogenerated libFAUDES luabindings declarations: "; 
00062   luaheader << FDVersionString() << " "  << FDPluginsString() << " */" << std::endl << std::endl; 
00063 
00064   // c static objects : auto load types
00065   rticode << "namespace faudes {" << std::endl;
00066   rticode << "/* Auto-register faudes types */" << std::endl;
00067 
00068   // traverse type registry to figure faudes types
00069   TypeRegistry::Iterator  tit;
00070   int tcnt;
00071   for(tit=TypeRegistry::G()->Begin(), tcnt=1; tit!=TypeRegistry::G()->End();tit++,tcnt++) {
00072     // get c/f type 
00073     std::string ctype=tit->second->CType();
00074     std::string ftype=tit->second->Name();
00075     // bail out if no c type specified
00076     if(ctype=="") continue;
00077     // remove name space faudes
00078     size_t pos=ctype.find("faudes::");
00079     if(pos!=std::string::npos) 
00080       ctype=ctype.substr(std::string("faudes::").length());
00081     // bail out no auto-registration specified
00082     if(!tit->second->AutoRegister()) continue;
00083     // report
00084     std::cout << "Generating auto-registration code for \"" << ftype << "\"" << std::endl;
00085     // produce c code
00086     std::string rtiname = std::string("gRti") + ToStringInteger(tcnt) + "Register" + ftype;
00087     rticode << "AutoRegisterType<" << ctype << "> " << rtiname << "(\"" << ftype <<"\");";
00088     rticode << std::endl;
00089     // extra data set: element tag
00090     if(tit->second->XElementTag()!="") {
00091       rtiname = std::string("gRti") + ToStringInteger(tcnt) + "XElementTag" + ftype;
00092       rticode << "AutoRegisterXElementTag<" << ctype << "> " << rtiname << "(\"" << ftype << 
00093         "\", \"" << tit->second->XElementTag() << "\");";
00094       rticode << std::endl;
00095     }
00096   }
00097 
00098   // c static objects: auto load types end
00099   rticode << "} // namespace" << std::endl;
00100 
00101   // c function declaration: load types
00102   rtiheader << "namespace faudes {" << std::endl;
00103   rtiheader << "void LoadRegisteredTypes(void);" << std::endl;
00104   rtiheader << "} // namespace" << std::endl;
00105 
00106   // c function definition: load types
00107   rticode << "namespace faudes {" << std::endl;
00108   rticode << "/* Register faudes types */" << std::endl;
00109   rticode << "void LoadRegisteredTypes(void) {" << std::endl;
00110 
00111   // traverse type registry to figure faudes types
00112   for(tit=TypeRegistry::G()->Begin(); tit!=TypeRegistry::G()->End();tit++) {
00113     // get c type 
00114     std::string ctype=tit->second->CType();
00115     // bail out if no c type specified
00116     if(ctype=="") continue;
00117     // remove name space faudes
00118     size_t pos=ctype.find("faudes::");
00119     if(pos!=std::string::npos) 
00120       ctype=ctype.substr(std::string("faudes::").length());
00121     // report
00122     std::cout << "Generating registration code for \"" << tit->second->Name() << "\"" << std::endl;
00123     // produce c code
00124     rticode << "  TypeRegistry::G()->Insert<" << ctype << ">(\"" << tit->second->Name() <<"\");";
00125     rticode << std::endl;
00126   }
00127 
00128   // c function definition: load types end
00129   rticode << "}" << std::endl;
00130   rticode << "} // namespace" << std::endl;
00131 
00132 
00133   // c function declaration: load functions
00134   rtiheader << "namespace faudes {" << std::endl;
00135   rtiheader << "void LoadRegisteredFunctions(void);" << std::endl;
00136   rtiheader << "} // namespace" << std::endl;
00137 
00138   // c function definition: load functions
00139   rticode << "namespace faudes {" << std::endl;
00140   rticode << "/* Register faudes functions */" << std::endl;
00141   rticode << "void LoadRegisteredFunctions(void) {" << std::endl;
00142 
00143   // c class definition: Function derivates 
00144   rtiheader << "namespace faudes {" << std::endl;
00145 
00146   // traverse function registry: define rti functions
00147   int fcnt=0;
00148   FunctionRegistry::Iterator  fit;
00149   for(fit=FunctionRegistry::G()->Begin(); fit!=FunctionRegistry::G()->End();fit++, fcnt++) {
00150     // current function definition
00151     const FunctionDefinition* fdef = fit->second;
00152     // get c type and faudes function name
00153     std::string ctype=fdef->CType();
00154     std::string fname = fdef->Name();  
00155     // bail out if no c type specified
00156     if(ctype=="") continue;
00157     // remove name space faudes
00158     size_t pos=ctype.find("faudes::");
00159     if(pos!=std::string::npos) 
00160       ctype=ctype.substr(std::string("faudes::").length());
00161     // bail out if no signature
00162     if(fdef->VariantsSize()==0) {
00163       std::cout << "Function registration: " << fname << ": no signatures" << std::endl;
00164       continue;
00165     }
00166     // interpret signatures: set up type array
00167     std::vector< std::vector<std::string> > cparams;
00168     std::vector< std::vector<Parameter::ParamAttr> > cattrib;
00169     std::vector< std::vector<bool> > cretval;
00170     cparams.resize(fdef->VariantsSize());
00171     cattrib.resize(fdef->VariantsSize());
00172     cretval.resize(fdef->VariantsSize());
00173     // loop all signatures
00174     for(int i=0; i<fdef->VariantsSize(); i++) {
00175       const Signature& sigi=fdef->Variant(i);
00176       int retcount=0;
00177       for(int j=0; j<sigi.Size(); j++) {
00178         // retrieve faudes type and attrib
00179         std::string ftype=sigi.At(j).Type();
00180   Parameter::ParamAttr fattr=sigi.At(j).Attribute();
00181   bool fcret=sigi.At(j).CReturn();   
00182         // count ret values
00183         if(fcret) retcount++;
00184         // bail out on unknown faudestype
00185         if(!TypeRegistry::G()->Exists(ftype)) break;
00186         // get corresponding ctype
00187         std::string ctype=TypeRegistry::G()->Definition(ftype).CType();
00188         // bail out on unknown ctype
00189         if(ctype=="") break;
00190         // bail out on non-out ret value
00191         if(fcret && !(fattr==Parameter::Out)) break;
00192         // bail out on undef attribute
00193         if(fattr==Parameter::UnDef) break;
00194         // bail out on more than one ret values
00195         if(retcount>1) break;
00196         // remove name space faudes
00197         size_t pos=ctype.find("faudes::");
00198         if(pos!=std::string::npos) 
00199           ctype=ctype.substr(std::string("faudes::").length());
00200         // param ok
00201         cparams.at(i).push_back(ctype);
00202         cattrib.at(i).push_back(fattr);
00203         cretval.at(i).push_back(fcret);
00204       } 
00205       // test for signature error
00206       if((int) cparams.at(i).size()!=sigi.Size()) {
00207         std::cout << "Function registration: " << fname << ": cannot interpret signature " 
00208       << sigi.Name() << std::endl;
00209         cparams.resize(i);
00210         break;
00211       }
00212     }
00213     // report
00214     std::cout << "Generating rti wrapper for \"" << fdef->Name() << "\"" << 
00215       " #" << cparams.size() << " variants" << std::endl;
00216     // produce c code: register all functions function
00217     std::string rtiname = std::string("Rti") + ToStringInteger(fcnt) + ctype;
00218     rticode << "  FunctionRegistry::G()->Insert<" << rtiname << ">(\"" << fname <<"\");" << std::endl;
00219     // produce c code: class declaration intro
00220     rtiheader << "/* Function class for c function " << ctype << "*/" << std::endl;
00221     rtiheader << "class " << rtiname << " : public Function { " << std::endl;
00222     rtiheader << "public:" << std::endl;
00223     rtiheader << rtiname << "(const FunctionDefinition* fdef) : Function(fdef) {};" << std::endl;
00224     rtiheader << "virtual Function* New(void) const { return new " << rtiname << "(pFuncDef); };" << std::endl;
00225     rtiheader << "protected:" << std::endl;
00226     // produce c code: function class: have typed param
00227     for(unsigned int i=0; i<cparams.size(); i++) 
00228       for(unsigned int j=0; j<cparams.at(i).size(); j++) 
00229         rtiheader << cparams.at(i).at(j) << "* " << "mP_" << i << "_" << j << ";" << std::endl;
00230     // produce c code: function class: do type check
00231     rtiheader << "virtual bool DoTypeCheck(int n) {" << std::endl;
00232     rtiheader << "  bool res=false;" << std::endl;
00233     rtiheader << "  switch(mVariantIndex) { "<< std::endl;
00234     for(unsigned int i=0; i<cparams.size(); i++) {
00235       rtiheader << "  case " << i << ": { // variant " << fdef->Variant(i).Name() << std::endl;
00236       rtiheader << "    switch(n) { "<< std::endl;
00237       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00238         rtiheader << "    case " << j << ": ";
00239         rtiheader << "    res=DoTypeCast<" << cparams.at(i).at(j) << ">(" << j << ", mP_" << i <<"_" << j << "); ";
00240         rtiheader << "break; "<< std::endl;
00241       }
00242       rtiheader << "    default: break; " << std::endl;
00243       rtiheader << "    } "<< std::endl;
00244       rtiheader << "    break; "<< std::endl;
00245       rtiheader << "  } "<< std::endl;
00246     }
00247     rtiheader << "  default: break; " << std::endl;
00248     rtiheader << "  } "<< std::endl;
00249     rtiheader << "  return res;" << std::endl;
00250     rtiheader << "};" << std::endl;
00251     // produce c code: function class: do execute
00252     rtiheader << "virtual void DoExecute(void) {" << std::endl;
00253     // produce c code: do execute: switch variant
00254     rtiheader << "  switch(mVariantIndex) { "<< std::endl;
00255     for(unsigned int i=0; i<cparams.size(); i++) {
00256       rtiheader << "  case " << i << ": { // variant " << fdef->Variant(i).Name() << std::endl;
00257       rtiheader << "    ";
00258       // figure return value (if any)
00259       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00260         if(!cretval.at(i).at(j)) continue;
00261         // special case: integer
00262         if(cparams.at(i).at(j) == "Integer") {
00263           rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
00264         } else 
00265         // special case: boolean
00266     if(cparams.at(i).at(j) == "Boolean") {
00267           rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
00268         } else
00269         // special case: integer
00270         if(cparams.at(i).at(j) == "String") {
00271           rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
00272         } else
00273         // std case
00274     rtiheader << "*mP_" << i << "_" << j  << " = ";
00275       }
00276       // function name
00277       rtiheader << ctype <<"(";
00278       // parameters
00279       int parpos=0;
00280       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00281         if(cretval.at(i).at(j)) continue;
00282         if((parpos++)!=0) rtiheader << " ,";
00283         // special case: integer
00284         if(cparams.at(i).at(j) == "Integer") {
00285           rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
00286         } else 
00287         // special case: boolean
00288     if(cparams.at(i).at(j) == "Boolean") {
00289           rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
00290         } else
00291         // special case: integer
00292         if(cparams.at(i).at(j) == "String") {
00293           rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
00294         } else
00295         // std case
00296         rtiheader << "*mP_" << i << "_" << j;
00297       }
00298       rtiheader << "); break; };" << std::endl;
00299     }
00300     // produce c code: switch variant; done
00301     rtiheader << "  default: break; " << std::endl;
00302     rtiheader << "  }; "<< std::endl;
00303     // produce c code: do execute: done
00304     rtiheader << "}; "<< std::endl;
00305     // produce c code: function class: done
00306     rtiheader << "};"  << std::endl;
00307 
00308     // produce swig code: lua function definition(s)    
00309     luaheader << "/* faudes-function \"" << fname << "\" */" << std::endl;
00310     // figure my plugin to insert a conditional
00311     std::string plugin=fdef->PlugIn();
00312     luaheader << "#if " << "SwigModule == \"Swig" << plugin << "\"" << std::endl;
00313     // use ctype function name
00314     if(ctype!=fname)
00315       luaheader << "%rename(" << fname << ") " << ctype << ";" << std::endl;
00316 
00317     // prepare swig code: preprocessed array
00318     std::vector< std::string > lfdefs;
00319     std::vector< std::string > lrtypes;
00320     std::vector< std::string > lhelp;
00321     // prepare swig code: generate per signature
00322     for(unsigned int i=0; i<cparams.size(); i++) {
00323       // create ctype function declaration: return value
00324       std::string lrtype="void";
00325       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00326         if(!cretval.at(i).at(j)) continue;
00327         // special case: integer
00328         if(cparams.at(i).at(j) == "Integer") {
00329           lrtype="long int";
00330         } else 
00331         // special case: boolean
00332   if(cparams.at(i).at(j) == "Boolean") {
00333           lrtype="bool";
00334         } else
00335         // special case: string
00336         if(cparams.at(i).at(j) == "String") {
00337         lrtype="std::string";
00338         } else
00339         // std case ctype as refernce
00340   lrtype + cparams.at(i).at(j);
00341         // no more than one return value
00342         break;
00343       }
00344       lrtypes.push_back(lrtype);
00345       // create ctype function declaration: function body
00346       std::string lfdef = ctype + "(";
00347       // create ctype function declaration: parameters
00348       int parpos=0;
00349       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00350         if(cretval.at(i).at(j)) continue;
00351         if((parpos++)!=0) lfdef += ", ";
00352         // have const for +In+
00353   if(cattrib.at(i).at(j)==Parameter::In)
00354           lfdef +=  "const ";
00355         // special case: integer
00356         if(cparams.at(i).at(j) == "Integer") {
00357           lfdef += "long int&";
00358         } else 
00359         // special case: boolean
00360   if(cparams.at(i).at(j) == "Boolean") {
00361           lfdef += "bool&";
00362         } else
00363         // special case: string
00364         if(cparams.at(i).at(j) == "String") {
00365           lfdef += "std::string&";
00366         } else
00367         // std case ctype as refernce
00368       lfdef += cparams.at(i).at(j) + "&";
00369         // mark elementary outputs
00370         if(cparams.at(i).at(j) == "Boolean" || cparams.at(i).at(j) == "String" 
00371            || cparams.at(i).at(j) == "Integer")
00372   if(cattrib.at(i).at(j)==Parameter::Out)
00373           lfdef += " OUTPUT";
00374       }
00375       // end of function declaration
00376       lfdef += ")"; 
00377       lfdefs.push_back(lfdef);
00378       // add help entry: build nice signature
00379       std::string luasig = " " + fname + "(";
00380       bool leftcomma = false;
00381       bool rightcomma = false;
00382       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00383         // special case: elementary output
00384         if(cparams.at(i).at(j) == "Boolean" || cparams.at(i).at(j) == "String" 
00385            || cparams.at(i).at(j) == "Integer")
00386     if(cattrib.at(i).at(j)==Parameter::Out) {
00387             if(leftcomma) luasig = "," + luasig;
00388       //            if(leftcomma) luasig = ", " + luasig; // need tab in help system?
00389       luasig=cparams.at(i).at(j) + luasig;
00390             leftcomma=true;
00391       continue;
00392     }
00393         // std case
00394         if(rightcomma) luasig += ", ";
00395         const Signature& sigi=fdef->Variant(i);
00396   luasig += sigi.At(j).Str();
00397         rightcomma=true;
00398       }  
00399       luasig+=")";
00400       // add help entry: add with topic
00401       if(fdef->TextDoc()!=""){
00402         std::string topic= fdef->PlugIn();
00403         std::string key1=fdef->KeywordAt(1);
00404         if(topic=="CoreFaudes") {
00405           topic=fdef->KeywordAt(1);
00406           key1=fdef->KeywordAt(2);
00407         }
00408         if(topic.length()>0) topic.at(0)=toupper(topic.at(0));
00409         if(key1.length()>0) key1.at(0)=toupper(key1.at(0));
00410         lhelp.push_back("SwigHelpEntry(\"" + topic + "\", \"" + key1 + "\", \"" +
00411     luasig + "\")");
00412       } else {
00413         lhelp.push_back("");
00414       }
00415     }
00416     // filter pseudo doublets (only differ in lrtype)
00417     for(unsigned int i=1; i<lfdefs.size();i++) {
00418       unsigned int j;
00419       for(j=0; j<i; j++) 
00420   if(lfdefs.at(i)==lfdefs.at(j)) break;
00421       if(j==i) continue; 
00422       // invalidate entry?
00423       if(lrtypes.at(j)=="void") 
00424         {lfdefs[j]=""; continue;}  
00425       if(lrtypes.at(i)=="void") 
00426         {lfdefs[i]=""; continue;}  
00427     } // done: prepare per signature
00428 
00429     // generate swig definitions: write
00430     int lcount=0;
00431     for(unsigned int i=0; i<lfdefs.size(); i++) {
00432       if(lfdefs.at(i)=="") continue;
00433       luaheader << lrtypes.at(i) << " " << lfdefs.at(i) << ";" << std::endl;
00434       lcount++;
00435       if(lhelp.at(i)=="") continue; 
00436       luaheader << lhelp.at(i) << ";" << std::endl;
00437     }
00438     std::cout << "Generating swig interface for function \"" << fdef->Name() << "\"" << 
00439       " #" << lcount << " variants" << std::endl;
00440 
00441     // end all signatures, incl conditional
00442     luaheader << "#endif " << std::endl;
00443     luaheader << std::endl;
00444 
00445 
00446   } // loop all functions
00447 
00448   // c class definition: function class: all such done
00449   rtiheader << "} // namespace" << std::endl;
00450 
00451   // c class definition: register function prototypes: done
00452   rticode << "}" << std::endl;
00453   rticode << "} // namespace" << std::endl;
00454 
00455   return(0);
00456 }

libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3