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 function declaration: load types
00065   rtiheader << "namespace faudes {" << std::endl;
00066   rtiheader << "void LoadAutoregisteredTypes(void);" << std::endl;
00067   rtiheader << "} // namespace" << std::endl;
00068 
00069   // c function definition: load types
00070   rticode << "namespace faudes {" << std::endl;
00071   rticode << "/* Register faudes types */" << std::endl;
00072   rticode << "void LoadAutoregisteredTypes(void) {" << std::endl;
00073 
00074   // traverse type registry to figure faudes types
00075   TypeRegistry::Iterator  tit;
00076   for(tit=TypeRegistry::G()->Begin(); tit!=TypeRegistry::G()->End();tit++) {
00077     // get c type 
00078     std::string ctype=tit->second->CType();
00079     // bail out if no c type specified
00080     if(ctype=="") continue;
00081     // remove name space faudes
00082     size_t pos=ctype.find("faudes::");
00083     if(pos!=std::string::npos) 
00084       ctype=ctype.substr(std::string("faudes::").length());
00085     // report
00086     std::cout << "Generating auto-registration code for \"" << tit->second->Name() << "\"" << std::endl;
00087     // produce c code
00088     rticode << "  TypeRegistry::G()->Insert<" << ctype << ">(\"" << tit->second->Name() <<"\");";
00089     rticode << std::endl;
00090   }
00091 
00092   // c function definition: load types end
00093   rticode << "}" << std::endl;
00094   rticode << "} // namespace" << std::endl;
00095 
00096 
00097   // c function declaration: load functions
00098   rtiheader << "namespace faudes {" << std::endl;
00099   rtiheader << "void LoadAutoregisteredFunctions(void);" << std::endl;
00100   rtiheader << "} // namespace" << std::endl;
00101 
00102   // c function definition: load functions
00103   rticode << "namespace faudes {" << std::endl;
00104   rticode << "/* Register faudes functions */" << std::endl;
00105   rticode << "void LoadAutoregisteredFunctions(void) {" << std::endl;
00106 
00107   // c class definition: Function derivates 
00108   rtiheader << "namespace faudes {" << std::endl;
00109 
00110   // traverse function registry: define rti functions
00111   int fcnt=0;
00112   FunctionRegistry::Iterator  fit;
00113   for(fit=FunctionRegistry::G()->Begin(); fit!=FunctionRegistry::G()->End();fit++, fcnt++) {
00114     // current function definition
00115     const FunctionDefinition* fdef = fit->second;
00116     // get c type and faudes function name
00117     std::string ctype=fdef->CType();
00118     std::string fname = fdef->Name();  
00119     // bail out if no c type specified
00120     if(ctype=="") continue;
00121     // remove name space faudes
00122     size_t pos=ctype.find("faudes::");
00123     if(pos!=std::string::npos) 
00124       ctype=ctype.substr(std::string("faudes::").length());
00125     // bail out if no signature
00126     if(fdef->VariantsSize()==0) {
00127       std::cout << "Function registration: " << fname << ": no signatures" << std::endl;
00128       continue;
00129     }
00130     // interpret signatures: set up type array
00131     std::vector< std::vector<std::string> > cparams;
00132     std::vector< std::vector<Parameter::ParamAttr> > cattrib;
00133     std::vector< std::vector<bool> > cretval;
00134     cparams.resize(fdef->VariantsSize());
00135     cattrib.resize(fdef->VariantsSize());
00136     cretval.resize(fdef->VariantsSize());
00137     // loop all signatures
00138     for(int i=0; i<fdef->VariantsSize(); i++) {
00139       const Signature& sigi=fdef->Variant(i);
00140       int retcount=0;
00141       for(int j=0; j<sigi.Size(); j++) {
00142         // retrieve faudes type and attrib
00143         std::string ftype=sigi.At(j).Type();
00144   Parameter::ParamAttr fattr=sigi.At(j).Attribute();
00145   bool fcret=sigi.At(j).CReturn();   
00146         // count ret values
00147         if(fcret) retcount++;
00148         // bail out on unknown faudestype
00149         if(!TypeRegistry::G()->Exists(ftype)) break;
00150         // get corresponding ctype
00151         std::string ctype=TypeRegistry::G()->Definition(ftype).CType();
00152         // bail out on unknown ctype
00153         if(ctype=="") break;
00154         // bail out on non-out ret value
00155         if(fcret && !(fattr==Parameter::Out)) break;
00156         // bail out on undef attribute
00157         if(fattr==Parameter::UnDef) break;
00158         // bail out on more than one ret values
00159         if(retcount>1) break;
00160         // remove name space faudes
00161         size_t pos=ctype.find("faudes::");
00162         if(pos!=std::string::npos) 
00163           ctype=ctype.substr(std::string("faudes::").length());
00164         // param ok
00165         cparams.at(i).push_back(ctype);
00166         cattrib.at(i).push_back(fattr);
00167         cretval.at(i).push_back(fcret);
00168       } 
00169       // test for signature error
00170       if((int) cparams.at(i).size()!=sigi.Size()) {
00171         std::cout << "Function registration: " << fname << ": cannot interpret signature " 
00172       << sigi.Name() << std::endl;
00173         cparams.resize(i);
00174         break;
00175       }
00176     }
00177     // report
00178     std::cout << "Generating rti wrapper for \"" << fdef->Name() << "\"" << 
00179       " #" << cparams.size() << " variants" << std::endl;
00180     // produce c code: register all functions function
00181     std::string rtiname = std::string("Rti") + ToStringInteger(fcnt) + ctype;
00182     rticode << "  FunctionRegistry::G()->Insert<" << rtiname << ">(\"" << fname <<"\");" << std::endl;
00183     // produce c code: class declaration intro
00184     rtiheader << "/* Function class for c function " << ctype << "*/" << std::endl;
00185     rtiheader << "class " << rtiname << " : public Function { " << std::endl;
00186     rtiheader << "public:" << std::endl;
00187     rtiheader << rtiname << "(const FunctionDefinition* fdef) : Function(fdef) {};" << std::endl;
00188     rtiheader << "virtual Function* New(void) const { return new " << rtiname << "(pFuncDef); };" << std::endl;
00189     rtiheader << "protected:" << std::endl;
00190     // produce c code: function class: have typed param
00191     for(unsigned int i=0; i<cparams.size(); i++) 
00192       for(unsigned int j=0; j<cparams.at(i).size(); j++) 
00193         rtiheader << cparams.at(i).at(j) << "* " << "mP_" << i << "_" << j << ";" << std::endl;
00194     // produce c code: function class: do type check
00195     rtiheader << "virtual bool DoTypeCheck(int n) {" << std::endl;
00196     rtiheader << "  bool res=false;" << std::endl;
00197     rtiheader << "  switch(mVariantIndex) { "<< std::endl;
00198     for(unsigned int i=0; i<cparams.size(); i++) {
00199       rtiheader << "  case " << i << ": { // variant " << fdef->Variant(i).Name() << std::endl;
00200       rtiheader << "    switch(n) { "<< std::endl;
00201       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00202         rtiheader << "    case " << j << ": ";
00203         rtiheader << "    res=DoTypeCast<" << cparams.at(i).at(j) << ">(" << j << ", mP_" << i <<"_" << j << "); ";
00204         rtiheader << "break; "<< std::endl;
00205       }
00206       rtiheader << "    default: break; " << std::endl;
00207       rtiheader << "    } "<< std::endl;
00208       rtiheader << "    break; "<< std::endl;
00209       rtiheader << "  } "<< std::endl;
00210     }
00211     rtiheader << "  default: break; " << std::endl;
00212     rtiheader << "  } "<< std::endl;
00213     rtiheader << "  return res;" << std::endl;
00214     rtiheader << "};" << std::endl;
00215     // produce c code: function class: do execute
00216     rtiheader << "virtual void DoExecute(void) {" << std::endl;
00217     // produce c code: do execute: switch variant
00218     rtiheader << "  switch(mVariantIndex) { "<< std::endl;
00219     for(unsigned int i=0; i<cparams.size(); i++) {
00220       rtiheader << "  case " << i << ": { // variant " << fdef->Variant(i).Name() << std::endl;
00221       rtiheader << "    ";
00222       // figure return value (if any)
00223       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00224         if(!cretval.at(i).at(j)) continue;
00225         // special case: integer
00226         if(cparams.at(i).at(j) == "Integer") {
00227           rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
00228         } else 
00229         // special case: boolean
00230     if(cparams.at(i).at(j) == "Boolean") {
00231           rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
00232         } else
00233         // special case: integer
00234         if(cparams.at(i).at(j) == "String") {
00235           rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
00236         } else
00237         // std case
00238     rtiheader << "*mP_" << i << "_" << j  << " = ";
00239       }
00240       // function name
00241       rtiheader << ctype <<"(";
00242       // parameters
00243       int parpos=0;
00244       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00245         if(cretval.at(i).at(j)) continue;
00246         if((parpos++)!=0) rtiheader << " ,";
00247         // special case: integer
00248         if(cparams.at(i).at(j) == "Integer") {
00249           rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
00250         } else 
00251         // special case: boolean
00252     if(cparams.at(i).at(j) == "Boolean") {
00253           rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
00254         } else
00255         // special case: integer
00256         if(cparams.at(i).at(j) == "String") {
00257           rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
00258         } else
00259         // std case
00260         rtiheader << "*mP_" << i << "_" << j;
00261       }
00262       rtiheader << "); break; };" << std::endl;
00263     }
00264     // produce c code: switch variant; done
00265     rtiheader << "  default: break; " << std::endl;
00266     rtiheader << "  }; "<< std::endl;
00267     // produce c code: do execute: done
00268     rtiheader << "}; "<< std::endl;
00269     // produce c code: function class: done
00270     rtiheader << "};"  << std::endl;
00271 
00272     // produce swig code: lua function definition(s)    
00273     luaheader << "/* faudes-function \"" << fname << "\" */" << std::endl;
00274     // figure my plugin to insert a conditional
00275     std::string plugin=fdef->PlugIn();
00276     luaheader << "#if " << "SwigModule == \"Swig" << plugin << "\"" << std::endl;
00277     // use ctype function name
00278     if(ctype!=fname)
00279       luaheader << "%rename(" << fname << ") " << ctype << ";" << std::endl;
00280 
00281     // prepare swig code: preprocessed array
00282     std::vector< std::string > lfdefs;
00283     std::vector< std::string > lrtypes;
00284     std::vector< std::string > lhelp;
00285     // prepare swig code: generate per signature
00286     for(unsigned int i=0; i<cparams.size(); i++) {
00287       // create ctype function declaration: return value
00288       std::string lrtype="void";
00289       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00290         if(!cretval.at(i).at(j)) continue;
00291         // special case: integer
00292         if(cparams.at(i).at(j) == "Integer") {
00293           lrtype="long int";
00294         } else 
00295         // special case: boolean
00296   if(cparams.at(i).at(j) == "Boolean") {
00297           lrtype="bool";
00298         } else
00299         // special case: string
00300         if(cparams.at(i).at(j) == "String") {
00301         lrtype="std::string";
00302         } else
00303         // std case ctype as refernce
00304   lrtype + cparams.at(i).at(j);
00305         // no more than one return value
00306         break;
00307       }
00308       lrtypes.push_back(lrtype);
00309       // create ctype function declaration: function body
00310       std::string lfdef = ctype + "(";
00311       // create ctype function declaration: parameters
00312       int parpos=0;
00313       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00314         if(cretval.at(i).at(j)) continue;
00315         if((parpos++)!=0) lfdef += ", ";
00316         // have const for +In+
00317   if(cattrib.at(i).at(j)==Parameter::In)
00318           lfdef +=  "const ";
00319         // special case: integer
00320         if(cparams.at(i).at(j) == "Integer") {
00321           lfdef += "long int&";
00322         } else 
00323         // special case: boolean
00324   if(cparams.at(i).at(j) == "Boolean") {
00325           lfdef += "bool&";
00326         } else
00327         // special case: string
00328         if(cparams.at(i).at(j) == "String") {
00329           lfdef += "std::string&";
00330         } else
00331         // std case ctype as refernce
00332       lfdef += cparams.at(i).at(j) + "&";
00333         // mark elementary outputs
00334         if(cparams.at(i).at(j) == "Boolean" || cparams.at(i).at(j) == "String" 
00335            || cparams.at(i).at(j) == "Integer")
00336   if(cattrib.at(i).at(j)==Parameter::Out)
00337           lfdef += " OUTPUT";
00338       }
00339       // end of function declaration
00340       lfdef += ")"; 
00341       lfdefs.push_back(lfdef);
00342       // add help entry: build nice signature
00343       std::string luasig = " " + fname + "(";
00344       bool leftcomma = false;
00345       bool rightcomma = false;
00346       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00347         // special case: elementary output
00348         if(cparams.at(i).at(j) == "Boolean" || cparams.at(i).at(j) == "String" 
00349            || cparams.at(i).at(j) == "Integer")
00350     if(cattrib.at(i).at(j)==Parameter::Out) {
00351             if(leftcomma) luasig = "," + luasig;
00352       //            if(leftcomma) luasig = ", " + luasig; // need tab in help system?
00353       luasig=cparams.at(i).at(j) + luasig;
00354             leftcomma=true;
00355       continue;
00356     }
00357         // std case
00358         if(rightcomma) luasig += ", ";
00359         const Signature& sigi=fdef->Variant(i);
00360   luasig += sigi.At(j).Str();
00361         rightcomma=true;
00362       }  
00363       luasig+=")";
00364       // add help entry: add with topic
00365       if(fdef->TextDoc()!=""){
00366         std::string topic= fdef->PlugIn();
00367         std::string key1=fdef->KeywordAt(1);
00368         if(topic=="CoreFaudes") {
00369           topic=fdef->KeywordAt(1);
00370           key1=fdef->KeywordAt(2);
00371         }
00372         if(topic.length()>0) topic.at(0)=toupper(topic.at(0));
00373         if(key1.length()>0) key1.at(0)=toupper(key1.at(0));
00374         lhelp.push_back("SwigHelpEntry(\"" + topic + "\", \"" + key1 + "\", \"" +
00375     luasig + "\")");
00376       } else {
00377         lhelp.push_back("");
00378       }
00379     }
00380     // filter pseudo doublets (only differ in lrtype)
00381     for(unsigned int i=1; i<lfdefs.size();i++) {
00382       unsigned int j;
00383       for(j=0; j<i; j++) 
00384   if(lfdefs.at(i)==lfdefs.at(j)) break;
00385       if(j==i) continue; 
00386       // invalidate entry?
00387       if(lrtypes.at(j)=="void") 
00388         {lfdefs[j]=""; continue;}  
00389       if(lrtypes.at(i)=="void") 
00390         {lfdefs[i]=""; continue;}  
00391     } // done: prepare per signature
00392 
00393     // generate swig definitions: write
00394     int lcount=0;
00395     for(unsigned int i=0; i<lfdefs.size(); i++) {
00396       if(lfdefs.at(i)=="") continue;
00397       luaheader << lrtypes.at(i) << " " << lfdefs.at(i) << ";" << std::endl;
00398       lcount++;
00399       if(lhelp.at(i)=="") continue; 
00400       luaheader << lhelp.at(i) << ";" << std::endl;
00401     }
00402     std::cout << "Generating swig interface for function \"" << fdef->Name() << "\"" << 
00403       " #" << lcount << " variants" << std::endl;
00404 
00405     // end all signatures, incl conditional
00406     luaheader << "#endif " << std::endl;
00407     luaheader << std::endl;
00408 
00409 
00410   } // loop all functions
00411 
00412   // c class definition: function class: all such done
00413   rtiheader << "} // namespace" << std::endl;
00414 
00415   // c class definition: register function prototypes: done
00416   rticode << "}" << std::endl;
00417   rticode << "} // namespace" << std::endl;
00418 
00419   return(0);
00420 }

libFAUDES 2.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3