|
libFAUDES
Sections
Index
|
rti2code.cppGo 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