rti2code.cpp
Go to the documentation of this file.
1/** rti2code.cpp Utility to generate registry initialisation code from rti files */
2
3/* FAU Discrete Event Systems Library (libfaudes)
4
5Copyright (C) 2009 Ruediger Berndt
6Copyright (C) 2010, 2023, 2025, 2026 Thomas Moor
7
8This library is free software; you can redistribute it and/or
9modify it under the terms of the GNU Lesser General Public
10License as published by the Free Software Foundation; either
11version 2.1 of the License, or (at your option) any later version.
12
13This library is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16Lesser General Public License for more details.
17
18You should have received a copy of the GNU Lesser General Public
19License along with this library; if not, write to the Free Software
20Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
21
22
23#include <string>
24#include <iostream>
25#include <fstream>
26#include "corefaudes.h"
27
28
29using namespace faudes;
30
31// ******************************************************************
32// error exit
33// ******************************************************************
34
35void usage(const std::string& rMessage="") {
36
37 // UI hints
38 if(rMessage!="") {
39 std::cerr << rMessage << std::endl;
40 std::cout << "" << std::endl;
41 }
42 std::cerr << "rti2code: " << VersionString() << std::endl;
43 std::cerr << std::endl;
44 std::cerr << "utility to generates c code from an rti-file to " << std::endl;
45 std::cerr << "1) extract c declarations for bindings interface code," << std::endl;
46 std::cerr << "2) register faudes-types and -functions with the run-time interface," << std::endl;
47 std::cerr << "3) generate convenience wrappers for scripting languages" << std::endl;
48 std::cerr << std::endl;
49 std::cerr << "usage:" << std::endl;
50 std::cerr << " rti2code [-swig|-loader|-wrapper] <rti input file> <output basename>" << std::endl;
51 std::cerr << " rti2code -merge <rti input files> <output rti-file>" << std::endl;
52 std::cerr << std::endl;
53 std::cerr << "[note: the -loader flag will produce .h/.cpp files to instantiate prototypes" << std::endl;
54 std::cerr << "[note: the -wrapper flag will produce .h/.cpp files to declare/define wrappers" << std::endl;
55 std::cerr << "[note: the -swig flag will produce a .i file for swig include" << std::endl;
56 std::cerr << "[note: the -flat flag circumvents an issue with SWIG pre 4.1.0]" << std::endl;
57 exit(1);
58}
59
60
61// ******************************************************************
62// main programm
63// ******************************************************************
64
65int main(int argc, char *argv[]) {
66
67 // config
68 bool loader=false;
69 bool swig=false;
70 bool flat=false;
71 bool wrapper=false;
72 bool merge=false;
73
74 // primitive command line parser
75 int pos=1;
76 for(; pos<argc; pos++) {
77 std::string option(argv[pos]);
78 // option: help
79 if((option=="-?") || (option=="--help")) {
80 usage();
81 continue;
82 }
83 // option: loader
84 if(option=="-loader") {
85 loader=true;
86 continue;
87 }
88 // option: swig
89 if(option=="-swig") {
90 swig=true;
91 continue;
92 }
93 // option: wrapper
94 if(option=="-wrapper") {
95 wrapper=true;
96 continue;
97 }
98 // option: flat
99 if(option=="-flat") {
100 flat=true;
101 continue;
102 }
103 // option: merge
104 if(option=="-merge") {
105 merge=true;
106 continue;
107 }
108 // option: unknown
109 if(option.c_str()[0]=='-') {
110 usage("unknown option "+ option);
111 continue;
112 }
113 // break for args
114 break;
115 }
116
117 // mode test
118 if(merge && (loader || swig || wrapper)) {
119 usage("mismatching options: either merge or code generation");
120 }
121 if(!merge && !(loader || swig || wrapper)) {
122 usage("mismatching options: either merge or code generation");
123 }
124 if(flat && !swig) {
125 usage("mismatching options: flat is only applicable to swig");
126 }
127 if(merge && (argc-pos <2)) {
128 usage("mismatching agruments: to few files to merge");
129 }
130 if(!merge && (argc-pos !=2)) {
131 usage("mismatching agruments: need one source and one destination for code generation");
132 }
133
134 // Merge mode -- get this done first
135 if(merge) {
136 // Load from files
137 for(; pos< argc-1; pos++) {
138 TypeRegistry::G()->MergeDocumentation(std::string(argv[pos]));
139 FunctionRegistry::G()->MergeDocumentation(std::string(argv[pos]));
140 }
141 // Dump
142 if(std::string(argv[argc-1]) != "-") {
143 SaveRegistry(std::string(argv[argc-1]));
144 } else {
145 SaveRegistry();
146 }
147 return 0;
148 }
149
150 // code-gen modes loader/swig
151 LoadRegistry(argv[pos++]);
152
153 // Code output streams
154 std::ofstream rtiheader;
155 std::ofstream rticode;
156 std::ofstream swigheader;
157 std::ofstream wrpheader;
158 std::ofstream wrpcode;
159 if(loader) {
160 rtiheader.open((std::string(argv[pos])+".h").c_str(), std::ios::out);
161 rticode.open((std::string(argv[pos])+".cpp").c_str(), std::ios::out);
162 }
163 if(swig){
164 swigheader.open((std::string(argv[pos])+".i").c_str(), std::ios::out);
165 }
166 if(wrapper) {
167 wrpheader.open((std::string(argv[pos])+".h").c_str(), std::ios::out);
168 wrpcode.open((std::string(argv[pos])+".cpp").c_str(), std::ios::out);
169 }
170
171 // Introduce myself
172 if(loader) {
173 rtiheader << "/* rti2code: autogenerated libFAUDES rti registration: ";
174 rtiheader << VersionString() << " " << PluginsString() << " */" << std::endl << std::endl;
175 rticode << "/* rti2code: autogenerated libFAUDES rti registration: ";
176 rticode << VersionString() << " " << PluginsString() << " */" << std::endl << std::endl;
177 }
178 if(swig) {
179 swigheader << "/* rti2code: autogenerated libFAUDES swig bindings declarations: ";
180 swigheader << VersionString() << " " << PluginsString() << " */" << std::endl << std::endl;
181 }
182 if(wrapper) {
183 wrpheader << "/* rti2code: autogenerated convenioence wrapper: ";
184 wrpheader << VersionString() << " " << PluginsString() << " */" << std::endl << std::endl;
185 wrpcode << "/* rti2code: autogenerated convenioence wrapper: ";
186 wrpcode << VersionString() << " " << PluginsString() << " */" << std::endl << std::endl;
187 }
188
189 // Generate C++ static factory objects (intro)
190 if(loader) {
191 rticode << "namespace faudes {" << std::endl;
192 rticode << "/* Register faudes types */" << std::endl;
193 }
194
195 // Generate C++ static factory objects (iterate types)
196 if(loader) {
198 int tcnt;
199 for(tit=TypeRegistry::G()->Begin(), tcnt=1; tit!=TypeRegistry::G()->End();tit++,tcnt++) {
200 // Get c/f type
201 std::string ctype=tit->second->CType();
202 std::string ftype=tit->second->Name();
203 // Bail out if no C type specified
204 if(ctype=="") continue;
205 // Remove name space faudes
206 size_t pos=ctype.find("faudes::");
207 if(pos!=std::string::npos)
208 ctype=ctype.substr(std::string("faudes::").length());
209 // Bail out if programmatically registered
210 // if(tit->second->AutoRegistered()) continue;
211 // ^^^^ Note: this is the default as of libFAUDES 2.34a; but autoregistration is not
212 // functional with MS VC optimisation; see cfl_cgenerator.h/cpp; a pragmatic fix to
213 // tyhe issue is to "autoregister again". Unhappy :-(
214 // report
215 std::cout << "rti2code: generating auto-registration code for \"" << ftype << "\"" << std::endl;
216 // Produce c code
217 std::string rtiname = std::string("gRti") + ToStringInteger(tcnt) + "Register" + ftype;
218 rticode << "AutoRegisterType<" << ctype << "> " << rtiname << "(\"" << ftype <<"\");";
219 rticode << std::endl;
220 // Extra data set: element tag
221 if(tit->second->ElementTag()!="") {
222 rtiname = std::string("gRti") + ToStringInteger(tcnt) + "ElementTag" + ftype;
223 rticode << "AutoRegisterElementTag<" << ctype << "> " << rtiname << "(\"" << ftype <<
224 "\", \"" << tit->second->ElementTag() << "\");";
225 rticode << std::endl;
226 }
227 // Extra data set: element tag
228 if(tit->second->ElementType()!="") {
229 rtiname = std::string("gRti") + ToStringInteger(tcnt) + "ElementType" + ftype;
230 rticode << "AutoRegisterElementType<" << ctype << "> " << rtiname << "(\"" << ftype <<
231 "\", \"" << tit->second->ElementType() << "\");";
232 rticode << std::endl;
233 }
234 }
235 }
236
237 // Generate C++ static factory objects (end)
238 if(loader) {
239 rticode << "} // namespace" << std::endl;
240 }
241
242 // C++ function declarations: load types
243 if(loader) {
244 rtiheader << "namespace faudes {" << std::endl;
245 rtiheader << "void LoadRegisteredTypes(void);" << std::endl;
246 rtiheader << "} // namespace" << std::endl;
247 }
248
249 // C++ function definition: load types
250 if(loader) {
251 rticode << "namespace faudes {" << std::endl;
252 rticode << "/* Register faudes types */" << std::endl;
253 rticode << "void LoadRegisteredTypes(void) {" << std::endl;
254 }
255
256 // Traverse type registry to figure faudes types
257 if(loader) {
259 for(tit=TypeRegistry::G()->Begin(); tit!=TypeRegistry::G()->End();tit++) {
260 // Get C type
261 std::string ctype=tit->second->CType();
262 // Bail out if no c type specified
263 if(ctype=="") continue;
264 // Remove name space faudes
265 size_t pos=ctype.find("faudes::");
266 if(pos!=std::string::npos)
267 ctype=ctype.substr(std::string("faudes::").length());
268 // Bail out if programmatically registered (default as of libFAUDES 2.34a
269 if(tit->second->AutoRegistered()) continue;
270 // Report
271 std::cout << "rti2code: generating registration code for \"" << tit->second->Name() << "\"" << std::endl;
272 // Produce c code
273 rticode << " TypeRegistry::G()->Insert<" << ctype << ">(\"" << tit->second->Name() <<"\");";
274 rticode << std::endl;
275 }
276 }
277
278 // C++ function definition: load types end
279 if(loader) {
280 rticode << "}" << std::endl;
281 rticode << "} // namespace" << std::endl;
282 }
283
284
285 // C++ function declaration: load functions
286 if(loader) {
287 rtiheader << "namespace faudes {" << std::endl;
288 rtiheader << "void LoadRegisteredFunctions(void);" << std::endl;
289 rtiheader << "} // namespace" << std::endl;
290 }
291
292 // C++ function definition: load functions
293 if(loader) {
294 rticode << "namespace faudes {" << std::endl;
295 rticode << "/* Register faudes functions */" << std::endl;
296 rticode << "void LoadRegisteredFunctions(void) {" << std::endl;
297 }
298
299 // C++ class definition: Function derivates
300 if(loader) {
301 rtiheader << "namespace faudes {" << std::endl;
302 }
303
304 // C++ wrapper: intro
305 if(wrapper) {
306 wrpcode << "namespace faudes {" << std::endl;
307 wrpheader << "namespace faudes {" << std::endl;
308 }
309
310 // Traverse function registry: define rti function objects
311 int fcnt=0;
313 for(fit=FunctionRegistry::G()->Begin(); fit!=FunctionRegistry::G()->End();fit++, fcnt++) {
314 // Current function definition
315 const FunctionDefinition* fdef = fit->second;
316 // Get C type and faudes function name
317 std::string ctype=fdef->CType();
318 std::string fname = fdef->Name();
319 // Bail out if no c type specified
320 if(ctype=="") continue;
321 // Remove name space faudes
322 size_t pos=ctype.find("faudes::");
323 if(pos!=std::string::npos)
324 ctype=ctype.substr(std::string("faudes::").length());
325 // Bail out if no signature
326 if(fdef->VariantsSize()==0) {
327 std::cout << "rti2cocde: function registration: " << fname << ": no signatures" << std::endl;
328 continue;
329 }
330
331
332 // Interpret signatures: set up types array
333 std::vector< std::vector<std::string> > fparams;
334 std::vector< std::vector<std::string> > ctypes;
335 std::vector< std::vector<Parameter::ParamAttr> > fattrib;
336 std::vector< std::vector<bool> > cretval;
337 // Loop all signatures
338 for(int i=0; i<fdef->VariantsSize(); i++) {
339 const Signature& sigi=fdef->Variant(i);
340 std::vector<std::string> fparamsi;
341 std::vector<std::string> ctypesi;
342 std::vector<Parameter::ParamAttr> fattribi;
343 std::vector<bool> cretvali;
344 int retcount=0;
345 for(int j=0; j<sigi.Size(); j++) {
346 // Retrieve faudes par, type and attrib
347 std::string fparam=sigi.At(j).Name();
348 std::string ftype=sigi.At(j).Type();
349 Parameter::ParamAttr fattr=sigi.At(j).Attribute();
350 bool fcret=sigi.At(j).CReturn();
351 // Count ret values
352 if(fcret) retcount++;
353 // Bail out on unknown faudestype
354 if(!TypeRegistry::G()->Exists(ftype)) break;
355 // Get corresponding ctype
356 std::string ctype=TypeRegistry::G()->Definition(ftype).CType();
357 // Bail out on unknown ctype
358 if(ctype=="") break;
359 // bail out on non-out ret value
360 if(fcret && !(fattr==Parameter::Out)) break;
361 // Bail out on undef attribute
362 if(fattr==Parameter::UnDef) break;
363 // Bail out on more than one ret values
364 if(retcount>1) break;
365 // Remove name space faudes
366 size_t pos=ctype.find("faudes::");
367 if(pos!=std::string::npos)
368 ctype=ctype.substr(std::string("faudes::").length());
369 // Param ok
370 fparamsi.push_back(fparam);
371 ctypesi.push_back(ctype);
372 fattribi.push_back(fattr);
373 cretvali.push_back(fcret);
374 }
375 // Test for signature error
376 if((int) ctypesi.size()!=sigi.Size()) {
377 std::cout << "rti2code: function registration: " << fname << ": cannot interpret signature "
378 << sigi.Name() << std::endl;
379 break;
380 }
381 // Record
382 fparams.push_back(fparamsi);
383 ctypes.push_back(ctypesi);
384 fattrib.push_back(fattribi);
385 cretval.push_back(cretvali);
386 }
387 // Report
388 std::cout << "rti2code: generating rti wrapper for \"" << fdef->Name() << "\"" <<
389 " #" << ctypes.size() << " variants" << std::endl;
390 std::string rtiname = std::string("Rti") + ToStringInteger(fcnt) + ctype;
391
392 // Produce C++ code: register faudes function
393 if(loader) {
394 rticode << " FunctionRegistry::G()->Insert<" << rtiname << ">(\"" << fname <<"\");" << std::endl;
395 }
396 // Produce C++ code: class declaration intro
397 if(loader) {
398 rtiheader << "/* Function class for C++ function " << ctype << "*/" << std::endl;
399 rtiheader << "class " << rtiname << " : public Function { " << std::endl;
400 rtiheader << "public:" << std::endl;
401 rtiheader << " using Function::operator=;" << std::endl;
402 rtiheader << rtiname << "(const FunctionDefinition* fdef) : Function(fdef) {};" << std::endl;
403 rtiheader << "virtual Function* New(void) const { return new " << rtiname << "(pFuncDef); };" << std::endl;
404 rtiheader << "protected:" << std::endl;
405 }
406 // Produce C++ code: function class: have typed param
407 if(loader) {
408 for(unsigned int i=0; i<ctypes.size(); i++)
409 for(unsigned int j=0; j<ctypes.at(i).size(); j++)
410 rtiheader << ctypes.at(i).at(j) << "* " << "mP_" << i << "_" << j << ";" << std::endl;
411 }
412 // Produce C++ code: function class: do type check
413 if(loader) {
414 rtiheader << "virtual bool DoTypeCheck(int n) {" << std::endl;
415 rtiheader << " bool res=false;" << std::endl;
416 rtiheader << " switch(mVariantIndex) { "<< std::endl;
417 for(unsigned int i=0; i<ctypes.size(); i++) {
418 rtiheader << " case " << i << ": { // variant " << fdef->Variant(i).Name() << std::endl;
419 rtiheader << " switch(n) { "<< std::endl;
420 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
421 rtiheader << " case " << j << ": ";
422 rtiheader << " res=DoTypeCast<" << ctypes.at(i).at(j) << ">(" << j << ", mP_" << i <<"_" << j << "); ";
423 rtiheader << "break; "<< std::endl;
424 }
425 rtiheader << " default: break; " << std::endl;
426 rtiheader << " } "<< std::endl;
427 rtiheader << " break; "<< std::endl;
428 rtiheader << " } "<< std::endl;
429 }
430 rtiheader << " default: break; " << std::endl;
431 rtiheader << " } "<< std::endl;
432 rtiheader << " return res;" << std::endl;
433 rtiheader << "};" << std::endl;
434 }
435 // Produce C++ code: function class: do execute
436 if(loader) {
437 rtiheader << "virtual void DoExecute(void) {" << std::endl;
438 }
439 // Produce C++ code: do execute: switch variant
440 if(loader) {
441 rtiheader << " switch(mVariantIndex) { "<< std::endl;
442 for(unsigned int i=0; i<ctypes.size(); i++) {
443 rtiheader << " case " << i << ": { // variant " << fdef->Variant(i).Name() << std::endl;
444 rtiheader << " ";
445 // Figure return value (if any)
446 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
447 if(!cretval.at(i).at(j)) continue;
448 // Special case: integer
449 if(ctypes.at(i).at(j) == "Integer") {
450 rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
451 } else
452 // Special case: boolean
453 if(ctypes.at(i).at(j) == "Boolean") {
454 rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
455 } else
456 // Special case: integer
457 if(ctypes.at(i).at(j) == "String") {
458 rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
459 } else
460 // Std case
461 rtiheader << "*mP_" << i << "_" << j << " = ";
462 }
463 // Function name
464 rtiheader << ctype <<"(";
465 // Parameters
466 int parpos=0;
467 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
468 if(cretval.at(i).at(j)) continue;
469 if((parpos++)!=0) rtiheader << " ,";
470 // Special case: integer
471 if(ctypes.at(i).at(j) == "Integer") {
472 rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
473 } else
474 // Special case: boolean
475 if(ctypes.at(i).at(j) == "Boolean") {
476 rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
477 } else
478 // Special case: integer
479 if(ctypes.at(i).at(j) == "String") {
480 rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
481 } else
482 // Std case
483 rtiheader << "*mP_" << i << "_" << j;
484 }
485 rtiheader << "); break; };" << std::endl;
486 }
487 // Produce C++ code: switch variant; done
488 rtiheader << " default: break; " << std::endl;
489 rtiheader << " }; "<< std::endl;
490 // Produce C++ code: do execute: done
491 rtiheader << "}; "<< std::endl;
492 // Produce c code: function class: done
493 rtiheader << "};" << std::endl;
494 }
495
496 // Produce SWIG interface: function declarations
497 if(swig) {
498 swigheader << "/* faudes-function \"" << fname << "\" */" << std::endl;
499 }
500 // Figure my plugin to insert a conditional
501 if(swig) {
502 if(!flat) {
503 std::string plugin=fdef->PlugIn();
504 swigheader << "#if " << "( SwigModule == \"Swig" << plugin << "\")";
505 //swigheader << " || ( SwigModule == \"SwigLibFaudes\")"; // requires SWIG 4.1
506 swigheader << std::endl;
507 }
508 }
509 // Use C-type function name
510 if(swig) {
511 if(ctype!=fname)
512 swigheader << "%rename(" << fname << ") " << ctype << ";" << std::endl;
513 }
514
515 // Prepare interfaces per signature
516 std::vector< std::string > lfsigs;
517 std::vector< std::string > lfdecs;
518 std::vector< std::string > lfdefs;
519 std::vector< std::string > lrtypes;
520 std::vector< std::string > lhelp;
521
522 // Process per signature (nominal wrappers)
523 for(unsigned int i=0; i<ctypes.size(); i++) {
524 // Create function declaration: return value
525 std::string lrtype="void";
526 // Special case: C++ function has a C++ return type
527 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
528 if(!cretval.at(i).at(j)) continue;
529 // Special case: integer
530 if(ctypes.at(i).at(j) == "Integer") {
531 lrtype="long int";
532 } else
533 // Special case: boolean
534 if(ctypes.at(i).at(j) == "Boolean") {
535 lrtype="bool";
536 } else
537 // Special case: string
538 if(ctypes.at(i).at(j) == "String") {
539 lrtype="std::string";
540 } else
541 // Std case ctype as refernce
542 lrtype = ctypes.at(i).at(j);
543 // No more than one return value
544 break;
545 }
546 lrtypes.push_back(lrtype);
547 // Create ctype function declaration
548 std::string lfdec = ctype + "(";
549 std::string lfsig = ctype + "-";
550 int parpos=0;
551 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
552 // Skip C-return
553 if(cretval.at(i).at(j)) continue;
554 if(parpos!=0) {
555 lfdec += ", ";
556 lfsig += "-";
557 }
558 // Effective signature
559 lfsig += ctypes.at(i).at(j);
560 // Have const for +In+
561 if(fattrib.at(i).at(j)==Parameter::In)
562 lfdec += "const ";
563 // Special case: integer
564 if(ctypes.at(i).at(j) == "Integer") {
565 lfdec += "long int&";
566 } else
567 // Special case: boolean
568 if(ctypes.at(i).at(j) == "Boolean") {
569 lfdec += "bool&";
570 } else
571 // Special case: string
572 if(ctypes.at(i).at(j) == "String") {
573 lfdec += "std::string&";
574 } else
575 // Std case ctype as refernce
576 lfdec += ctypes.at(i).at(j) + "&";
577 parpos++;
578 // Mark elementary outputs
579 bool marked=false;
580 if(ctypes.at(i).at(j) == "Boolean" || ctypes.at(i).at(j) == "String"
581 || ctypes.at(i).at(j) == "Integer") {
582 if(fattrib.at(i).at(j)==Parameter::Out) {
583 lfdec += " OUTPUT";
584 marked=true;
585 }
586 }
587 // give it a name
588 if(!marked) {
589 lfdec += " " + fparams.at(i).at(j);
590 }
591 }
592 // End of function declaration
593 lfdec += ")";
594 lfdecs.push_back(lfdec);
595 lfsigs.push_back(lfsig);
596 // Add help entry: build nice signature
597 std::string luasig = " " + fname + "(";
598 bool leftcomma = false;
599 bool rightcomma = false;
600 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
601 // Special case: elementary output
602 if(ctypes.at(i).at(j) == "Boolean" || ctypes.at(i).at(j) == "String"
603 || ctypes.at(i).at(j) == "Integer")
604 if(fattrib.at(i).at(j)==Parameter::Out) {
605 if(leftcomma) luasig = "," + luasig;
606 // if(leftcomma) luasig = ", " + luasig; // need tab in help system?
607 luasig=ctypes.at(i).at(j) + luasig;
608 leftcomma=true;
609 continue;
610 }
611 // Std case
612 if(rightcomma) luasig += ", ";
613 const Signature& sigi=fdef->Variant(i);
614 luasig += sigi.At(j).Str();
615 rightcomma=true;
616 }
617 luasig+=")";
618 // Add help entry: add with topic
619 if(fdef->TextDoc()!=""){
620 std::string topic= fdef->PlugIn();
621 std::string key1=fdef->KeywordAt(1);
622 if(topic=="CoreFaudes") {
623 topic=fdef->KeywordAt(1);
624 key1=fdef->KeywordAt(2);
625 }
626 if(topic.length()>0) topic.at(0)=toupper(topic.at(0));
627 if(key1.length()>0) key1.at(0)=toupper(key1.at(0));
628 lhelp.push_back("SwigHelpEntry(\"" + topic + "\", \"" + key1 + "\", \"" +
629 luasig + "\")");
630 } else {
631 lhelp.push_back("");
632 }
633 // Std no function body
634 lfdefs.push_back("");
635 }
636
637 // Test whether we generate convenience wrappers: dont so if we have in-situ parameters
638 bool xwrp=true;
639 for(unsigned int i=0; i<ctypes.size(); i++) {
640 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
641 if(fattrib.at(i).at(j)==Parameter::InOut)
642 xwrp=false;
643 }
644 }
645
646 // Test whether we generate convenience wrappers: for signatures, with exactly one out parameter
647 for(unsigned int i=0; i<ctypes.size() && xwrp; i++) {
648 int fret=-1;
649 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
650 // No extra wrapper if we have a C return value
651 if(cretval.at(i).at(j)) {
652 fret=-1;
653 break;
654 }
655 // Insist in exactly one faudes output parameter
656 if(fattrib.at(i).at(j)==Parameter::Out) {
657 if(fret>=0) {
658 fret=-1;
659 break;
660 };
661 fret=j;
662 }
663 // No extra wrapper if we have an elementary type as the only output
664 if(ctypes.at(i).at(j) == "Boolean" || ctypes.at(i).at(j) == "String"
665 || ctypes.at(i).at(j) == "Integer") {
666 if(fattrib.at(i).at(j)==Parameter::Out) {
667 fret=-1;
668 break;
669 }
670 }
671 }
672 // Do generate extra wrapper with faudes return value
673 if(fret>=0) {
674 // record return type
675 std::string lrtype = ctypes.at(i).at(fret);
676 lrtypes.push_back(lrtype);
677 // Create ctype function declaration: function body
678 std::string lfdec = ctype + "(";
679 std::string lfsig = ctype + "-";
680 // Create ctype function declaration: parameters
681 int parpos=0;
682 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
683 // Skip C-return
684 if(j==fret) continue;
685 if(parpos!=0) {
686 lfdec += ", ";
687 lfsig += "-";
688 }
689 // Effective signature
690 lfsig += ctypes.at(i).at(j);
691 // Have const for +In+
692 if(fattrib.at(i).at(j)==Parameter::In)
693 lfdec += "const ";
694 // Special case: integer
695 if(ctypes.at(i).at(j) == "Integer") {
696 lfdec += "long int&";
697 } else
698 // Special case: boolean
699 if(ctypes.at(i).at(j) == "Boolean") {
700 lfdec += "bool&";
701 } else
702 // Special case: string
703 if(ctypes.at(i).at(j) == "String") {
704 lfdec += "std::string&";
705 } else {
706 // Std case ctype as refernce
707 lfdec += ctypes.at(i).at(j) + "&";
708 }
709 // Name the parameter
710 lfdec += " " + fparams.at(i).at(j);
711 parpos++;
712 }
713 lfdec += ")";
714 // Record function definition
715 lfdecs.push_back(lfdec);
716 lfsigs.push_back(lfsig);
717 // Create ctype body
718 std::string lfdef;
719 lfdef += "{ ";
720 lfdef += lrtype;
721 lfdef += " res; ";
722 lfdef += ctype;
723 lfdef += "(";
724 parpos=0;
725 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
726 if(j!=0)
727 lfdef += ", ";
728 if(j==fret) {
729 lfdef += "res";
730 continue;
731 }
732 lfdef += fparams.at(i).at(j);
733 }
734 lfdef += "); return res; }";
735 // Record function definition
736 lfdefs.push_back(lfdef);
737 // no help entry
738 lhelp.push_back("");
739 }
740
741 }// Done: itarate signatures
742
743 // Filter pseudo doublets (matching signature)
744 for(unsigned int i=1; i<lfsigs.size();i++) {
745 unsigned int j;
746 for(j=0; j<i; j++)
747 if(lfsigs.at(i)==lfsigs.at(j)) break;
748 if(j==i) continue;
749 std::cout << "rti2code: ambiguous signatures: ";
750 std::cout << lrtypes.at(i) << "+" << lfsigs.at(i) << " vs. ";
751 std::cout << lrtypes.at(j) << "+" << lfsigs.at(j) << std::endl;
752 // Invalidate entry (prefer non-void return type)
753 if((lrtypes.at(j)=="void") && (lrtypes.at(i)!="void"))
754 {lfdecs[j]=""; continue;}
755 if((lrtypes.at(i)=="void") && (lrtypes.at(j)!="void"))
756 {lfdecs[i]=""; continue;}
757 // Invalidate entry (by order: first wins)
758 lfdecs[i]="";
759 }
760
761 // Generate SWIG declarations: write
762 if(swig) {
763 int lcount=0;
764 for(unsigned int i=0; i<lfdecs.size(); i++) {
765 if(lfdecs.at(i)=="") continue;
766 swigheader << "%feature(\"autodoc\",\"1\");" << std::endl;
767 swigheader << lrtypes.at(i) << " " << lfdecs.at(i) << ";" << std::endl;
768 if(lhelp.at(i)!="")
769 swigheader << lhelp.at(i) << ";" << std::endl;
770 lcount++;
771 }
772 if(!flat) {
773 swigheader << "#endif " << std::endl;
774 }
775 swigheader << std::endl;
776 std::cout << "rti2code: generating swig interface for function \"" << fdef->Name() << "\"" <<
777 " #" << lcount << " variants" << std::endl;
778 }
779
780 // Generate C code: convenience wrappers
781 if(wrapper) {
782 int lcount=0;
783 for(unsigned int i=0; i<lfdecs.size(); i++) {
784 if(lfdecs.at(i)=="") continue;
785 if(lfdefs.at(i)=="") continue;
786 wrpheader << "extern FAUDES_API " << lrtypes.at(i) << " " << lfdecs.at(i) << ";" << std::endl;
787 wrpcode << lrtypes.at(i) << " " << lfdecs.at(i) << " " << lfdefs.at(i) << ";" << std::endl;
788 lcount++;
789 }
790 std::cout << "rti2code: generating convenience wrappers for function \"" << fdef->Name() << "\"" <<
791 " #" << lcount << " variants" << std::endl;
792 }
793
794 } // loop functions
795
796 // C++ class definition: function class: all such done
797 if(loader) {
798 rtiheader << "} // namespace" << std::endl;
799 }
800
801 // C++ class definition: register function prototypes: done
802 if(loader) {
803 rticode << "}" << std::endl;
804 rticode << "} // namespace" << std::endl;
805 }
806
807 // C++ wrappers: done
808 if(wrapper) {
809 wrpheader << "} // namespace" << std::endl;
810 wrpcode << "} // namespace" << std::endl;
811 }
812
813 return(0);
814}
int main()
const std::string & Name(void) const
std::string KeywordAt(int pos) const
const std::string & PlugIn(void) const
const std::string & TextDoc(void) const
const std::string & CType(void) const
const Signature & Variant(const std::string &rName) const
Iterator End(void) const
static FunctionRegistry * G()
std::map< std::string, FunctionDefinition * >::const_iterator Iterator
void MergeDocumentation(TokenReader &rTr)
Iterator Begin(void) const
std::string Str(void) const
bool CReturn(void) const
const std::string & Type(void) const
const ParamAttr & Attribute(void) const
const std::string & Name(void) const
int Size(void) const
const std::string & Name(void) const
const Parameter & At(int n) const
void MergeDocumentation(TokenReader &rTr)
const TypeDefinition & Definition(const std::string &rTypeName) const
static TypeRegistry * G()
std::map< std::string, TypeDefinition * >::const_iterator Iterator
bool Exists(const std::string &rName) const
Iterator End(void) const
void SaveRegistry(const std::string &rPath)
void LoadRegistry(const std::string &rPath)
std::string VersionString()
std::string PluginsString()
std::string ToStringInteger(Int number)
Definition cfl_utils.cpp:44
void usage(const std::string &rMessage="")
Definition rti2code.cpp:35

libFAUDES 2.34g --- 2026.04.09 --- c++ api documentaion by doxygen