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 code for: faudes type \"" << 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     cparams.resize(fdef->VariantsSize());
00134     cattrib.resize(fdef->VariantsSize());
00135     // loop all signatures
00136     for(int i=0; i<fdef->VariantsSize(); i++) {
00137       const Signature& sigi=fdef->Variant(i);
00138       for(int j=0; j<sigi.Size(); j++) {
00139         // retrieve faudes type and attrib
00140         std::string ftype=sigi.At(j).mTDName;
00141   Parameter::ParamAttr fattr=sigi.At(j).mAttr;
00142         // bail out on unknown faudestype
00143         if(!TypeRegistry::G()->Exists(ftype)) break;
00144         // get corresponding ctype
00145         std::string ctype=TypeRegistry::G()->Definition(ftype).CType();
00146         // bail out on unknown ctype
00147         if(ctype=="") break;
00148         // remove name space faudes
00149         size_t pos=ctype.find("faudes::");
00150         if(pos!=std::string::npos) 
00151           ctype=ctype.substr(std::string("faudes::").length());
00152         // param ok
00153         cparams.at(i).push_back(ctype);
00154         cattrib.at(i).push_back(fattr);
00155       } 
00156       // test for signature error
00157       if((int) cparams.at(i).size()!=sigi.Size()) {
00158         std::cout << "Function registration: " << fname << ": cannot interpret signature" << std::endl;
00159         cparams.resize(i);
00160         break;
00161       }
00162     }
00163     // report
00164     std::cout << "Generating code for: faudes function \"" << fdef->Name() << "\"" << std::endl;
00165     // produce c code: register all functions function
00166     std::string rtiname = std::string("Rti") + ToStringInteger(fcnt) + ctype;
00167     rticode << "  FunctionRegistry::G()->Insert<" << rtiname << ">(\"" << fname <<"\");" << std::endl;
00168     // produce c code: class declaration intro
00169     rtiheader << "/* Function class for c function " << ctype << "*/" << std::endl;
00170     rtiheader << "class " << rtiname << " : public Function { " << std::endl;
00171     rtiheader << "public:" << std::endl;
00172     rtiheader << rtiname << "(const FunctionDefinition* fdef) : Function(fdef) {};" << std::endl;
00173     rtiheader << "virtual Function* New(void) const { return new " << rtiname << "(pFuncDef); };" << std::endl;
00174     rtiheader << "protected:" << std::endl;
00175     // produce c code: function class: have typed param
00176     for(unsigned int i=0; i<cparams.size(); i++) 
00177       for(unsigned int j=0; j<cparams.at(i).size(); j++) 
00178         rtiheader << cparams.at(i).at(j) << "* " << "mP_" << i << "_" << j << ";" << std::endl;
00179     // produce c code: function class: do type check
00180     rtiheader << "virtual bool DoTypeCheck(int n) {" << std::endl;
00181     rtiheader << "  bool res=false;" << std::endl;
00182     rtiheader << "  switch(mVariantIndex) { "<< std::endl;
00183     for(unsigned int i=0; i<cparams.size(); i++) {
00184       rtiheader << "  case " << i << ": { // variant " << fdef->Variant(i).Name() << std::endl;
00185       rtiheader << "    switch(n) { "<< std::endl;
00186       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00187         rtiheader << "    case " << j << ": ";
00188         rtiheader << "    res=DoTypeCast<" << cparams.at(i).at(j) << ">(" << j << ", mP_" << i <<"_" << j << "); ";
00189         rtiheader << "break; "<< std::endl;
00190       }
00191       rtiheader << "    default: break; " << std::endl;
00192       rtiheader << "    } "<< std::endl;
00193       rtiheader << "    break; "<< std::endl;
00194       rtiheader << "  } "<< std::endl;
00195     }
00196     rtiheader << "  default: break; " << std::endl;
00197     rtiheader << "  } "<< std::endl;
00198     rtiheader << "  return res;" << std::endl;
00199     rtiheader << "};" << std::endl;
00200     // produce c code: function class: do execute
00201     rtiheader << "virtual void DoExecute(void) {" << std::endl;
00202     // produce c code: do execute: switch variant
00203     rtiheader << "  switch(mVariantIndex) { "<< std::endl;
00204     for(unsigned int i=0; i<cparams.size(); i++) {
00205       rtiheader << "  case " << i << ": { // variant " << fdef->Variant(i).Name() << std::endl;
00206       rtiheader << "    " << ctype <<"(";
00207       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00208         if(j!=0) rtiheader << " ,";
00209         // special case: integer
00210         if(cparams.at(i).at(j) == "Integer") {
00211           rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
00212         } else 
00213         // special case: boolean
00214     if(cparams.at(i).at(j) == "Boolean") {
00215           rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
00216         } else
00217         // special case: integer
00218         if(cparams.at(i).at(j) == "String") {
00219           rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
00220         } else
00221         // std case
00222         rtiheader << "*mP_" << i << "_" << j;
00223       }
00224       rtiheader << "); break; };" << std::endl;
00225     }
00226     // produce c code: switch variant; done
00227     rtiheader << "  default: break; " << std::endl;
00228     rtiheader << "  }; "<< std::endl;
00229     // produce c code: do execute: done
00230     rtiheader << "}; "<< std::endl;
00231     // produce c code: function class: done
00232     rtiheader << "};"  << std::endl;
00233 
00234     // produce c code: lua function definition(s)    
00235     luaheader << "/* faudes-function \"" << fname << "\" */" << std::endl;
00236     // figure my plugin to insert a conditional
00237     std::string plugin=fdef->PlugIn();
00238     luaheader << "#if " << "SwigModule == \"Swig" << plugin << "\"" << std::endl;
00239     // use ctype function name
00240     if(ctype!=fname)
00241       luaheader << "%rename(" << fname << ") " << ctype << ";" << std::endl;
00242     // generate per signature
00243     for(unsigned int i=0; i<cparams.size(); i++) {
00244       // create ctype function declaration
00245       luaheader << "void  " << ctype <<"(";
00246       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00247         if(j!=0) luaheader << ", ";
00248         // have const for +In+
00249   if(cattrib.at(i).at(j)==Parameter::In)
00250           luaheader << "const ";
00251         // special case: integer
00252         if(cparams.at(i).at(j) == "Integer") {
00253           luaheader << "long int&";
00254         } else 
00255         // special case: boolean
00256   if(cparams.at(i).at(j) == "Boolean") {
00257           luaheader << "bool&";
00258         } else
00259         // special case: string
00260         if(cparams.at(i).at(j) == "String") {
00261           luaheader << "std::string&";
00262         } else
00263         // std case ctype as refernce
00264   luaheader << cparams.at(i).at(j) << "&";
00265         // mark elementary outputs
00266         if(cparams.at(i).at(j) == "Boolean" || cparams.at(i).at(j) == "String" 
00267            || cparams.at(i).at(j) == "Integer")
00268   if(cattrib.at(i).at(j)==Parameter::Out)
00269           luaheader << " OUTPUT";
00270       }
00271       // end of function declaration
00272       luaheader << ");" << std::endl;
00273  
00274       // add help entry: build nice signature
00275       std::string luasig = " " + fname + "(";
00276       bool leftcomma = false;
00277       bool rightcomma = false;
00278       for(unsigned int j=0; j<cparams.at(i).size(); j++) {
00279         // special case: elementary output
00280         if(cparams.at(i).at(j) == "Boolean" || cparams.at(i).at(j) == "String" 
00281            || cparams.at(i).at(j) == "Integer")
00282     if(cattrib.at(i).at(j)==Parameter::Out) {
00283             if(leftcomma) luasig = "," + luasig;
00284       //            if(leftcomma) luasig = ", " + luasig; // need tab in help system?
00285       luasig=cparams.at(i).at(j) + luasig;
00286             leftcomma=true;
00287       continue;
00288     }
00289         // std case
00290         if(rightcomma) luasig += ", ";
00291         const Signature& sigi=fdef->Variant(i);
00292   luasig += sigi.At(j).Str();
00293         rightcomma=true;
00294       }  
00295       luasig+=")";
00296       // add help entry: add with topic
00297       if(fdef->TextDoc()!=""){
00298         std::string topic= fdef->PlugIn();
00299         std::string key1=fdef->KeywordAt(1);
00300         if(topic=="CoreFaudes") {
00301           topic=fdef->KeywordAt(1);
00302           key1=fdef->KeywordAt(2);
00303         }
00304         if(topic.length()>0) topic.at(0)=toupper(topic.at(0));
00305         if(key1.length()>0) key1.at(0)=toupper(key1.at(0));
00306         luaheader << "SwigHelpEntry(\"" << topic <<"\", \"" << key1 << "\", \"" << luasig << "\");" << std::endl;
00307       }
00308     
00309     } // done: per signature;
00310 
00311     // and all signatures, incl conditional
00312     luaheader << "#endif " << std::endl;
00313     luaheader << std::endl;
00314 
00315 
00316   } // loop all functions
00317 
00318   // c class definition: function class: all such done
00319   rtiheader << "} // namespace" << std::endl;
00320 
00321   // c class definition: register function prototypes: done
00322   rticode << "}" << std::endl;
00323   rticode << "} // namespace" << std::endl;
00324 
00325   return(0);
00326 }

libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6