|
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 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