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 (default as of libFAUDES 2.34a
210 if(tit->second->AutoRegistered()) continue;
211 // report
212 std::cout << "rti2code: generating auto-registration code for \"" << ftype << "\"" << std::endl;
213 // Produce c code
214 std::string rtiname = std::string("gRti") + ToStringInteger(tcnt) + "Register" + ftype;
215 rticode << "AutoRegisterType<" << ctype << "> " << rtiname << "(\"" << ftype <<"\");";
216 rticode << std::endl;
217 // Extra data set: element tag
218 if(tit->second->ElementTag()!="") {
219 rtiname = std::string("gRti") + ToStringInteger(tcnt) + "ElementTag" + ftype;
220 rticode << "AutoRegisterElementTag<" << ctype << "> " << rtiname << "(\"" << ftype <<
221 "\", \"" << tit->second->ElementTag() << "\");";
222 rticode << std::endl;
223 }
224 // Extra data set: element tag
225 if(tit->second->ElementType()!="") {
226 rtiname = std::string("gRti") + ToStringInteger(tcnt) + "ElementType" + ftype;
227 rticode << "AutoRegisterElementType<" << ctype << "> " << rtiname << "(\"" << ftype <<
228 "\", \"" << tit->second->ElementType() << "\");";
229 rticode << std::endl;
230 }
231 }
232 }
233
234 // Generate C++ static factory objects (end)
235 if(loader) {
236 rticode << "} // namespace" << std::endl;
237 }
238
239 // C++ function declarations: load types
240 if(loader) {
241 rtiheader << "namespace faudes {" << std::endl;
242 rtiheader << "void LoadRegisteredTypes(void);" << std::endl;
243 rtiheader << "} // namespace" << std::endl;
244 }
245
246 // C++ function definition: load types
247 if(loader) {
248 rticode << "namespace faudes {" << std::endl;
249 rticode << "/* Register faudes types */" << std::endl;
250 rticode << "void LoadRegisteredTypes(void) {" << std::endl;
251 }
252
253 // Traverse type registry to figure faudes types
254 if(loader) {
256 for(tit=TypeRegistry::G()->Begin(); tit!=TypeRegistry::G()->End();tit++) {
257 // Get C type
258 std::string ctype=tit->second->CType();
259 // Bail out if no c type specified
260 if(ctype=="") continue;
261 // Remove name space faudes
262 size_t pos=ctype.find("faudes::");
263 if(pos!=std::string::npos)
264 ctype=ctype.substr(std::string("faudes::").length());
265 // Bail out if programmatically registered (default as of libFAUDES 2.34a
266 if(tit->second->AutoRegistered()) continue;
267 // Report
268 std::cout << "rti2code: generating registration code for \"" << tit->second->Name() << "\"" << std::endl;
269 // Produce c code
270 rticode << " TypeRegistry::G()->Insert<" << ctype << ">(\"" << tit->second->Name() <<"\");";
271 rticode << std::endl;
272 }
273 }
274
275 // C++ function definition: load types end
276 if(loader) {
277 rticode << "}" << std::endl;
278 rticode << "} // namespace" << std::endl;
279 }
280
281
282 // C++ function declaration: load functions
283 if(loader) {
284 rtiheader << "namespace faudes {" << std::endl;
285 rtiheader << "void LoadRegisteredFunctions(void);" << std::endl;
286 rtiheader << "} // namespace" << std::endl;
287 }
288
289 // C++ function definition: load functions
290 if(loader) {
291 rticode << "namespace faudes {" << std::endl;
292 rticode << "/* Register faudes functions */" << std::endl;
293 rticode << "void LoadRegisteredFunctions(void) {" << std::endl;
294 }
295
296 // C++ class definition: Function derivates
297 if(loader) {
298 rtiheader << "namespace faudes {" << std::endl;
299 }
300
301 // C++ wrapper: intro
302 if(wrapper) {
303 wrpcode << "namespace faudes {" << std::endl;
304 wrpheader << "namespace faudes {" << std::endl;
305 }
306
307 // Traverse function registry: define rti function objects
308 int fcnt=0;
310 for(fit=FunctionRegistry::G()->Begin(); fit!=FunctionRegistry::G()->End();fit++, fcnt++) {
311 // Current function definition
312 const FunctionDefinition* fdef = fit->second;
313 // Get C type and faudes function name
314 std::string ctype=fdef->CType();
315 std::string fname = fdef->Name();
316 // Bail out if no c type specified
317 if(ctype=="") continue;
318 // Remove name space faudes
319 size_t pos=ctype.find("faudes::");
320 if(pos!=std::string::npos)
321 ctype=ctype.substr(std::string("faudes::").length());
322 // Bail out if no signature
323 if(fdef->VariantsSize()==0) {
324 std::cout << "rti2cocde: function registration: " << fname << ": no signatures" << std::endl;
325 continue;
326 }
327
328
329 // Interpret signatures: set up types array
330 std::vector< std::vector<std::string> > fparams;
331 std::vector< std::vector<std::string> > ctypes;
332 std::vector< std::vector<Parameter::ParamAttr> > fattrib;
333 std::vector< std::vector<bool> > cretval;
334 // Loop all signatures
335 for(int i=0; i<fdef->VariantsSize(); i++) {
336 const Signature& sigi=fdef->Variant(i);
337 std::vector<std::string> fparamsi;
338 std::vector<std::string> ctypesi;
339 std::vector<Parameter::ParamAttr> fattribi;
340 std::vector<bool> cretvali;
341 int retcount=0;
342 for(int j=0; j<sigi.Size(); j++) {
343 // Retrieve faudes par, type and attrib
344 std::string fparam=sigi.At(j).Name();
345 std::string ftype=sigi.At(j).Type();
346 Parameter::ParamAttr fattr=sigi.At(j).Attribute();
347 bool fcret=sigi.At(j).CReturn();
348 // Count ret values
349 if(fcret) retcount++;
350 // Bail out on unknown faudestype
351 if(!TypeRegistry::G()->Exists(ftype)) break;
352 // Get corresponding ctype
353 std::string ctype=TypeRegistry::G()->Definition(ftype).CType();
354 // Bail out on unknown ctype
355 if(ctype=="") break;
356 // bail out on non-out ret value
357 if(fcret && !(fattr==Parameter::Out)) break;
358 // Bail out on undef attribute
359 if(fattr==Parameter::UnDef) break;
360 // Bail out on more than one ret values
361 if(retcount>1) break;
362 // Remove name space faudes
363 size_t pos=ctype.find("faudes::");
364 if(pos!=std::string::npos)
365 ctype=ctype.substr(std::string("faudes::").length());
366 // Param ok
367 fparamsi.push_back(fparam);
368 ctypesi.push_back(ctype);
369 fattribi.push_back(fattr);
370 cretvali.push_back(fcret);
371 }
372 // Test for signature error
373 if((int) ctypesi.size()!=sigi.Size()) {
374 std::cout << "rti2code: function registration: " << fname << ": cannot interpret signature "
375 << sigi.Name() << std::endl;
376 break;
377 }
378 // Record
379 fparams.push_back(fparamsi);
380 ctypes.push_back(ctypesi);
381 fattrib.push_back(fattribi);
382 cretval.push_back(cretvali);
383 }
384 // Report
385 std::cout << "rti2code: generating rti wrapper for \"" << fdef->Name() << "\"" <<
386 " #" << ctypes.size() << " variants" << std::endl;
387 std::string rtiname = std::string("Rti") + ToStringInteger(fcnt) + ctype;
388
389 // Produce C++ code: register faudes function
390 if(loader) {
391 rticode << " FunctionRegistry::G()->Insert<" << rtiname << ">(\"" << fname <<"\");" << std::endl;
392 }
393 // Produce C++ code: class declaration intro
394 if(loader) {
395 rtiheader << "/* Function class for C++ function " << ctype << "*/" << std::endl;
396 rtiheader << "class " << rtiname << " : public Function { " << std::endl;
397 rtiheader << "public:" << std::endl;
398 rtiheader << " using Function::operator=;" << std::endl;
399 rtiheader << rtiname << "(const FunctionDefinition* fdef) : Function(fdef) {};" << std::endl;
400 rtiheader << "virtual Function* New(void) const { return new " << rtiname << "(pFuncDef); };" << std::endl;
401 rtiheader << "protected:" << std::endl;
402 }
403 // Produce C++ code: function class: have typed param
404 if(loader) {
405 for(unsigned int i=0; i<ctypes.size(); i++)
406 for(unsigned int j=0; j<ctypes.at(i).size(); j++)
407 rtiheader << ctypes.at(i).at(j) << "* " << "mP_" << i << "_" << j << ";" << std::endl;
408 }
409 // Produce C++ code: function class: do type check
410 if(loader) {
411 rtiheader << "virtual bool DoTypeCheck(int n) {" << std::endl;
412 rtiheader << " bool res=false;" << std::endl;
413 rtiheader << " switch(mVariantIndex) { "<< std::endl;
414 for(unsigned int i=0; i<ctypes.size(); i++) {
415 rtiheader << " case " << i << ": { // variant " << fdef->Variant(i).Name() << std::endl;
416 rtiheader << " switch(n) { "<< std::endl;
417 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
418 rtiheader << " case " << j << ": ";
419 rtiheader << " res=DoTypeCast<" << ctypes.at(i).at(j) << ">(" << j << ", mP_" << i <<"_" << j << "); ";
420 rtiheader << "break; "<< std::endl;
421 }
422 rtiheader << " default: break; " << std::endl;
423 rtiheader << " } "<< std::endl;
424 rtiheader << " break; "<< std::endl;
425 rtiheader << " } "<< std::endl;
426 }
427 rtiheader << " default: break; " << std::endl;
428 rtiheader << " } "<< std::endl;
429 rtiheader << " return res;" << std::endl;
430 rtiheader << "};" << std::endl;
431 }
432 // Produce C++ code: function class: do execute
433 if(loader) {
434 rtiheader << "virtual void DoExecute(void) {" << std::endl;
435 }
436 // Produce C++ code: do execute: switch variant
437 if(loader) {
438 rtiheader << " switch(mVariantIndex) { "<< std::endl;
439 for(unsigned int i=0; i<ctypes.size(); i++) {
440 rtiheader << " case " << i << ": { // variant " << fdef->Variant(i).Name() << std::endl;
441 rtiheader << " ";
442 // Figure return value (if any)
443 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
444 if(!cretval.at(i).at(j)) continue;
445 // Special case: integer
446 if(ctypes.at(i).at(j) == "Integer") {
447 rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
448 } else
449 // Special case: boolean
450 if(ctypes.at(i).at(j) == "Boolean") {
451 rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
452 } else
453 // Special case: integer
454 if(ctypes.at(i).at(j) == "String") {
455 rtiheader << "*(mP_" << i << "_" << j << "->CReference()) = ";
456 } else
457 // Std case
458 rtiheader << "*mP_" << i << "_" << j << " = ";
459 }
460 // Function name
461 rtiheader << ctype <<"(";
462 // Parameters
463 int parpos=0;
464 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
465 if(cretval.at(i).at(j)) continue;
466 if((parpos++)!=0) rtiheader << " ,";
467 // Special case: integer
468 if(ctypes.at(i).at(j) == "Integer") {
469 rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
470 } else
471 // Special case: boolean
472 if(ctypes.at(i).at(j) == "Boolean") {
473 rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
474 } else
475 // Special case: integer
476 if(ctypes.at(i).at(j) == "String") {
477 rtiheader << "*(mP_" << i << "_" << j << "->CReference())";
478 } else
479 // Std case
480 rtiheader << "*mP_" << i << "_" << j;
481 }
482 rtiheader << "); break; };" << std::endl;
483 }
484 // Produce C++ code: switch variant; done
485 rtiheader << " default: break; " << std::endl;
486 rtiheader << " }; "<< std::endl;
487 // Produce C++ code: do execute: done
488 rtiheader << "}; "<< std::endl;
489 // Produce c code: function class: done
490 rtiheader << "};" << std::endl;
491 }
492
493 // Produce SWIG interface: function declarations
494 if(swig) {
495 swigheader << "/* faudes-function \"" << fname << "\" */" << std::endl;
496 }
497 // Figure my plugin to insert a conditional
498 if(swig) {
499 if(!flat) {
500 std::string plugin=fdef->PlugIn();
501 swigheader << "#if " << "( SwigModule == \"Swig" << plugin << "\")";
502 //swigheader << " || ( SwigModule == \"SwigLibFaudes\")"; // requires SWIG 4.1
503 swigheader << std::endl;
504 }
505 }
506 // Use C-type function name
507 if(swig) {
508 if(ctype!=fname)
509 swigheader << "%rename(" << fname << ") " << ctype << ";" << std::endl;
510 }
511
512 // Prepare interfaces per signature
513 std::vector< std::string > lfsigs;
514 std::vector< std::string > lfdecs;
515 std::vector< std::string > lfdefs;
516 std::vector< std::string > lrtypes;
517 std::vector< std::string > lhelp;
518
519 // Process per signature (nominal wrappers)
520 for(unsigned int i=0; i<ctypes.size(); i++) {
521 // Create function declaration: return value
522 std::string lrtype="void";
523 // Special case: C++ function has a C++ return type
524 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
525 if(!cretval.at(i).at(j)) continue;
526 // Special case: integer
527 if(ctypes.at(i).at(j) == "Integer") {
528 lrtype="long int";
529 } else
530 // Special case: boolean
531 if(ctypes.at(i).at(j) == "Boolean") {
532 lrtype="bool";
533 } else
534 // Special case: string
535 if(ctypes.at(i).at(j) == "String") {
536 lrtype="std::string";
537 } else
538 // Std case ctype as refernce
539 lrtype = ctypes.at(i).at(j);
540 // No more than one return value
541 break;
542 }
543 lrtypes.push_back(lrtype);
544 // Create ctype function declaration
545 std::string lfdec = ctype + "(";
546 std::string lfsig = ctype + "-";
547 int parpos=0;
548 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
549 // Skip C-return
550 if(cretval.at(i).at(j)) continue;
551 if(parpos!=0) {
552 lfdec += ", ";
553 lfsig += "-";
554 }
555 // Effective signature
556 lfsig += ctypes.at(i).at(j);
557 // Have const for +In+
558 if(fattrib.at(i).at(j)==Parameter::In)
559 lfdec += "const ";
560 // Special case: integer
561 if(ctypes.at(i).at(j) == "Integer") {
562 lfdec += "long int&";
563 } else
564 // Special case: boolean
565 if(ctypes.at(i).at(j) == "Boolean") {
566 lfdec += "bool&";
567 } else
568 // Special case: string
569 if(ctypes.at(i).at(j) == "String") {
570 lfdec += "std::string&";
571 } else
572 // Std case ctype as refernce
573 lfdec += ctypes.at(i).at(j) + "&";
574 parpos++;
575 // Mark elementary outputs
576 bool marked=false;
577 if(ctypes.at(i).at(j) == "Boolean" || ctypes.at(i).at(j) == "String"
578 || ctypes.at(i).at(j) == "Integer") {
579 if(fattrib.at(i).at(j)==Parameter::Out) {
580 lfdec += " OUTPUT";
581 marked=true;
582 }
583 }
584 // give it a name
585 if(!marked) {
586 lfdec += " " + fparams.at(i).at(j);
587 }
588 }
589 // End of function declaration
590 lfdec += ")";
591 lfdecs.push_back(lfdec);
592 lfsigs.push_back(lfsig);
593 // Add help entry: build nice signature
594 std::string luasig = " " + fname + "(";
595 bool leftcomma = false;
596 bool rightcomma = false;
597 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
598 // Special case: elementary output
599 if(ctypes.at(i).at(j) == "Boolean" || ctypes.at(i).at(j) == "String"
600 || ctypes.at(i).at(j) == "Integer")
601 if(fattrib.at(i).at(j)==Parameter::Out) {
602 if(leftcomma) luasig = "," + luasig;
603 // if(leftcomma) luasig = ", " + luasig; // need tab in help system?
604 luasig=ctypes.at(i).at(j) + luasig;
605 leftcomma=true;
606 continue;
607 }
608 // Std case
609 if(rightcomma) luasig += ", ";
610 const Signature& sigi=fdef->Variant(i);
611 luasig += sigi.At(j).Str();
612 rightcomma=true;
613 }
614 luasig+=")";
615 // Add help entry: add with topic
616 if(fdef->TextDoc()!=""){
617 std::string topic= fdef->PlugIn();
618 std::string key1=fdef->KeywordAt(1);
619 if(topic=="CoreFaudes") {
620 topic=fdef->KeywordAt(1);
621 key1=fdef->KeywordAt(2);
622 }
623 if(topic.length()>0) topic.at(0)=toupper(topic.at(0));
624 if(key1.length()>0) key1.at(0)=toupper(key1.at(0));
625 lhelp.push_back("SwigHelpEntry(\"" + topic + "\", \"" + key1 + "\", \"" +
626 luasig + "\")");
627 } else {
628 lhelp.push_back("");
629 }
630 // Std no function body
631 lfdefs.push_back("");
632 }
633
634 // Test whether we generate convenience wrappers: dont so if we have in-situ parameters
635 bool xwrp=true;
636 for(unsigned int i=0; i<ctypes.size(); i++) {
637 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
638 if(fattrib.at(i).at(j)==Parameter::InOut)
639 xwrp=false;
640 }
641 }
642
643 // Test whether we generate convenience wrappers: for signatures, with exactly one out parameter
644 for(unsigned int i=0; i<ctypes.size() && xwrp; i++) {
645 int fret=-1;
646 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
647 // No extra wrapper if we have a C return value
648 if(cretval.at(i).at(j)) {
649 fret=-1;
650 break;
651 }
652 // Insist in exactly one faudes output parameter
653 if(fattrib.at(i).at(j)==Parameter::Out) {
654 if(fret>=0) {
655 fret=-1;
656 break;
657 };
658 fret=j;
659 }
660 // No extra wrapper if we have an elementary type as the only output
661 if(ctypes.at(i).at(j) == "Boolean" || ctypes.at(i).at(j) == "String"
662 || ctypes.at(i).at(j) == "Integer") {
663 if(fattrib.at(i).at(j)==Parameter::Out) {
664 fret=-1;
665 break;
666 }
667 }
668 }
669 // Do generate extra wrapper with faudes return value
670 if(fret>=0) {
671 // record return type
672 std::string lrtype = ctypes.at(i).at(fret);
673 lrtypes.push_back(lrtype);
674 // Create ctype function declaration: function body
675 std::string lfdec = ctype + "(";
676 std::string lfsig = ctype + "-";
677 // Create ctype function declaration: parameters
678 int parpos=0;
679 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
680 // Skip C-return
681 if(j==fret) continue;
682 if(parpos!=0) {
683 lfdec += ", ";
684 lfsig += "-";
685 }
686 // Effective signature
687 lfsig += ctypes.at(i).at(j);
688 // Have const for +In+
689 if(fattrib.at(i).at(j)==Parameter::In)
690 lfdec += "const ";
691 // Special case: integer
692 if(ctypes.at(i).at(j) == "Integer") {
693 lfdec += "long int&";
694 } else
695 // Special case: boolean
696 if(ctypes.at(i).at(j) == "Boolean") {
697 lfdec += "bool&";
698 } else
699 // Special case: string
700 if(ctypes.at(i).at(j) == "String") {
701 lfdec += "std::string&";
702 } else {
703 // Std case ctype as refernce
704 lfdec += ctypes.at(i).at(j) + "&";
705 }
706 // Name the parameter
707 lfdec += " " + fparams.at(i).at(j);
708 parpos++;
709 }
710 lfdec += ")";
711 // Record function definition
712 lfdecs.push_back(lfdec);
713 lfsigs.push_back(lfsig);
714 // Create ctype body
715 std::string lfdef;
716 lfdef += "{ ";
717 lfdef += lrtype;
718 lfdef += " res; ";
719 lfdef += ctype;
720 lfdef += "(";
721 parpos=0;
722 for(unsigned int j=0; j<ctypes.at(i).size(); j++) {
723 if(j!=0)
724 lfdef += ", ";
725 if(j==fret) {
726 lfdef += "res";
727 continue;
728 }
729 lfdef += fparams.at(i).at(j);
730 }
731 lfdef += "); return res; }";
732 // Record function definition
733 lfdefs.push_back(lfdef);
734 // no help entry
735 lhelp.push_back("");
736 }
737
738 }// Done: itarate signatures
739
740 // Filter pseudo doublets (matching signature)
741 for(unsigned int i=1; i<lfsigs.size();i++) {
742 unsigned int j;
743 for(j=0; j<i; j++)
744 if(lfsigs.at(i)==lfsigs.at(j)) break;
745 if(j==i) continue;
746 std::cout << "rti2code: ambiguous signatures: ";
747 std::cout << lrtypes.at(i) << "+" << lfsigs.at(i) << " vs. ";
748 std::cout << lrtypes.at(j) << "+" << lfsigs.at(j) << std::endl;
749 // Invalidate entry (prefer non-void return type)
750 if((lrtypes.at(j)=="void") && (lrtypes.at(i)!="void"))
751 {lfdecs[j]=""; continue;}
752 if((lrtypes.at(i)=="void") && (lrtypes.at(j)!="void"))
753 {lfdecs[i]=""; continue;}
754 // Invalidate entry (by order: first wins)
755 lfdecs[i]="";
756 }
757
758 // Generate SWIG declarations: write
759 if(swig) {
760 int lcount=0;
761 for(unsigned int i=0; i<lfdecs.size(); i++) {
762 if(lfdecs.at(i)=="") continue;
763 swigheader << "%feature(\"autodoc\",\"1\");" << std::endl;
764 swigheader << lrtypes.at(i) << " " << lfdecs.at(i) << ";" << std::endl;
765 if(lhelp.at(i)!="")
766 swigheader << lhelp.at(i) << ";" << std::endl;
767 lcount++;
768 }
769 if(!flat) {
770 swigheader << "#endif " << std::endl;
771 }
772 swigheader << std::endl;
773 std::cout << "rti2code: generating swig interface for function \"" << fdef->Name() << "\"" <<
774 " #" << lcount << " variants" << std::endl;
775 }
776
777 // Generate C code: convenience wrappers
778 if(wrapper) {
779 int lcount=0;
780 for(unsigned int i=0; i<lfdecs.size(); i++) {
781 if(lfdecs.at(i)=="") continue;
782 if(lfdefs.at(i)=="") continue;
783 wrpheader << "extern FAUDES_API " << lrtypes.at(i) << " " << lfdecs.at(i) << ";" << std::endl;
784 wrpcode << lrtypes.at(i) << " " << lfdecs.at(i) << " " << lfdefs.at(i) << ";" << std::endl;
785 lcount++;
786 }
787 std::cout << "rti2code: generating convenience wrappers for function \"" << fdef->Name() << "\"" <<
788 " #" << lcount << " variants" << std::endl;
789 }
790
791 } // loop functions
792
793 // C++ class definition: function class: all such done
794 if(loader) {
795 rtiheader << "} // namespace" << std::endl;
796 }
797
798 // C++ class definition: register function prototypes: done
799 if(loader) {
800 rticode << "}" << std::endl;
801 rticode << "} // namespace" << std::endl;
802 }
803
804 // C++ wrappers: done
805 if(wrapper) {
806 wrpheader << "} // namespace" << std::endl;
807 wrpcode << "} // namespace" << std::endl;
808 }
809
810 return(0);
811}
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:43
void usage(const std::string &rMessage="")
Definition rti2code.cpp:35

libFAUDES 2.34d --- 2026.03.11 --- c++ api documentaion by doxygen