1 /* -----------------------------------------------------------------------------
2 * This file is part of SWIG, which is licensed as a whole under version 3
3 * (or any later version) of the GNU General Public License. Some additional
4 * terms also apply to certain portions of SWIG. The full details of the SWIG
5 * license and copyrights can be found in the LICENSE and COPYRIGHT files
6 * included with the SWIG source code as distributed by the SWIG developers
7 * and at http://www.swig.org/legal.html.
8 *
9 * ruby.cxx
10 *
11 * Ruby language module for SWIG.
12 * ----------------------------------------------------------------------------- */
13
14 #include "swigmod.h"
15 #include "cparse.h"
16 #include <ctype.h>
17 #include <string.h>
18 #include <limits.h> /* for INT_MAX */
19
20 #define SWIG_PROTECTED_TARGET_METHODS 1
21
22 class RClass {
23 private:
24 String *temp;
25
26 public:
27 String *name; /* class name (renamed) */
28 String *cname; /* original C class/struct name */
29 String *mname; /* Mangled name */
30
31 /**
32 * The C variable name used in the SWIG-generated wrapper code to refer to
33 * this class; usually it is of the form "SwigClassXXX.klass", where SwigClassXXX
34 * is a swig_class struct instance and klass is a member of that struct.
35 */
36 String *vname;
37
38 /**
39 * The C variable name used in the SWIG-generated wrapper code to refer to
40 * the module that implements this class's methods (when we're trying to
41 * support C++ multiple inheritance). Usually it is of the form
42 * "SwigClassClassName.mImpl", where SwigClassXXX is a swig_class struct instance
43 * and mImpl is a member of that struct.
44 */
45 String *mImpl;
46
47 String *type;
48 String *prefix;
49 String *init;
50
51
52 int constructor_defined;
53 int destructor_defined;
54
RClass()55 RClass() {
56 temp = NewString("");
57 name = NewString("");
58 cname = NewString("");
59 mname = NewString("");
60 vname = NewString("");
61 mImpl = NewString("");
62 type = NewString("");
63 prefix = NewString("");
64 init = NewString("");
65 constructor_defined = 0;
66 destructor_defined = 0;
67 }
68
~RClass()69 ~RClass() {
70 Delete(name);
71 Delete(cname);
72 Delete(vname);
73 Delete(mImpl);
74 Delete(mname);
75 Delete(type);
76 Delete(prefix);
77 Delete(init);
78 Delete(temp);
79 }
80
set_name(const_String_or_char_ptr cn,const_String_or_char_ptr rn,const_String_or_char_ptr valn)81 void set_name(const_String_or_char_ptr cn, const_String_or_char_ptr rn, const_String_or_char_ptr valn) {
82 /* Original C/C++ class (or struct) name */
83 Clear(cname);
84 Append(cname, cn);
85
86 /* Mangled name */
87 Delete(mname);
88 mname = Swig_name_mangle(cname);
89
90 /* Renamed class name */
91 Clear(name);
92 Append(name, valn);
93
94 /* Variable name for the VALUE that refers to the Ruby Class object */
95 Clear(vname);
96 Printf(vname, "SwigClass%s.klass", name);
97
98 /* Variable name for the VALUE that refers to the Ruby Class object */
99 Clear(mImpl);
100 Printf(mImpl, "SwigClass%s.mImpl", name);
101
102 /* Prefix */
103 Clear(prefix);
104 Printv(prefix, (rn ? rn : cn), "_", NIL);
105 }
106
strip(const_String_or_char_ptr s)107 char *strip(const_String_or_char_ptr s) {
108 Clear(temp);
109 Append(temp, s);
110 if (Strncmp(s, prefix, Len(prefix)) == 0) {
111 Replaceall(temp, prefix, "");
112 }
113 return Char(temp);
114 }
115 };
116
117
118 /* flags for the make_autodoc function */
119 enum autodoc_t {
120 AUTODOC_CLASS,
121 AUTODOC_CTOR,
122 AUTODOC_DTOR,
123 AUTODOC_STATICFUNC,
124 AUTODOC_FUNC,
125 AUTODOC_METHOD,
126 AUTODOC_GETTER,
127 AUTODOC_SETTER,
128 AUTODOC_NONE
129 };
130
131 static const char *usage = "\
132 Ruby Options (available with -ruby)\n\
133 -autorename - Enable renaming of classes and methods to follow Ruby coding standards\n\
134 -globalmodule - Wrap everything into the global module\n\
135 -initname <name>- Set entry function to Init_<name> (used by `require')\n\
136 -minherit - Attempt to support multiple inheritance\n\
137 -noautorename - Disable renaming of classes and methods (default)\n\
138 -prefix <name> - Set a prefix <name> to be prepended to all names\n\
139 ";
140
141
142 #define RCLASS(hash, name) (RClass*)(Getattr(hash, name) ? Data(Getattr(hash, name)) : 0)
143 #define SET_RCLASS(hash, name, klass) Setattr(hash, name, NewVoid(klass, 0))
144
145
146 class RUBY:public Language {
147 private:
148
149 String *module;
150 String *modvar;
151 String *feature;
152 String *prefix;
153 int current;
154 Hash *classes; /* key=cname val=RClass */
155 RClass *klass; /* Currently processing class */
156 Hash *special_methods; /* Python style special method name table */
157
158 File *f_directors;
159 File *f_directors_h;
160 File *f_directors_helpers;
161 File *f_begin;
162 File *f_runtime;
163 File *f_runtime_h;
164 File *f_header;
165 File *f_wrappers;
166 File *f_init;
167 File *f_initbeforefunc;
168
169 bool useGlobalModule;
170 bool multipleInheritance;
171
172 // Wrap modes
173 enum WrapperMode {
174 NO_CPP,
175 MEMBER_FUNC,
176 CONSTRUCTOR_ALLOCATE,
177 CONSTRUCTOR_INITIALIZE,
178 DESTRUCTOR,
179 MEMBER_VAR,
180 CLASS_CONST,
181 STATIC_FUNC,
182 STATIC_VAR
183 };
184
185 /* ------------------------------------------------------------
186 * autodoc level declarations
187 * ------------------------------------------------------------ */
188
189 enum autodoc_l {
190 NO_AUTODOC = -2, // no autodoc
191 STRING_AUTODOC = -1, // use provided string
192 NAMES_AUTODOC = 0, // only parameter names
193 TYPES_AUTODOC = 1, // parameter names and types
194 EXTEND_AUTODOC = 2, // extended documentation and parameter names
195 EXTEND_TYPES_AUTODOC = 3 // extended documentation and parameter types + names
196 };
197
198 autodoc_t last_mode;
199 String* last_autodoc;
200
autodoc_level(String * autodoc)201 autodoc_l autodoc_level(String *autodoc) {
202 autodoc_l dlevel = NO_AUTODOC;
203 char *c = Char(autodoc);
204 if (c) {
205 if (isdigit(c[0])) {
206 dlevel = (autodoc_l) atoi(c);
207 } else {
208 if (strcmp(c, "extended") == 0) {
209 dlevel = EXTEND_AUTODOC;
210 } else {
211 dlevel = STRING_AUTODOC;
212 }
213 }
214 }
215 return dlevel;
216 }
217
218
219
220 /* ------------------------------------------------------------
221 * have_docstring()
222 * Check if there is a docstring directive and it has text,
223 * or there is an autodoc flag set
224 * ------------------------------------------------------------ */
225
have_docstring(Node * n)226 bool have_docstring(Node *n) {
227 String *str = Getattr(n, "feature:docstring");
228 return (str && Len(str) > 0) || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"));
229 }
230
231 /* ------------------------------------------------------------
232 * docstring()
233 * Get the docstring text, stripping off {} if necessary,
234 * and enclose in triple double quotes. If autodoc is also
235 * set then it will build a combined docstring.
236 * ------------------------------------------------------------ */
237
docstring(Node * n,autodoc_t ad_type)238 String *docstring(Node *n, autodoc_t ad_type) {
239
240 String *str = Getattr(n, "feature:docstring");
241 bool have_ds = (str && Len(str) > 0);
242 bool have_auto = (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"));
243 String *autodoc = NULL;
244 String *doc = NULL;
245
246 if (have_ds) {
247 char *t = Char(str);
248 if (*t == '{') {
249 Delitem(str, 0);
250 Delitem(str, DOH_END);
251 }
252 }
253
254 if (have_auto) {
255 autodoc = make_autodoc(n, ad_type);
256 have_auto = (autodoc && Len(autodoc) > 0);
257 }
258
259 if (have_auto || have_ds)
260 doc = NewString("/*");
261
262 if (have_auto && have_ds) { // Both autodoc and docstring are present
263 Printv(doc, "\n", autodoc, "\n", str, "\n", NIL);
264 } else if (!have_auto && have_ds) { // only docstring
265 Printv(doc, str, NIL);
266 } else if (have_auto && !have_ds) { // only autodoc
267 Printv(doc, "\n", autodoc, "\n", NIL);
268 } else {
269 doc = NewString("");
270 }
271
272 if (have_auto || have_ds)
273 Append(doc, "*/\n");
274
275 // Save the generated strings in the parse tree in case they are used later
276 // by post processing tools
277 Setattr(n, "ruby:docstring", doc);
278 Setattr(n, "ruby:autodoc", autodoc);
279 return doc;
280 }
281
282 /* -----------------------------------------------------------------------------
283 * addMissingParameterNames()
284 * For functions that have not had nameless parameters set in the Language class.
285 *
286 * Inputs:
287 * plist - entire parameter list
288 * arg_offset - argument number for first parameter
289 * Side effects:
290 * The "lname" attribute in each parameter in plist will be contain a parameter name
291 * ----------------------------------------------------------------------------- */
292
addMissingParameterNames(Node * n,ParmList * plist,int arg_offset)293 void addMissingParameterNames(Node* n, ParmList *plist, int arg_offset) {
294 Parm *p = plist;
295 int i = arg_offset;
296 while (p) {
297 if (!Getattr(p, "lname")) {
298 String *name = makeParameterName(n, p, i);
299 Setattr(p, "lname", name);
300 Delete(name);
301 }
302 i++;
303 p = nextSibling(p);
304 }
305 }
306
307 /* ------------------------------------------------------------
308 * make_autodocParmList()
309 * Generate the documentation for the function parameters
310 * ------------------------------------------------------------ */
311
make_autodocParmList(Node * n,bool showTypes)312 String *make_autodocParmList(Node *n, bool showTypes) {
313 String *doc = NewString("");
314 String *pdocs = 0;
315 ParmList *plist = CopyParmList(Getattr(n, "parms"));
316 Parm *p;
317 Parm *pnext;
318 int lines = 0;
319 int arg_num = is_wrapping_class() ? 1 : 0;
320 const int maxwidth = 80;
321
322 addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
323
324 Swig_typemap_attach_parms("in", plist, 0);
325 Swig_typemap_attach_parms("doc", plist, 0);
326
327 if (Strcmp(ParmList_protostr(plist), "void") == 0) {
328 //No parameters actually
329 return doc;
330 }
331
332 for (p = plist; p; p = pnext, arg_num++) {
333
334 String *tm = Getattr(p, "tmap:in");
335 if (tm) {
336 pnext = Getattr(p, "tmap:in:next");
337 if (checkAttribute(p, "tmap:in:numinputs", "0")) {
338 continue;
339 }
340 } else {
341 pnext = nextSibling(p);
342 }
343
344 String *name = 0;
345 String *type = 0;
346 String *value = 0;
347 String *pdoc = Getattr(p, "tmap:doc");
348 if (pdoc) {
349 name = Getattr(p, "tmap:doc:name");
350 type = Getattr(p, "tmap:doc:type");
351 value = Getattr(p, "tmap:doc:value");
352 }
353
354 // Note: the generated name should be consistent with that in kwnames[]
355 String *made_name = 0;
356 if (!name) {
357 name = made_name = makeParameterName(n, p, arg_num);
358 }
359
360 type = type ? type : Getattr(p, "type");
361 value = value ? value : Getattr(p, "value");
362
363 if (SwigType_isvarargs(type))
364 break;
365
366 // Skip the 'self' parameter which in ruby is implicit
367 if ( Cmp(name, "self") == 0 )
368 continue;
369
370 // Make __p parameters just p (as used in STL)
371 Replace( name, "__", "", DOH_REPLACE_FIRST );
372
373 if (Len(doc)) {
374 // add a comma to the previous one if any
375 Append(doc, ", ");
376
377 // Do we need to wrap a long line?
378 if ((Len(doc) - lines * maxwidth) > maxwidth) {
379 Printf(doc, "\n%s", tab4);
380 lines += 1;
381 }
382 }
383
384 // Do the param type too?
385 Node *nn = classLookup(Getattr(p, "type"));
386 String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
387 if (showTypes)
388 Printf(doc, "%s ", type_str);
389
390 Append(doc, name);
391 if (pdoc) {
392 if (!pdocs)
393 pdocs = NewString("Parameters:\n");
394 Printf(pdocs, " %s.\n", pdoc);
395 }
396
397 if (value) {
398 String *new_value = convertValue(value, Getattr(p, "type"));
399 if (new_value) {
400 value = new_value;
401 } else {
402 Node *lookup = Swig_symbol_clookup(value, 0);
403 if (lookup)
404 value = Getattr(lookup, "sym:name");
405 }
406 Printf(doc, "=%s", value);
407 }
408 Delete(type_str);
409 Delete(made_name);
410 }
411 if (pdocs)
412 Setattr(n, "feature:pdocs", pdocs);
413 Delete(plist);
414 return doc;
415 }
416
417 /* ------------------------------------------------------------
418 * make_autodoc()
419 * Build a docstring for the node, using parameter and other
420 * info in the parse tree. If the value of the autodoc
421 * attribute is "0" then do not include parameter types, if
422 * it is "1" (the default) then do. If it has some other
423 * value then assume it is supplied by the extension writer
424 * and use it directly.
425 * ------------------------------------------------------------ */
426
make_autodoc(Node * n,autodoc_t ad_type)427 String *make_autodoc(Node *n, autodoc_t ad_type) {
428 int extended = 0;
429 // If the function is overloaded then this function is called
430 // for the last one. Rewind to the first so the docstrings are
431 // in order.
432 while (Getattr(n, "sym:previousSibling"))
433 n = Getattr(n, "sym:previousSibling");
434
435 Node *pn = Swig_methodclass(n);
436 String* super_names = NewString("");
437 String* class_name = Getattr(pn, "sym:name") ;
438
439 if ( !class_name ) {
440 class_name = NewString("");
441 } else {
442 class_name = Copy(class_name);
443 List *baselist = Getattr(pn, "bases");
444 if (baselist && Len(baselist)) {
445 Iterator base = First(baselist);
446 while (base.item && GetFlag(base.item, "feature:ignore")) {
447 base = Next(base);
448 }
449
450 int count = 0;
451 for ( ;base.item; ++count) {
452 if ( count ) Append(super_names, ", ");
453 String *basename = Getattr(base.item, "sym:name");
454
455 String* basenamestr = NewString(basename);
456 Node* parent = parentNode(base.item);
457 while (parent)
458 {
459 String *parent_name = Copy( Getattr(parent, "sym:name") );
460 if ( !parent_name ) {
461 Node* mod = Getattr(parent, "module");
462 if ( mod )
463 parent_name = Copy( Getattr(mod, "name") );
464 if ( parent_name )
465 (Char(parent_name))[0] = (char)toupper((Char(parent_name))[0]);
466 }
467 if ( parent_name ) {
468 Insert(basenamestr, 0, "::");
469 Insert(basenamestr, 0, parent_name);
470 Delete(parent_name);
471 }
472 parent = parentNode(parent);
473 }
474
475 Append(super_names, basenamestr );
476 Delete(basenamestr);
477 base = Next(base);
478 }
479 }
480 }
481 String* full_name;
482 if ( module ) {
483 full_name = NewString(module);
484 if (Len(class_name) > 0)
485 Append(full_name, "::");
486 }
487 else
488 full_name = NewString("");
489 Append(full_name, class_name);
490
491 String* symname = Getattr(n, "sym:name");
492 if ( Getattr( special_methods, symname ) )
493 symname = Getattr( special_methods, symname );
494
495 String* methodName = NewString(full_name);
496 Append(methodName, symname);
497
498
499 // Each overloaded function will try to get documented,
500 // so we keep the name of the last overloaded function and its type.
501 // Documenting just from functionWrapper() is not possible as
502 // sym:name has already been changed to include the class name
503 if ( last_mode == ad_type && Cmp(methodName, last_autodoc) == 0 ) {
504 Delete(full_name);
505 Delete(class_name);
506 Delete(super_names);
507 Delete(methodName);
508 return NewString("");
509 }
510
511
512 last_mode = ad_type;
513 last_autodoc = Copy(methodName);
514
515 String *doc = NewString("");
516 int counter = 0;
517 bool skipAuto = false;
518 Node* on = n;
519 for ( ; n; ++counter ) {
520 String *type_str = NULL;
521 skipAuto = false;
522 bool showTypes = false;
523 String *autodoc = Getattr(n, "feature:autodoc");
524 autodoc_l dlevel = autodoc_level(autodoc);
525 switch (dlevel) {
526 case NO_AUTODOC:
527 break;
528 case NAMES_AUTODOC:
529 showTypes = false;
530 break;
531 case TYPES_AUTODOC:
532 showTypes = true;
533 break;
534 case EXTEND_AUTODOC:
535 extended = 1;
536 showTypes = false;
537 break;
538 case EXTEND_TYPES_AUTODOC:
539 extended = 1;
540 showTypes = true;
541 break;
542 case STRING_AUTODOC:
543 skipAuto = true;
544 break;
545 }
546
547 SwigType *type = Getattr(n, "type");
548
549 if (type) {
550 if (Strcmp(type, "void") == 0) {
551 type_str = NULL;
552 } else {
553 SwigType *qt = SwigType_typedef_resolve_all(type);
554 if (SwigType_isenum(qt)) {
555 type_str = NewString("int");
556 } else {
557 Node *nn = classLookup(type);
558 type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
559 }
560 }
561 }
562
563 if (counter == 0) {
564 switch (ad_type) {
565 case AUTODOC_CLASS:
566 Printf(doc, " Document-class: %s", full_name);
567 if ( Len(super_names) > 0 )
568 Printf( doc, " < %s", super_names);
569 Append(doc, "\n\n");
570 break;
571 case AUTODOC_CTOR:
572 Printf(doc, " Document-method: %s.new\n\n", full_name);
573 break;
574
575 case AUTODOC_DTOR:
576 break;
577
578 case AUTODOC_STATICFUNC:
579 Printf(doc, " Document-method: %s.%s\n\n", full_name, symname);
580 break;
581
582 case AUTODOC_FUNC:
583 case AUTODOC_METHOD:
584 case AUTODOC_GETTER:
585 Printf(doc, " Document-method: %s.%s\n\n", full_name, symname);
586 break;
587 case AUTODOC_SETTER:
588 Printf(doc, " Document-method: %s.%s=\n\n", full_name, symname);
589 break;
590 case AUTODOC_NONE:
591 break;
592 }
593 }
594
595 if (skipAuto) {
596 if ( counter == 0 ) Printf(doc, " call-seq:\n");
597 switch( ad_type )
598 {
599 case AUTODOC_STATICFUNC:
600 case AUTODOC_FUNC:
601 case AUTODOC_METHOD:
602 case AUTODOC_GETTER:
603 {
604 String *paramList = make_autodocParmList(n, showTypes);
605 if (Len(paramList))
606 Printf(doc, " %s(%s)", symname, paramList);
607 else
608 Printf(doc, " %s", symname);
609 if (type_str)
610 Printf(doc, " -> %s", type_str);
611 break;
612 }
613 case AUTODOC_SETTER:
614 {
615 Printf(doc, " %s=(x)", symname);
616 if (type_str)
617 Printf(doc, " -> %s", type_str);
618 break;
619 }
620 default:
621 break;
622 }
623 } else {
624 switch (ad_type) {
625 case AUTODOC_CLASS:
626 {
627 // Only do the autodoc if there isn't a docstring for the class
628 String *str = Getattr(n, "feature:docstring");
629 if (counter == 0 && (str == 0 || Len(str) == 0)) {
630 if (CPlusPlus) {
631 Printf(doc, " Proxy of C++ %s class", full_name);
632 } else {
633 Printf(doc, " Proxy of C %s struct", full_name);
634 }
635 }
636 }
637 break;
638 case AUTODOC_CTOR:
639 if (counter == 0)
640 Printf(doc, " call-seq:\n");
641 if (Strcmp(class_name, symname) == 0) {
642 String *paramList = make_autodocParmList(n, showTypes);
643 if (Len(paramList))
644 Printf(doc, " %s.new(%s)", class_name, paramList);
645 else
646 Printf(doc, " %s.new", class_name);
647 } else {
648 Printf(doc, " %s.new(%s)", class_name, make_autodocParmList(n, showTypes));
649 }
650 break;
651
652 case AUTODOC_DTOR:
653 break;
654
655 case AUTODOC_STATICFUNC:
656 case AUTODOC_FUNC:
657 case AUTODOC_METHOD:
658 case AUTODOC_GETTER:
659 {
660 if (counter == 0)
661 Printf(doc, " call-seq:\n");
662 String *paramList = make_autodocParmList(n, showTypes);
663 if (Len(paramList))
664 Printf(doc, " %s(%s)", symname, paramList);
665 else
666 Printf(doc, " %s", symname);
667 if (type_str)
668 Printf(doc, " -> %s", type_str);
669 break;
670 }
671 case AUTODOC_SETTER:
672 {
673 Printf(doc, " call-seq:\n");
674 Printf(doc, " %s=(x)", symname);
675 if (type_str)
676 Printf(doc, " -> %s", type_str);
677 break;
678 }
679 case AUTODOC_NONE:
680 break;
681 }
682 }
683
684 // if it's overloaded then get the next decl and loop around again
685 n = Getattr(n, "sym:nextSibling");
686 if (n)
687 Append(doc, "\n");
688 Delete(type_str);
689 }
690
691 Printf(doc, "\n\n");
692 if (!skipAuto) {
693 switch (ad_type) {
694 case AUTODOC_CLASS:
695 case AUTODOC_DTOR:
696 break;
697 case AUTODOC_CTOR:
698 Printf(doc, "Class constructor.\n");
699 break;
700 case AUTODOC_STATICFUNC:
701 Printf(doc, "A class method.\n");
702 break;
703 case AUTODOC_FUNC:
704 Printf(doc, "A module function.\n");
705 break;
706 case AUTODOC_METHOD:
707 Printf(doc, "An instance method.\n");
708 break;
709 case AUTODOC_GETTER:
710 Printf(doc, "Get value of attribute.\n");
711 break;
712 case AUTODOC_SETTER:
713 Printf(doc, "Set new value for attribute.\n");
714 break;
715 case AUTODOC_NONE:
716 break;
717 }
718 }
719
720
721 n = on;
722 while ( n ) {
723 String *autodoc = Getattr(n, "feature:autodoc");
724 autodoc_l dlevel = autodoc_level(autodoc);
725
726 switch (dlevel) {
727 case NO_AUTODOC:
728 case NAMES_AUTODOC:
729 case TYPES_AUTODOC:
730 extended = 0;
731 break;
732 case STRING_AUTODOC:
733 extended = 2;
734 Replaceall( autodoc, "$class", class_name );
735 Printv(doc, autodoc, ".", NIL);
736 break;
737 case EXTEND_AUTODOC:
738 case EXTEND_TYPES_AUTODOC:
739 extended = 1;
740 break;
741 }
742
743
744 if (extended) {
745 String *pdocs = Getattr(n, "feature:pdocs");
746 if (pdocs) {
747 Printv(doc, "\n\n", pdocs, NULL);
748 break;
749 }
750 if ( extended == 2 ) break;
751 }
752 n = Getattr(n, "sym:nextSibling");
753 }
754
755 Delete(full_name);
756 Delete(class_name);
757 Delete(super_names);
758 Delete(methodName);
759
760 return doc;
761 }
762
763 /* ------------------------------------------------------------
764 * convertValue()
765 * Check if string v can be a Ruby value literal,
766 * (eg. number or string), or translate it to a Ruby literal.
767 * ------------------------------------------------------------ */
convertValue(String * v,SwigType * t)768 String *convertValue(String *v, SwigType *t) {
769 if (v && Len(v) > 0) {
770 char fc = (Char(v))[0];
771 if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) {
772 /* number or string (or maybe NULL pointer) */
773 if (SwigType_ispointer(t) && Strcmp(v, "0") == 0)
774 return NewString("None");
775 else
776 return v;
777 }
778 if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0)
779 return SwigType_ispointer(t) ? NewString("nil") : NewString("0");
780 if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0)
781 return NewString("True");
782 if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0)
783 return NewString("False");
784 }
785 return 0;
786 }
787
788 public:
789
790 /* ---------------------------------------------------------------------
791 * RUBY()
792 *
793 * Initialize member data
794 * --------------------------------------------------------------------- */
RUBY()795 RUBY() :
796 module(0),
797 modvar(0),
798 feature(0),
799 prefix(0),
800 current(0),
801 classes(0),
802 klass(0),
803 special_methods(0),
804 f_directors(0),
805 f_directors_h(0),
806 f_directors_helpers(0),
807 f_begin(0),
808 f_runtime(0),
809 f_runtime_h(0),
810 f_header(0),
811 f_wrappers(0),
812 f_init(0),
813 f_initbeforefunc(0),
814 useGlobalModule(false),
815 multipleInheritance(false),
816 last_mode(AUTODOC_NONE),
817 last_autodoc(NewString("")) {
818 current = NO_CPP;
819 director_prot_ctor_code = NewString("");
820 Printv(director_prot_ctor_code,
821 "if ( $comparison ) { /* subclassed */\n",
822 " $director_new \n",
823 "} else {\n", " rb_raise(rb_eRuntimeError,\"accessing abstract class or protected constructor\"); \n", " return Qnil;\n", "}\n", NIL);
824 director_multiple_inheritance = 0;
825 director_language = 1;
826 }
827
828 /* ---------------------------------------------------------------------
829 * main()
830 *
831 * Parse command line options and initializes variables.
832 * --------------------------------------------------------------------- */
833
main(int argc,char * argv[])834 virtual void main(int argc, char *argv[]) {
835
836 int autorename = 0;
837
838 /* Set location of SWIG library */
839 SWIG_library_directory("ruby");
840
841 /* Look for certain command line options */
842 for (int i = 1; i < argc; i++) {
843 if (argv[i]) {
844 if (strcmp(argv[i], "-initname") == 0) {
845 if (argv[i + 1]) {
846 char *name = argv[i + 1];
847 feature = NewString(name);
848 Swig_mark_arg(i);
849 Swig_mark_arg(i + 1);
850 i++;
851 } else {
852 Swig_arg_error();
853 }
854 }
855 else if (strcmp(argv[i], "-feature") == 0) {
856 fprintf( stderr, "Warning: Ruby -feature option is deprecated, "
857 "please use -initname instead.\n");
858 if (argv[i + 1]) {
859 char *name = argv[i + 1];
860 feature = NewString(name);
861 Swig_mark_arg(i);
862 Swig_mark_arg(i + 1);
863 i++;
864 } else {
865 Swig_arg_error();
866 }
867 } else if (strcmp(argv[i], "-globalmodule") == 0) {
868 useGlobalModule = true;
869 Swig_mark_arg(i);
870 } else if (strcmp(argv[i], "-minherit") == 0) {
871 multipleInheritance = true;
872 director_multiple_inheritance = 1;
873 Swig_mark_arg(i);
874 } else if (strcmp(argv[i], "-autorename") == 0) {
875 autorename = 1;
876 Swig_mark_arg(i);
877 } else if (strcmp(argv[i], "-noautorename") == 0) {
878 autorename = 0;
879 Swig_mark_arg(i);
880 } else if (strcmp(argv[i], "-prefix") == 0) {
881 if (argv[i + 1]) {
882 char *name = argv[i + 1];
883 prefix = NewString(name);
884 Swig_mark_arg(i);
885 Swig_mark_arg(i + 1);
886 i++;
887 } else {
888 Swig_arg_error();
889 }
890 } else if (strcmp(argv[i], "-help") == 0) {
891 Printf(stdout, "%s\n", usage);
892 } else if (strcmp(argv[i], "-cppcast") == 0) {
893 Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
894 Swig_mark_arg(i);
895 } else if (strcmp(argv[i], "-nocppcast") == 0) {
896 Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
897 Swig_mark_arg(i);
898 SWIG_exit(EXIT_FAILURE);
899 }
900 }
901 }
902
903 if (autorename) {
904 /* Turn on the autorename mode */
905 Preprocessor_define((DOH *) "SWIG_RUBY_AUTORENAME", 0);
906 }
907
908 /* Add a symbol to the parser for conditional compilation */
909 Preprocessor_define("SWIGRUBY 1", 0);
910
911 /* Add typemap definitions */
912 SWIG_typemap_lang("ruby");
913 SWIG_config_file("ruby.swg");
914 allow_overloading();
915 }
916
917 /**
918 * Generate initialization code to define the Ruby module(s),
919 * accounting for nested modules as necessary.
920 */
defineRubyModule()921 void defineRubyModule() {
922 List *modules = Split(module, ':', INT_MAX);
923 if (modules != 0 && Len(modules) > 0) {
924 String *mv = 0;
925 Iterator m;
926 m = First(modules);
927 while (m.item) {
928 if (Len(m.item) > 0) {
929 if (mv != 0) {
930 Printv(f_init, tab4, modvar, " = rb_define_module_under(", modvar, ", \"", m.item, "\");\n", NIL);
931 } else {
932 Printv(f_init, tab4, modvar, " = rb_define_module(\"", m.item, "\");\n", NIL);
933 mv = NewString(modvar);
934 }
935 }
936 m = Next(m);
937 }
938 Delete(mv);
939 Delete(modules);
940 }
941 }
942
registerMagicMethods()943 void registerMagicMethods() {
944
945 special_methods = NewHash();
946
947 /* Python->Ruby style special method name. */
948 /* Basic */
949 Setattr(special_methods, "__repr__", "inspect");
950 Setattr(special_methods, "__str__", "to_s");
951 Setattr(special_methods, "__cmp__", "<=>");
952 Setattr(special_methods, "__hash__", "hash");
953 Setattr(special_methods, "__nonzero__", "nonzero?");
954
955 /* Callable */
956 Setattr(special_methods, "__call__", "call");
957
958 /* Collection */
959 Setattr(special_methods, "__len__", "length");
960 Setattr(special_methods, "__getitem__", "[]");
961 Setattr(special_methods, "__setitem__", "[]=");
962
963 /* Operators */
964 Setattr(special_methods, "__add__", "+");
965 Setattr(special_methods, "__pos__", "+@");
966 Setattr(special_methods, "__sub__", "-");
967 Setattr(special_methods, "__neg__", "-@");
968 Setattr(special_methods, "__mul__", "*");
969 Setattr(special_methods, "__div__", "/");
970 Setattr(special_methods, "__mod__", "%");
971 Setattr(special_methods, "__lshift__", "<<");
972 Setattr(special_methods, "__rshift__", ">>");
973 Setattr(special_methods, "__and__", "&");
974 Setattr(special_methods, "__or__", "|");
975 Setattr(special_methods, "__xor__", "^");
976 Setattr(special_methods, "__invert__", "~");
977 Setattr(special_methods, "__lt__", "<");
978 Setattr(special_methods, "__le__", "<=");
979 Setattr(special_methods, "__gt__", ">");
980 Setattr(special_methods, "__ge__", ">=");
981 Setattr(special_methods, "__eq__", "==");
982
983 /* Other numeric */
984 Setattr(special_methods, "__divmod__", "divmod");
985 Setattr(special_methods, "__pow__", "**");
986 Setattr(special_methods, "__abs__", "abs");
987 Setattr(special_methods, "__int__", "to_i");
988 Setattr(special_methods, "__float__", "to_f");
989 Setattr(special_methods, "__coerce__", "coerce");
990 }
991
992 /* ---------------------------------------------------------------------
993 * top()
994 * --------------------------------------------------------------------- */
995
top(Node * n)996 virtual int top(Node *n) {
997
998 String *mod_docstring = NULL;
999
1000 /**
1001 * See if any Ruby module options have been specified as options
1002 * to the %module directive.
1003 */
1004 Node *swigModule = Getattr(n, "module");
1005 if (swigModule) {
1006 Node *options = Getattr(swigModule, "options");
1007 if (options) {
1008 if (Getattr(options, "directors")) {
1009 allow_directors();
1010 }
1011 if (Getattr(options, "dirprot")) {
1012 allow_dirprot();
1013 }
1014 if (Getattr(options, "ruby_globalmodule")) {
1015 useGlobalModule = true;
1016 }
1017 if (Getattr(options, "ruby_minherit")) {
1018 multipleInheritance = true;
1019 director_multiple_inheritance = 1;
1020 }
1021 mod_docstring = Getattr(options, "docstring");
1022 }
1023 }
1024
1025 /* Set comparison with none for ConstructorToFunction */
1026
1027
1028 setSubclassInstanceCheck(NewStringf("strcmp(rb_obj_classname(self), classname) != 0"));
1029 // setSubclassInstanceCheck(NewString("CLASS_OF(self) != cFoo.klass"));
1030
1031 /* Initialize all of the output files */
1032 String *outfile = Getattr(n, "outfile");
1033 String *outfile_h = Getattr(n, "outfile_h");
1034
1035 if (!outfile) {
1036 Printf(stderr, "Unable to determine outfile\n");
1037 SWIG_exit(EXIT_FAILURE);
1038 }
1039
1040 f_begin = NewFile(outfile, "w", SWIG_output_files());
1041 if (!f_begin) {
1042 FileErrorDisplay(outfile);
1043 SWIG_exit(EXIT_FAILURE);
1044 }
1045
1046 f_runtime = NewString("");
1047 f_init = NewString("");
1048 f_header = NewString("");
1049 f_wrappers = NewString("");
1050 f_directors_h = NewString("");
1051 f_directors = NewString("");
1052 f_directors_helpers = NewString("");
1053 f_initbeforefunc = NewString("");
1054
1055 if (directorsEnabled()) {
1056 if (!outfile_h) {
1057 Printf(stderr, "Unable to determine outfile_h\n");
1058 SWIG_exit(EXIT_FAILURE);
1059 }
1060 f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
1061 if (!f_runtime_h) {
1062 FileErrorDisplay(outfile_h);
1063 SWIG_exit(EXIT_FAILURE);
1064 }
1065 }
1066
1067 /* Register file targets with the SWIG file handler */
1068 Swig_register_filebyname("header", f_header);
1069 Swig_register_filebyname("wrapper", f_wrappers);
1070 Swig_register_filebyname("begin", f_begin);
1071 Swig_register_filebyname("runtime", f_runtime);
1072 Swig_register_filebyname("init", f_init);
1073 Swig_register_filebyname("director", f_directors);
1074 Swig_register_filebyname("director_h", f_directors_h);
1075 Swig_register_filebyname("director_helpers", f_directors_helpers);
1076 Swig_register_filebyname("initbeforefunc", f_initbeforefunc);
1077
1078 modvar = 0;
1079 current = NO_CPP;
1080 klass = 0;
1081 classes = NewHash();
1082
1083 registerMagicMethods();
1084
1085 Swig_banner(f_begin);
1086
1087 Printf(f_runtime, "\n\n#ifndef SWIGRUBY\n#define SWIGRUBY\n#endif\n\n");
1088
1089 if (directorsEnabled()) {
1090 Printf(f_runtime, "#define SWIG_DIRECTORS\n");
1091 }
1092
1093 Printf(f_runtime, "\n");
1094
1095 /* typedef void *VALUE */
1096 SwigType *value = NewSwigType(T_VOID);
1097 SwigType_add_pointer(value);
1098 SwigType_typedef(value, "VALUE");
1099 Delete(value);
1100
1101 /* Set module name */
1102 set_module(Char(Getattr(n, "name")));
1103
1104 if (directorsEnabled()) {
1105 /* Build a version of the module name for use in a C macro name. */
1106 String *module_macro = Copy(module);
1107 Replaceall(module_macro, "::", "__");
1108
1109 Swig_banner(f_directors_h);
1110 Printf(f_directors_h, "\n");
1111 Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_macro);
1112 Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_macro);
1113 Printf(f_directors_h, "namespace Swig {\n");
1114 Printf(f_directors_h, " class Director;\n");
1115 Printf(f_directors_h, "}\n\n");
1116
1117 Printf(f_directors_helpers, "/* ---------------------------------------------------\n");
1118 Printf(f_directors_helpers, " * C++ director class helpers\n");
1119 Printf(f_directors_helpers, " * --------------------------------------------------- */\n\n");
1120
1121 Printf(f_directors, "\n\n");
1122 Printf(f_directors, "/* ---------------------------------------------------\n");
1123 Printf(f_directors, " * C++ director class methods\n");
1124 Printf(f_directors, " * --------------------------------------------------- */\n\n");
1125 if (outfile_h) {
1126 String *filename = Swig_file_filename(outfile_h);
1127 Printf(f_directors, "#include \"%s\"\n\n", filename);
1128 Delete(filename);
1129 }
1130
1131 Delete(module_macro);
1132 }
1133
1134 Printf(f_header, "#define SWIG_init Init_%s\n", feature);
1135 Printf(f_header, "#define SWIG_name \"%s\"\n\n", module);
1136
1137 if (mod_docstring) {
1138 if (Len(mod_docstring)) {
1139 Printf(f_header, "/*\n Document-module: %s\n\n%s\n*/\n", module, mod_docstring);
1140 }
1141 Delete(mod_docstring);
1142 mod_docstring = NULL;
1143 }
1144
1145 Printf(f_header, "static VALUE %s;\n", modvar);
1146
1147 /* Start generating the initialization function */
1148 String* docs = docstring(n, AUTODOC_CLASS);
1149 Printf(f_init, "/*\n%s\n*/", docs );
1150 Printv(f_init, "\n", "#ifdef __cplusplus\n", "extern \"C\"\n", "#endif\n", "SWIGEXPORT void Init_", feature, "(void) {\n", "size_t i;\n", "\n", NIL);
1151
1152 Printv(f_init, tab4, "SWIG_InitRuntime();\n", NIL);
1153
1154 if (!useGlobalModule)
1155 defineRubyModule();
1156
1157 Printv(f_init, "\n", "SWIG_InitializeModule(0);\n", "for (i = 0; i < swig_module.size; i++) {\n", "SWIG_define_class(swig_module.types[i]);\n", "}\n", NIL);
1158 Printf(f_init, "\n");
1159
1160 /* Initialize code to keep track of objects */
1161 Printf(f_init, "SWIG_RubyInitializeTrackings();\n");
1162
1163 Language::top(n);
1164
1165 if (directorsEnabled()) {
1166 // Insert director runtime into the f_runtime file (make it occur before %header section)
1167 Swig_insert_file("director_common.swg", f_runtime);
1168 Swig_insert_file("director.swg", f_runtime);
1169 }
1170
1171 /* Finish off our init function */
1172 Printf(f_init, "}\n");
1173 SwigType_emit_type_table(f_runtime, f_wrappers);
1174
1175 /* Close all of the files */
1176 Dump(f_runtime, f_begin);
1177 Dump(f_header, f_begin);
1178
1179 if (directorsEnabled()) {
1180 Dump(f_directors_helpers, f_begin);
1181 Dump(f_directors, f_begin);
1182 Dump(f_directors_h, f_runtime_h);
1183 Printf(f_runtime_h, "\n");
1184 Printf(f_runtime_h, "#endif\n");
1185 Delete(f_runtime_h);
1186 }
1187
1188 Dump(f_wrappers, f_begin);
1189 Dump(f_initbeforefunc, f_begin);
1190 Wrapper_pretty_print(f_init, f_begin);
1191
1192 Delete(f_header);
1193 Delete(f_wrappers);
1194 Delete(f_init);
1195 Delete(f_initbeforefunc);
1196 Delete(f_runtime);
1197 Delete(f_begin);
1198
1199 return SWIG_OK;
1200 }
1201
1202 /* -----------------------------------------------------------------------------
1203 * importDirective()
1204 * ----------------------------------------------------------------------------- */
1205
importDirective(Node * n)1206 virtual int importDirective(Node *n) {
1207 String *modname = Getattr(n, "module");
1208 if (modname) {
1209 if (prefix) {
1210 Insert(modname, 0, prefix);
1211 }
1212
1213 List *modules = Split(modname, ':', INT_MAX);
1214 if (modules && Len(modules) > 0) {
1215 modname = NewString("");
1216 String *last = NULL;
1217 Iterator m = First(modules);
1218 while (m.item) {
1219 if (Len(m.item) > 0) {
1220 if (last) {
1221 Append(modname, "/");
1222 }
1223 Append(modname, m.item);
1224 last = m.item;
1225 }
1226 m = Next(m);
1227 }
1228 Printf(f_init, "rb_require(\"%s\");\n", modname);
1229 Delete(modname);
1230 }
1231 Delete(modules);
1232 }
1233 return Language::importDirective(n);
1234 }
1235
1236 /* ---------------------------------------------------------------------
1237 * set_module(const char *mod_name)
1238 *
1239 * Sets the module name. Does nothing if it's already set (so it can
1240 * be overridden as a command line option).
1241 *---------------------------------------------------------------------- */
1242
set_module(const char * s)1243 void set_module(const char *s) {
1244 String *mod_name = NewString(s);
1245 if (module == 0) {
1246 /* Start with the empty string */
1247 module = NewString("");
1248
1249 if (prefix) {
1250 Insert(mod_name, 0, prefix);
1251 }
1252
1253 /* Account for nested modules */
1254 List *modules = Split(mod_name, ':', INT_MAX);
1255 if (modules != 0 && Len(modules) > 0) {
1256 String *last = 0;
1257 Iterator m = First(modules);
1258 while (m.item) {
1259 if (Len(m.item) > 0) {
1260 String *cap = NewString(m.item);
1261 (Char(cap))[0] = (char)toupper((Char(cap))[0]);
1262 if (last != 0) {
1263 Append(module, "::");
1264 }
1265 Append(module, cap);
1266 last = m.item;
1267 }
1268 m = Next(m);
1269 }
1270 if (last) {
1271 if (feature == 0) {
1272 feature = Copy(last);
1273 }
1274 (Char(last))[0] = (char)toupper((Char(last))[0]);
1275 modvar = NewStringf("m%s", last);
1276 }
1277 }
1278 Delete(modules);
1279 }
1280 Delete(mod_name);
1281 }
1282
1283 /* --------------------------------------------------------------------------
1284 * nativeWrapper()
1285 * -------------------------------------------------------------------------- */
nativeWrapper(Node * n)1286 virtual int nativeWrapper(Node *n) {
1287 String *funcname = Getattr(n, "wrap:name");
1288 Swig_warning(WARN_LANG_NATIVE_UNIMPL, input_file, line_number, "Adding native function %s not supported (ignored).\n", funcname);
1289 return SWIG_NOWRAP;
1290 }
1291
1292 /**
1293 * Process the comma-separated list of aliases (if any).
1294 */
defineAliases(Node * n,const_String_or_char_ptr iname)1295 void defineAliases(Node *n, const_String_or_char_ptr iname) {
1296 String *aliasv = Getattr(n, "feature:alias");
1297 if (aliasv) {
1298 List *aliases = Split(aliasv, ',', INT_MAX);
1299 if (aliases && Len(aliases) > 0) {
1300 Iterator alias = First(aliases);
1301 while (alias.item) {
1302 if (Len(alias.item) > 0) {
1303 if (current == NO_CPP) {
1304 if (useGlobalModule) {
1305 Printv(f_init, tab4, "rb_define_alias(rb_cObject, \"", alias.item, "\", \"", iname, "\");\n", NIL);
1306 } else {
1307 Printv(f_init, tab4, "rb_define_alias(rb_singleton_class(", modvar, "), \"", alias.item, "\", \"", iname, "\");\n", NIL);
1308 }
1309 } else if (multipleInheritance) {
1310 Printv(klass->init, tab4, "rb_define_alias(", klass->mImpl, ", \"", alias.item, "\", \"", iname, "\");\n", NIL);
1311 } else {
1312 Printv(klass->init, tab4, "rb_define_alias(", klass->vname, ", \"", alias.item, "\", \"", iname, "\");\n", NIL);
1313 }
1314 }
1315 alias = Next(alias);
1316 }
1317 }
1318 Delete(aliases);
1319 }
1320 }
1321
1322 /* ---------------------------------------------------------------------
1323 * create_command(Node *n, char *iname)
1324 *
1325 * Creates a new command from a C function.
1326 * iname = Name of function in scripting language
1327 *
1328 * A note about what "protected" and "private" mean in Ruby:
1329 *
1330 * A private method is accessible only within the class or its subclasses,
1331 * and it is callable only in "function form", with 'self' (implicit or
1332 * explicit) as a receiver.
1333 *
1334 * A protected method is callable only from within its class, but unlike
1335 * a private method, it can be called with a receiver other than self, such
1336 * as another instance of the same class.
1337 * --------------------------------------------------------------------- */
1338
create_command(Node * n,const_String_or_char_ptr iname)1339 void create_command(Node *n, const_String_or_char_ptr iname) {
1340
1341 String *alloc_func = Swig_name_wrapper(iname);
1342 String *wname = Swig_name_wrapper(iname);
1343 if (CPlusPlus) {
1344 Insert(wname, 0, "VALUEFUNC(");
1345 Append(wname, ")");
1346 }
1347 if (current != NO_CPP)
1348 iname = klass->strip(iname);
1349 if (Getattr(special_methods, iname)) {
1350 iname = GetChar(special_methods, iname);
1351 }
1352
1353 String *s = NewString("");
1354 String *temp = NewString("");
1355
1356 #ifdef SWIG_PROTECTED_TARGET_METHODS
1357 const char *rb_define_method = is_public(n) ? "rb_define_method" : "rb_define_protected_method";
1358 #else
1359 const char *rb_define_method = "rb_define_method";
1360 #endif
1361 switch (current) {
1362 case MEMBER_FUNC:
1363 {
1364 if (multipleInheritance) {
1365 Printv(klass->init, tab4, rb_define_method, "(", klass->mImpl, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
1366 } else {
1367 Printv(klass->init, tab4, rb_define_method, "(", klass->vname, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
1368 }
1369 }
1370 break;
1371 case CONSTRUCTOR_ALLOCATE:
1372 Printv(s, tab4, "rb_define_alloc_func(", klass->vname, ", ", alloc_func, ");\n", NIL);
1373 Replaceall(klass->init, "$allocator", s);
1374 break;
1375 case CONSTRUCTOR_INITIALIZE:
1376 Printv(s, tab4, rb_define_method, "(", klass->vname, ", \"initialize\", ", wname, ", -1);\n", NIL);
1377 Replaceall(klass->init, "$initializer", s);
1378 break;
1379 case MEMBER_VAR:
1380 Append(temp, iname);
1381 /* Check for _set or _get at the end of the name. */
1382 if (Len(temp) > 4) {
1383 const char *p = Char(temp) + (Len(temp) - 4);
1384 if (strcmp(p, "_set") == 0) {
1385 Delslice(temp, Len(temp) - 4, DOH_END);
1386 Append(temp, "=");
1387 } else if (strcmp(p, "_get") == 0) {
1388 Delslice(temp, Len(temp) - 4, DOH_END);
1389 }
1390 }
1391 if (multipleInheritance) {
1392 Printv(klass->init, tab4, "rb_define_method(", klass->mImpl, ", \"", temp, "\", ", wname, ", -1);\n", NIL);
1393 } else {
1394 Printv(klass->init, tab4, "rb_define_method(", klass->vname, ", \"", temp, "\", ", wname, ", -1);\n", NIL);
1395 }
1396 break;
1397 case STATIC_FUNC:
1398 Printv(klass->init, tab4, "rb_define_singleton_method(", klass->vname, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
1399 break;
1400 case NO_CPP:
1401 if (!useGlobalModule) {
1402 Printv(s, tab4, "rb_define_module_function(", modvar, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
1403 Printv(f_init, s, NIL);
1404 } else {
1405 Printv(s, tab4, "rb_define_global_function(\"", iname, "\", ", wname, ", -1);\n", NIL);
1406 Printv(f_init, s, NIL);
1407 }
1408 break;
1409 case DESTRUCTOR:
1410 case CLASS_CONST:
1411 case STATIC_VAR:
1412 default:
1413 assert(false); // Should not have gotten here for these types
1414 }
1415
1416 defineAliases(n, iname);
1417
1418 Delete(temp);
1419 Delete(s);
1420 Delete(wname);
1421 Delete(alloc_func);
1422 }
1423
1424 /* ---------------------------------------------------------------------
1425 * applyInputTypemap()
1426 *
1427 * Look up the appropriate "in" typemap for this parameter (p),
1428 * substitute the correct strings for the $target and $input typemap
1429 * parameters, and dump the resulting code to the wrapper file.
1430 * --------------------------------------------------------------------- */
1431
applyInputTypemap(Parm * p,String * ln,String * source,Wrapper * f,String * symname)1432 Parm *applyInputTypemap(Parm *p, String *ln, String *source, Wrapper *f, String *symname) {
1433 String *tm;
1434 SwigType *pt = Getattr(p, "type");
1435 if ((tm = Getattr(p, "tmap:in"))) {
1436 Replaceall(tm, "$target", ln);
1437 Replaceall(tm, "$source", source);
1438 Replaceall(tm, "$input", source);
1439 Replaceall(tm, "$symname", symname);
1440
1441 if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
1442 Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
1443 } else {
1444 Replaceall(tm, "$disown", "0");
1445 }
1446
1447 Setattr(p, "emit:input", Copy(source));
1448 Printf(f->code, "%s\n", tm);
1449 p = Getattr(p, "tmap:in:next");
1450 } else {
1451 Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
1452 p = nextSibling(p);
1453 }
1454 return p;
1455 }
1456
skipIgnoredArgs(Parm * p)1457 Parm *skipIgnoredArgs(Parm *p) {
1458 while (checkAttribute(p, "tmap:in:numinputs", "0")) {
1459 p = Getattr(p, "tmap:in:next");
1460 }
1461 return p;
1462 }
1463
1464 /* ---------------------------------------------------------------------
1465 * marshalInputArgs()
1466 *
1467 * Process all of the arguments passed into the scripting language
1468 * method and convert them into C/C++ function arguments using the
1469 * supplied typemaps.
1470 * --------------------------------------------------------------------- */
1471
marshalInputArgs(Node * n,ParmList * l,int numarg,int numreq,String * kwargs,bool allow_kwargs,Wrapper * f)1472 void marshalInputArgs(Node *n, ParmList *l, int numarg, int numreq, String *kwargs, bool allow_kwargs, Wrapper *f) {
1473 int i;
1474 Parm *p;
1475 String *tm;
1476 String *source;
1477 String *target;
1478
1479 source = NewString("");
1480 target = NewString("");
1481
1482 bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
1483
1484 /**
1485 * The 'start' value indicates which of the C/C++ function arguments
1486 * produced here corresponds to the first value in Ruby's argv[] array.
1487 * The value of start is either zero or one. If start is zero, then
1488 * the first argument (with name arg1) is based on the value of argv[0].
1489 * If start is one, then arg1 is based on the value of argv[1].
1490 */
1491 int start = (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) ? 1 : 0;
1492
1493 int varargs = emit_isvarargs(l);
1494
1495 Printf(kwargs, "{ ");
1496 for (i = 0, p = l; i < numarg; i++) {
1497
1498 p = skipIgnoredArgs(p);
1499
1500 String *pn = Getattr(p, "name");
1501 String *ln = Getattr(p, "lname");
1502
1503 /* Produce string representation of source argument */
1504 Clear(source);
1505
1506 /* First argument is a special case */
1507 if (i == 0) {
1508 Printv(source, (start == 0) ? "argv[0]" : "self", NIL);
1509 } else {
1510 Printf(source, "argv[%d]", i - start);
1511 }
1512
1513 /* Produce string representation of target argument */
1514 Clear(target);
1515 Printf(target, "%s", Char(ln));
1516
1517 if (i >= (numreq)) { /* Check if parsing an optional argument */
1518 Printf(f->code, " if (argc > %d) {\n", i - start);
1519 }
1520
1521 /* Record argument name for keyword argument handling */
1522 if (Len(pn)) {
1523 Printf(kwargs, "\"%s\",", pn);
1524 } else {
1525 Printf(kwargs, "\"arg%d\",", i + 1);
1526 }
1527
1528 /* Look for an input typemap */
1529 p = applyInputTypemap(p, ln, source, f, Getattr(n, "name"));
1530 if (i >= numreq) {
1531 Printf(f->code, "}\n");
1532 }
1533 }
1534
1535 /* Finish argument marshalling */
1536 Printf(kwargs, " NULL }");
1537 if (allow_kwargs) {
1538 // kwarg support not implemented
1539 // Printv(f->locals, tab4, "const char *kwnames[] = ", kwargs, ";\n", NIL);
1540 }
1541
1542 /* Trailing varargs */
1543 if (varargs) {
1544 if (p && (tm = Getattr(p, "tmap:in"))) {
1545 Clear(source);
1546 Printf(source, "argv[%d]", i - start);
1547 Replaceall(tm, "$input", source);
1548 Setattr(p, "emit:input", Copy(source));
1549 Printf(f->code, "if (argc > %d) {\n", i - start);
1550 Printv(f->code, tm, "\n", NIL);
1551 Printf(f->code, "}\n");
1552 }
1553 }
1554
1555 Delete(source);
1556 Delete(target);
1557 }
1558
1559 /* ---------------------------------------------------------------------
1560 * insertConstraintCheckingCode(ParmList *l, Wrapper *f)
1561 *
1562 * Checks each of the parameters in the parameter list for a "check"
1563 * typemap and (if it finds one) inserts the typemapping code into
1564 * the function wrapper.
1565 * --------------------------------------------------------------------- */
1566
insertConstraintCheckingCode(ParmList * l,Wrapper * f)1567 void insertConstraintCheckingCode(ParmList *l, Wrapper *f) {
1568 Parm *p;
1569 String *tm;
1570 for (p = l; p;) {
1571 if ((tm = Getattr(p, "tmap:check"))) {
1572 Replaceall(tm, "$target", Getattr(p, "lname"));
1573 Printv(f->code, tm, "\n", NIL);
1574 p = Getattr(p, "tmap:check:next");
1575 } else {
1576 p = nextSibling(p);
1577 }
1578 }
1579 }
1580
1581 /* ---------------------------------------------------------------------
1582 * insertCleanupCode(ParmList *l, String *cleanup)
1583 *
1584 * Checks each of the parameters in the parameter list for a "freearg"
1585 * typemap and (if it finds one) inserts the typemapping code into
1586 * the function wrapper.
1587 * --------------------------------------------------------------------- */
1588
insertCleanupCode(ParmList * l,String * cleanup)1589 void insertCleanupCode(ParmList *l, String *cleanup) {
1590 String *tm;
1591 for (Parm *p = l; p;) {
1592 if ((tm = Getattr(p, "tmap:freearg"))) {
1593 if (Len(tm) != 0) {
1594 Replaceall(tm, "$source", Getattr(p, "lname"));
1595 Printv(cleanup, tm, "\n", NIL);
1596 }
1597 p = Getattr(p, "tmap:freearg:next");
1598 } else {
1599 p = nextSibling(p);
1600 }
1601 }
1602 }
1603
1604 /* ---------------------------------------------------------------------
1605 * insertArgOutputCode(ParmList *l, String *outarg, int& need_result)
1606 *
1607 * Checks each of the parameters in the parameter list for a "argout"
1608 * typemap and (if it finds one) inserts the typemapping code into
1609 * the function wrapper.
1610 * --------------------------------------------------------------------- */
1611
insertArgOutputCode(ParmList * l,String * outarg,int & need_result)1612 void insertArgOutputCode(ParmList *l, String *outarg, int &need_result) {
1613 String *tm;
1614 for (Parm *p = l; p;) {
1615 if ((tm = Getattr(p, "tmap:argout"))) {
1616 Replaceall(tm, "$source", Getattr(p, "lname"));
1617 Replaceall(tm, "$target", "vresult");
1618 Replaceall(tm, "$result", "vresult");
1619 Replaceall(tm, "$arg", Getattr(p, "emit:input"));
1620 Replaceall(tm, "$input", Getattr(p, "emit:input"));
1621
1622 Printv(outarg, tm, "\n", NIL);
1623 need_result += 1;
1624 p = Getattr(p, "tmap:argout:next");
1625 } else {
1626 p = nextSibling(p);
1627 }
1628 }
1629 }
1630
1631 /* ---------------------------------------------------------------------
1632 * validIdentifier()
1633 *
1634 * Is this a valid identifier in the scripting language?
1635 * Ruby method names can include any combination of letters, numbers
1636 * and underscores. A Ruby method name may optionally end with
1637 * a question mark ("?"), exclamation point ("!") or equals sign ("=").
1638 *
1639 * Methods whose names end with question marks are, by convention,
1640 * predicate methods that return true or false (e.g. Array#empty?).
1641 *
1642 * Methods whose names end with exclamation points are, by convention,
1643 * called bang methods that modify the instance in place (e.g. Array#sort!).
1644 *
1645 * Methods whose names end with an equals sign are attribute setters
1646 * (e.g. Thread#critical=).
1647 * --------------------------------------------------------------------- */
1648
validIdentifier(String * s)1649 virtual int validIdentifier(String *s) {
1650 char *c = Char(s);
1651 while (*c) {
1652 if (!(isalnum(*c) || (*c == '_') || (*c == '?') || (*c == '!') || (*c == '=')))
1653 return 0;
1654 c++;
1655 }
1656 return 1;
1657 }
1658
1659 /* ---------------------------------------------------------------------
1660 * functionWrapper()
1661 *
1662 * Create a function declaration and register it with the interpreter.
1663 * --------------------------------------------------------------------- */
1664
functionWrapper(Node * n)1665 virtual int functionWrapper(Node *n) {
1666
1667 String *nodeType;
1668 bool destructor;
1669
1670 String *symname = Copy(Getattr(n, "sym:name"));
1671 SwigType *t = Getattr(n, "type");
1672 ParmList *l = Getattr(n, "parms");
1673 int director_method = 0;
1674 String *tm;
1675
1676 int need_result = 0;
1677
1678 /* Ruby needs no destructor wrapper */
1679 if (current == DESTRUCTOR)
1680 return SWIG_NOWRAP;
1681
1682 nodeType = Getattr(n, "nodeType");
1683 destructor = (!Cmp(nodeType, "destructor"));
1684
1685 /* If the C++ class constructor is overloaded, we only want to
1686 * write out the "new" singleton method once since it is always
1687 * the same. (It's the "initialize" method that will handle the
1688 * overloading). */
1689
1690 if (current == CONSTRUCTOR_ALLOCATE && Swig_symbol_isoverloaded(n) && Getattr(n, "sym:nextSibling") != 0)
1691 return SWIG_OK;
1692
1693 String *overname = 0;
1694 if (Getattr(n, "sym:overloaded")) {
1695 overname = Getattr(n, "sym:overname");
1696 } else {
1697 if (!addSymbol(symname, n))
1698 return SWIG_ERROR;
1699 }
1700
1701 String *cleanup = NewString("");
1702 String *outarg = NewString("");
1703 String *kwargs = NewString("");
1704 Wrapper *f = NewWrapper();
1705
1706 /* Rename predicate methods */
1707 if (GetFlag(n, "feature:predicate")) {
1708 Append(symname, "?");
1709 }
1710
1711 /* Rename bang methods */
1712 if (GetFlag(n, "feature:bang")) {
1713 Append(symname, "!");
1714 }
1715
1716 /* Determine the name of the SWIG wrapper function */
1717 String *wname = Swig_name_wrapper(symname);
1718 if (overname && current != CONSTRUCTOR_ALLOCATE) {
1719 Append(wname, overname);
1720 }
1721
1722 /* Emit arguments */
1723 if (current != CONSTRUCTOR_ALLOCATE) {
1724 emit_parameter_variables(l, f);
1725 }
1726
1727 /* Attach standard typemaps */
1728 if (current != CONSTRUCTOR_ALLOCATE) {
1729 emit_attach_parmmaps(l, f);
1730 }
1731 Setattr(n, "wrap:parms", l);
1732
1733 /* Get number of arguments */
1734 int numarg = emit_num_arguments(l);
1735 int numreq = emit_num_required(l);
1736 int varargs = emit_isvarargs(l);
1737 bool allow_kwargs = GetFlag(n, "feature:kwargs") ? true : false;
1738
1739 bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
1740 int start = (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) ? 1 : 0;
1741
1742 /* Now write the wrapper function itself */
1743 if (current == CONSTRUCTOR_ALLOCATE) {
1744 Printv(f->def, "SWIGINTERN VALUE\n", NIL);
1745 Printf(f->def, "#ifdef HAVE_RB_DEFINE_ALLOC_FUNC\n");
1746 Printv(f->def, wname, "(VALUE self)\n", NIL);
1747 Printf(f->def, "#else\n");
1748 Printv(f->def, wname, "(int argc, VALUE *argv, VALUE self)\n", NIL);
1749 Printf(f->def, "#endif\n");
1750 Printv(f->def, "{\n", NIL);
1751 } else if (current == CONSTRUCTOR_INITIALIZE) {
1752 Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL);
1753 if (!varargs) {
1754 Printf(f->code, "if ((argc < %d) || (argc > %d)) ", numreq - start, numarg - start);
1755 } else {
1756 Printf(f->code, "if (argc < %d) ", numreq - start);
1757 }
1758 Printf(f->code, "{rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc); SWIG_fail;}\n", numreq - start);
1759 } else {
1760
1761 if ( current == NO_CPP )
1762 {
1763 String* docs = docstring(n, AUTODOC_FUNC);
1764 Printf(f_wrappers, "%s", docs);
1765 Delete(docs);
1766 }
1767
1768 Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL);
1769 if (!varargs) {
1770 Printf(f->code, "if ((argc < %d) || (argc > %d)) ", numreq - start, numarg - start);
1771 } else {
1772 Printf(f->code, "if (argc < %d) ", numreq - start);
1773 }
1774 Printf(f->code, "{rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc); SWIG_fail;}\n", numreq - start);
1775 }
1776
1777 /* Now walk the function parameter list and generate code */
1778 /* to get arguments */
1779 if (current != CONSTRUCTOR_ALLOCATE) {
1780 marshalInputArgs(n, l, numarg, numreq, kwargs, allow_kwargs, f);
1781 }
1782 // FIXME?
1783 if (ctor_director) {
1784 numarg--;
1785 numreq--;
1786 }
1787
1788 /* Insert constraint checking code */
1789 insertConstraintCheckingCode(l, f);
1790
1791 /* Insert cleanup code */
1792 insertCleanupCode(l, cleanup);
1793
1794 /* Insert argument output code */
1795 insertArgOutputCode(l, outarg, need_result);
1796
1797 /* if the object is a director, and the method call originated from its
1798 * underlying Ruby object, resolve the call by going up the c++
1799 * inheritance chain. otherwise try to resolve the method in Ruby.
1800 * without this check an infinite loop is set up between the director and
1801 * shadow class method calls.
1802 */
1803
1804 // NOTE: this code should only be inserted if this class is the
1805 // base class of a director class. however, in general we haven't
1806 // yet analyzed all classes derived from this one to see if they are
1807 // directors. furthermore, this class may be used as the base of
1808 // a director class defined in a completely different module at a
1809 // later time, so this test must be included whether or not directorbase
1810 // is true. we do skip this code if directors have not been enabled
1811 // at the command line to preserve source-level compatibility with
1812 // non-polymorphic swig. also, if this wrapper is for a smart-pointer
1813 // method, there is no need to perform the test since the calling object
1814 // (the smart-pointer) and the director object (the "pointee") are
1815 // distinct.
1816
1817 director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
1818 if (director_method) {
1819 Wrapper_add_local(f, "director", "Swig::Director *director = 0");
1820 Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
1821 Wrapper_add_local(f, "upcall", "bool upcall = false");
1822 Append(f->code, "upcall = (director && (director->swig_get_self() == self));\n");
1823 }
1824
1825 /* Now write code to make the function call */
1826 if (current != CONSTRUCTOR_ALLOCATE) {
1827 if (current == CONSTRUCTOR_INITIALIZE) {
1828 Node *pn = Swig_methodclass(n);
1829 String *symname = Getattr(pn, "sym:name");
1830 String *action = Getattr(n, "wrap:action");
1831 if (directorsEnabled()) {
1832 String *classname = NewStringf("const char *classname SWIGUNUSED = \"%s::%s\"", module, symname);
1833 Wrapper_add_local(f, "classname", classname);
1834 }
1835 if (action) {
1836 SwigType *smart = Swig_cparse_smartptr(pn);
1837 String *result_name = NewStringf("%s%s", smart ? "smart" : "", Swig_cresult_name());
1838 if (smart) {
1839 String *result_var = NewStringf("%s *%s = 0", SwigType_namestr(smart), result_name);
1840 Wrapper_add_local(f, result_name, result_var);
1841 Printf(action, "\n%s = new %s(%s);", result_name, SwigType_namestr(smart), Swig_cresult_name());
1842 }
1843 Printf(action, "\nDATA_PTR(self) = %s;", result_name);
1844 if (GetFlag(pn, "feature:trackobjects")) {
1845 Printf(action, "\nSWIG_RubyAddTracking(%s, self);", result_name);
1846 }
1847 Delete(result_name);
1848 Delete(smart);
1849 }
1850 }
1851
1852 /* Emit the function call */
1853 if (director_method) {
1854 Printf(f->code, "try {\n");
1855 }
1856
1857 Setattr(n, "wrap:name", wname);
1858
1859 Swig_director_emit_dynamic_cast(n, f);
1860 String *actioncode = emit_action(n);
1861
1862 if (director_method) {
1863 Printf(actioncode, "} catch (Swig::DirectorException& e) {\n");
1864 Printf(actioncode, " rb_exc_raise(e.getError());\n");
1865 Printf(actioncode, " SWIG_fail;\n");
1866 Printf(actioncode, "}\n");
1867 }
1868
1869 /* Return value if necessary */
1870 if (SwigType_type(t) != T_VOID && current != CONSTRUCTOR_INITIALIZE) {
1871 need_result = 1;
1872 if (GetFlag(n, "feature:predicate")) {
1873 Printv(actioncode, tab4, "vresult = (", Swig_cresult_name(), " ? Qtrue : Qfalse);\n", NIL);
1874 } else {
1875 tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode);
1876 actioncode = 0;
1877 if (tm) {
1878 Replaceall(tm, "$result", "vresult");
1879 Replaceall(tm, "$source", Swig_cresult_name());
1880 Replaceall(tm, "$target", "vresult");
1881
1882 if (GetFlag(n, "feature:new"))
1883 Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
1884 else
1885 Replaceall(tm, "$owner", "0");
1886
1887 #if 1
1888 // FIXME: this will not try to unwrap directors returned as non-director
1889 // base class pointers!
1890
1891 /* New addition to unwrap director return values so that the original
1892 * Ruby object is returned instead.
1893 */
1894 bool unwrap = false;
1895 String *decl = Getattr(n, "decl");
1896 int is_pointer = SwigType_ispointer_return(decl);
1897 int is_reference = SwigType_isreference_return(decl);
1898 if (is_pointer || is_reference) {
1899 String *type = Getattr(n, "type");
1900 Node *parent = Swig_methodclass(n);
1901 Node *modname = Getattr(parent, "module");
1902 Node *target = Swig_directormap(modname, type);
1903 if (target)
1904 unwrap = true;
1905 }
1906 if (unwrap) {
1907 Wrapper_add_local(f, "director", "Swig::Director *director = 0");
1908 Printf(f->code, "director = dynamic_cast<Swig::Director *>(%s);\n", Swig_cresult_name());
1909 Printf(f->code, "if (director) {\n");
1910 Printf(f->code, " vresult = director->swig_get_self();\n");
1911 Printf(f->code, "} else {\n");
1912 Printf(f->code, "%s\n", tm);
1913 Printf(f->code, "}\n");
1914 director_method = 0;
1915 } else {
1916 Printf(f->code, "%s\n", tm);
1917 }
1918 #else
1919 Printf(f->code, "%s\n", tm);
1920 #endif
1921 Delete(tm);
1922 } else {
1923 Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s.\n", SwigType_str(t, 0));
1924 }
1925 }
1926 }
1927 if (actioncode) {
1928 Append(f->code, actioncode);
1929 Delete(actioncode);
1930 }
1931 emit_return_variable(n, t, f);
1932 }
1933
1934 /* Extra code needed for new and initialize methods */
1935 if (current == CONSTRUCTOR_ALLOCATE) {
1936 Node *pn = Swig_methodclass(n);
1937 SwigType *smart = Swig_cparse_smartptr(pn);
1938 if (smart)
1939 SwigType_add_pointer(smart);
1940 String *classtype = smart ? smart : t;
1941 need_result = 1;
1942 Printf(f->code, "VALUE vresult = SWIG_NewClassInstance(self, SWIGTYPE%s);\n", Char(SwigType_manglestr(classtype)));
1943 Printf(f->code, "#ifndef HAVE_RB_DEFINE_ALLOC_FUNC\n");
1944 Printf(f->code, "rb_obj_call_init(vresult, argc, argv);\n");
1945 Printf(f->code, "#endif\n");
1946 Delete(smart);
1947 } else if (current == CONSTRUCTOR_INITIALIZE) {
1948 need_result = 1;
1949 }
1950 else
1951 {
1952 if ( need_result > 1 ) {
1953 if ( SwigType_type(t) == T_VOID )
1954 Printf(f->code, "vresult = rb_ary_new();\n");
1955 else
1956 {
1957 Printf(f->code, "if (vresult == Qnil) vresult = rb_ary_new();\n");
1958 Printf(f->code, "else vresult = SWIG_Ruby_AppendOutput( "
1959 "rb_ary_new(), vresult);\n");
1960 }
1961 }
1962 }
1963
1964 /* Dump argument output code; */
1965 Printv(f->code, outarg, NIL);
1966
1967 /* Dump the argument cleanup code */
1968 int need_cleanup = (current != CONSTRUCTOR_ALLOCATE) && (Len(cleanup) != 0);
1969 if (need_cleanup) {
1970 Printv(f->code, cleanup, NIL);
1971 }
1972
1973
1974 /* Look for any remaining cleanup. This processes the %new directive */
1975 if (current != CONSTRUCTOR_ALLOCATE && GetFlag(n, "feature:new")) {
1976 tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
1977 if (tm) {
1978 Replaceall(tm, "$source", Swig_cresult_name());
1979 Printv(f->code, tm, "\n", NIL);
1980 Delete(tm);
1981 }
1982 }
1983
1984 /* Special processing on return value. */
1985 tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0);
1986 if (tm) {
1987 Replaceall(tm, "$source", Swig_cresult_name());
1988 Printv(f->code, tm, NIL);
1989 Delete(tm);
1990 }
1991
1992 if (director_method) {
1993 if ((tm = Swig_typemap_lookup("directorfree", n, Swig_cresult_name(), 0))) {
1994 Replaceall(tm, "$input", Swig_cresult_name());
1995 Replaceall(tm, "$result", "vresult");
1996 Printf(f->code, "%s\n", tm);
1997 }
1998 }
1999
2000
2001 /* Wrap things up (in a manner of speaking) */
2002 if (need_result) {
2003 if (current == CONSTRUCTOR_ALLOCATE) {
2004 Printv(f->code, tab4, "return vresult;\n", NIL);
2005 } else if (current == CONSTRUCTOR_INITIALIZE) {
2006 Printv(f->code, tab4, "return self;\n", NIL);
2007 Printv(f->code, "fail:\n", NIL);
2008 if (need_cleanup) {
2009 Printv(f->code, cleanup, NIL);
2010 }
2011 Printv(f->code, tab4, "return Qnil;\n", NIL);
2012 } else {
2013 Wrapper_add_local(f, "vresult", "VALUE vresult = Qnil");
2014 Printv(f->code, tab4, "return vresult;\n", NIL);
2015 Printv(f->code, "fail:\n", NIL);
2016 if (need_cleanup) {
2017 Printv(f->code, cleanup, NIL);
2018 }
2019 Printv(f->code, tab4, "return Qnil;\n", NIL);
2020 }
2021 } else {
2022 Printv(f->code, tab4, "return Qnil;\n", NIL);
2023 Printv(f->code, "fail:\n", NIL);
2024 if (need_cleanup) {
2025 Printv(f->code, cleanup, NIL);
2026 }
2027 Printv(f->code, tab4, "return Qnil;\n", NIL);
2028 }
2029
2030 Printf(f->code, "}\n");
2031
2032 /* Substitute the cleanup code */
2033 Replaceall(f->code, "$cleanup", cleanup);
2034
2035 /* Substitute the function name */
2036 Replaceall(f->code, "$symname", symname);
2037
2038 /* Emit the function */
2039 Wrapper_print(f, f_wrappers);
2040
2041 /* Now register the function with the interpreter */
2042 if (!Swig_symbol_isoverloaded(n)) {
2043 create_command(n, symname);
2044 } else {
2045 if (current == CONSTRUCTOR_ALLOCATE) {
2046 create_command(n, symname);
2047 } else {
2048 if (!Getattr(n, "sym:nextSibling"))
2049 dispatchFunction(n);
2050 }
2051 }
2052
2053 Delete(kwargs);
2054 Delete(cleanup);
2055 Delete(outarg);
2056 DelWrapper(f);
2057 Delete(symname);
2058
2059 return SWIG_OK;
2060 }
2061
2062 /* ------------------------------------------------------------
2063 * dispatchFunction()
2064 * ------------------------------------------------------------ */
2065
dispatchFunction(Node * n)2066 void dispatchFunction(Node *n) {
2067 /* Last node in overloaded chain */
2068
2069 int maxargs;
2070 String *tmp = NewString("");
2071 String *dispatch = Swig_overload_dispatch(n, "return %s(nargs, args, self);", &maxargs);
2072
2073 /* Generate a dispatch wrapper for all overloaded functions */
2074
2075 Wrapper *f = NewWrapper();
2076 String *symname = Getattr(n, "sym:name");
2077 String *wname = Swig_name_wrapper(symname);
2078
2079 Printv(f->def, "SWIGINTERN VALUE ", wname, "(int nargs, VALUE *args, VALUE self) {", NIL);
2080
2081 Wrapper_add_local(f, "argc", "int argc");
2082 bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
2083 if (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) {
2084 Printf(tmp, "VALUE argv[%d]", maxargs + 1);
2085 } else {
2086 Printf(tmp, "VALUE argv[%d]", maxargs);
2087 }
2088 Wrapper_add_local(f, "argv", tmp);
2089 Wrapper_add_local(f, "ii", "int ii");
2090
2091 if (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) {
2092 maxargs += 1;
2093 Printf(f->code, "argc = nargs + 1;\n");
2094 Printf(f->code, "argv[0] = self;\n");
2095 Printf(f->code, "if (argc > %d) SWIG_fail;\n", maxargs);
2096 Printf(f->code, "for (ii = 1; (ii < argc); ++ii) {\n");
2097 Printf(f->code, "argv[ii] = args[ii-1];\n");
2098 Printf(f->code, "}\n");
2099 } else {
2100 Printf(f->code, "argc = nargs;\n");
2101 Printf(f->code, "if (argc > %d) SWIG_fail;\n", maxargs);
2102 Printf(f->code, "for (ii = 0; (ii < argc); ++ii) {\n");
2103 Printf(f->code, "argv[ii] = args[ii];\n");
2104 Printf(f->code, "}\n");
2105 }
2106
2107 Replaceall(dispatch, "$args", "nargs, args, self");
2108 Printv(f->code, dispatch, "\n", NIL);
2109
2110
2111
2112 // Generate prototype list, go to first node
2113 Node *sibl = n;
2114
2115 while (Getattr(sibl, "sym:previousSibling"))
2116 sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
2117
2118 // Constructors will be treated specially
2119 const bool isCtor = (!Cmp(Getattr(sibl, "nodeType"), "constructor"));
2120 const bool isMethod = ( Cmp(Getattr(sibl, "ismember"), "1") == 0 &&
2121 (!isCtor) );
2122
2123 // Construct real method name
2124 String* methodName = NewString("");
2125 if ( isMethod ) {
2126 // Sometimes a method node has no parent (SF#3034054).
2127 // This value is used in an exception message, so just skip the class
2128 // name in this case so at least we don't segfault. This is probably
2129 // just working around a problem elsewhere though.
2130 Node *parent_node = parentNode(sibl);
2131 if (parent_node)
2132 Printv( methodName, Getattr(parent_node,"sym:name"), ".", NIL );
2133 }
2134 Append( methodName, Getattr(sibl,"sym:name" ) );
2135 if ( isCtor ) Append( methodName, ".new" );
2136
2137 // Generate prototype list
2138 String *protoTypes = NewString("");
2139 do {
2140 Append( protoTypes, "\n\" ");
2141 if (!isCtor) {
2142 SwigType *type = SwigType_str(Getattr(sibl, "type"), NULL);
2143 Printv(protoTypes, type, " ", NIL);
2144 Delete(type);
2145 }
2146 Printv(protoTypes, methodName, NIL );
2147 Parm* p = Getattr(sibl, "wrap:parms");
2148 if (p && (current == MEMBER_FUNC || current == MEMBER_VAR ||
2149 ctor_director) )
2150 p = nextSibling(p); // skip self
2151 Append( protoTypes, "(" );
2152 while(p)
2153 {
2154 Append( protoTypes, SwigType_str(Getattr(p,"type"), Getattr(p,"name")) );
2155 if ( ( p = nextSibling(p)) ) Append(protoTypes, ", ");
2156 }
2157 Append( protoTypes, ")\\n\"" );
2158 } while ((sibl = Getattr(sibl, "sym:nextSibling")));
2159
2160 Append(f->code, "fail:\n");
2161 Printf(f->code, "Ruby_Format_OverloadedError( argc, %d, \"%s\", %s);\n",
2162 maxargs, methodName, protoTypes);
2163 Append(f->code, "\nreturn Qnil;\n");
2164
2165 Delete(methodName);
2166 Delete(protoTypes);
2167
2168 Printv(f->code, "}\n", NIL);
2169 Wrapper_print(f, f_wrappers);
2170 create_command(n, Char(symname));
2171
2172 DelWrapper(f);
2173 Delete(dispatch);
2174 Delete(tmp);
2175 Delete(wname);
2176 }
2177
2178 /* ---------------------------------------------------------------------
2179 * variableWrapper()
2180 * --------------------------------------------------------------------- */
2181
variableWrapper(Node * n)2182 virtual int variableWrapper(Node *n) {
2183 String* docs = docstring(n, AUTODOC_GETTER);
2184 Printf(f_wrappers, "%s", docs);
2185 Delete(docs);
2186
2187
2188 char *name = GetChar(n, "name");
2189 char *iname = GetChar(n, "sym:name");
2190 SwigType *t = Getattr(n, "type");
2191 String *tm;
2192 String *getfname, *setfname;
2193 Wrapper *getf, *setf;
2194 const int assignable = is_assignable(n);
2195
2196 // Determine whether virtual global variables shall be used
2197 // which have different getter and setter signatures,
2198 // see https://docs.ruby-lang.org/en/2.6.0/extension_rdoc.html#label-Global+Variables+Shared+Between+C+and+Ruby
2199 const bool use_virtual_var = (current == NO_CPP && useGlobalModule);
2200
2201 getf = NewWrapper();
2202 setf = NewWrapper();
2203
2204 /* create getter */
2205 int addfail = 0;
2206 String *getname = Swig_name_get(NSPACE_TODO, iname);
2207 getfname = Swig_name_wrapper(getname);
2208 Setattr(n, "wrap:name", getfname);
2209 Printv(getf->def, "SWIGINTERN VALUE\n", getfname, "(", NIL);
2210 Printf(getf->def, (use_virtual_var) ? "ID id, VALUE *data" : "VALUE self");
2211 Printf(getf->def, ") {");
2212 Wrapper_add_local(getf, "_val", "VALUE _val");
2213
2214 tm = Swig_typemap_lookup("varout", n, name, 0);
2215 if (tm) {
2216 Replaceall(tm, "$result", "_val");
2217 Replaceall(tm, "$target", "_val");
2218 Replaceall(tm, "$source", name);
2219 /* Printv(getf->code,tm, NIL); */
2220 addfail = emit_action_code(n, getf->code, tm);
2221 } else {
2222 Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
2223 }
2224 Printv(getf->code, tab4, "return _val;\n", NIL);
2225 if (addfail) {
2226 Append(getf->code, "fail:\n");
2227 Append(getf->code, " return Qnil;\n");
2228 }
2229 Append(getf->code, "}\n");
2230
2231 Wrapper_print(getf, f_wrappers);
2232
2233 if (!assignable) {
2234 setfname = NewString("(rb_gvar_setter_t *)NULL");
2235 } else {
2236 /* create setter */
2237 String* docs = docstring(n, AUTODOC_SETTER);
2238 Printf(f_wrappers, "%s", docs);
2239 Delete(docs);
2240
2241 String *setname = Swig_name_set(NSPACE_TODO, iname);
2242 setfname = Swig_name_wrapper(setname);
2243 Setattr(n, "wrap:name", setfname);
2244 Printf(setf->def, "SWIGINTERN ");
2245 if (use_virtual_var) {
2246 Printv(setf->def, "void\n", setfname, "(VALUE _val, ID id, VALUE *data) {", NIL);
2247 } else {
2248 Printv(setf->def, "VALUE\n", setfname, "(VALUE self, VALUE _val) {", NIL);
2249 }
2250 tm = Swig_typemap_lookup("varin", n, name, 0);
2251 if (tm) {
2252 Replaceall(tm, "$input", "_val");
2253 Replaceall(tm, "$source", "_val");
2254 Replaceall(tm, "$target", name);
2255 /* Printv(setf->code,tm,"\n",NIL); */
2256 emit_action_code(n, setf->code, tm);
2257 } else {
2258 Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s\n", SwigType_str(t, 0));
2259 }
2260 if (use_virtual_var) {
2261 Printf(setf->code, "fail:\n");
2262 Printv(setf->code, tab4, "return;\n", NIL);
2263 } else {
2264 Printv(setf->code, tab4, "return _val;\n", NIL);
2265 Printf(setf->code, "fail:\n");
2266 Printv(setf->code, tab4, "return Qnil;\n", NIL);
2267 }
2268 Printf(setf->code, "}\n");
2269 Wrapper_print(setf, f_wrappers);
2270 Delete(setname);
2271 }
2272
2273 /* define accessor methods */
2274 Insert(getfname, 0, "VALUEFUNC(");
2275 Append(getfname, ")");
2276 Insert(setfname, 0, (use_virtual_var) ? "SWIG_RUBY_VOID_ANYARGS_FUNC(" : "VALUEFUNC(");
2277 Append(setfname, ")");
2278
2279 String *s = NewString("");
2280 switch (current) {
2281 case STATIC_VAR:
2282 /* C++ class variable */
2283 Printv(s, tab4, "rb_define_singleton_method(", klass->vname, ", \"", klass->strip(iname), "\", ", getfname, ", 0);\n", NIL);
2284 if (assignable) {
2285 Printv(s, tab4, "rb_define_singleton_method(", klass->vname, ", \"", klass->strip(iname), "=\", ", setfname, ", 1);\n", NIL);
2286 }
2287 Printv(klass->init, s, NIL);
2288 break;
2289 default:
2290 /* C global variable */
2291 /* wrapped in Ruby module attribute */
2292 assert(current == NO_CPP);
2293 if (!useGlobalModule) {
2294 Printv(s, tab4, "rb_define_singleton_method(", modvar, ", \"", iname, "\", ", getfname, ", 0);\n", NIL);
2295 if (assignable) {
2296 Printv(s, tab4, "rb_define_singleton_method(", modvar, ", \"", iname, "=\", ", setfname, ", 1);\n", NIL);
2297 }
2298 } else {
2299 Printv(s, tab4, "rb_define_virtual_variable(\"$", iname, "\", ", getfname, ", ", setfname, ");\n", NIL);
2300 }
2301 Printv(f_init, s, NIL);
2302 Delete(s);
2303 break;
2304 }
2305 Delete(getname);
2306 Delete(getfname);
2307 Delete(setfname);
2308 DelWrapper(setf);
2309 DelWrapper(getf);
2310 return SWIG_OK;
2311 }
2312
2313
2314 /* ---------------------------------------------------------------------
2315 * validate_const_name(char *name)
2316 *
2317 * Validate constant name.
2318 * --------------------------------------------------------------------- */
2319
validate_const_name(char * name,const char * reason)2320 char *validate_const_name(char *name, const char *reason) {
2321 if (!name || name[0] == '\0')
2322 return name;
2323
2324 if (isupper(name[0]))
2325 return name;
2326
2327 if (islower(name[0])) {
2328 name[0] = (char)toupper(name[0]);
2329 Swig_warning(WARN_RUBY_WRONG_NAME, input_file, line_number, "Wrong %s name (corrected to `%s')\n", reason, name);
2330 return name;
2331 }
2332
2333 Swig_warning(WARN_RUBY_WRONG_NAME, input_file, line_number, "Wrong %s name %s\n", reason, name);
2334
2335 return name;
2336 }
2337
2338 /* ---------------------------------------------------------------------
2339 * constantWrapper()
2340 * --------------------------------------------------------------------- */
2341
constantWrapper(Node * n)2342 virtual int constantWrapper(Node *n) {
2343 Swig_require("constantWrapper", n, "*sym:name", "type", "value", NIL);
2344
2345 char *iname = GetChar(n, "sym:name");
2346 SwigType *type = Getattr(n, "type");
2347 String *rawval = Getattr(n, "rawval");
2348 String *value = rawval ? rawval : Getattr(n, "value");
2349
2350 if (current == CLASS_CONST) {
2351 iname = klass->strip(iname);
2352 }
2353 validate_const_name(iname, "constant");
2354 SetChar(n, "sym:name", iname);
2355
2356 /* Special hook for member pointer */
2357 if (SwigType_type(type) == T_MPOINTER) {
2358 String *wname = Swig_name_wrapper(iname);
2359 Printf(f_header, "static %s = %s;\n", SwigType_str(type, wname), value);
2360 value = Char(wname);
2361 }
2362 String *tm = Swig_typemap_lookup("constant", n, value, 0);
2363 if (!tm)
2364 tm = Swig_typemap_lookup("constcode", n, value, 0);
2365 if (tm) {
2366 Replaceall(tm, "$source", value);
2367 Replaceall(tm, "$target", iname);
2368 Replaceall(tm, "$symname", iname);
2369 Replaceall(tm, "$value", value);
2370 if (current == CLASS_CONST) {
2371 if (multipleInheritance) {
2372 Replaceall(tm, "$module", klass->mImpl);
2373 Printv(klass->init, tm, "\n", NIL);
2374 } else {
2375 Replaceall(tm, "$module", klass->vname);
2376 Printv(klass->init, tm, "\n", NIL);
2377 }
2378 } else {
2379 if (!useGlobalModule) {
2380 Replaceall(tm, "$module", modvar);
2381 } else {
2382 Replaceall(tm, "$module", "rb_cObject");
2383 }
2384 Printf(f_init, "%s\n", tm);
2385 }
2386 } else {
2387 Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value %s = %s\n", SwigType_str(type, 0), value);
2388 }
2389 Swig_restore(n);
2390 return SWIG_OK;
2391 }
2392
2393 /* -----------------------------------------------------------------------------
2394 * classDeclaration()
2395 *
2396 * Records information about classes---even classes that might be defined in
2397 * other modules referenced by %import.
2398 * ----------------------------------------------------------------------------- */
2399
classDeclaration(Node * n)2400 virtual int classDeclaration(Node *n) {
2401 if (!Getattr(n, "feature:onlychildren")) {
2402 String *name = Getattr(n, "name");
2403 String *symname = Getattr(n, "sym:name");
2404
2405 String *namestr = SwigType_namestr(name);
2406 klass = RCLASS(classes, Char(namestr));
2407 if (!klass) {
2408 klass = new RClass();
2409 String *valid_name = NewString(symname ? symname : namestr);
2410 validate_const_name(Char(valid_name), "class");
2411 klass->set_name(namestr, symname, valid_name);
2412 SET_RCLASS(classes, Char(namestr), klass);
2413 Delete(valid_name);
2414 }
2415 Delete(namestr);
2416 }
2417 return Language::classDeclaration(n);
2418 }
2419
2420 /**
2421 * Process the comma-separated list of mixed-in module names (if any).
2422 */
includeRubyModules(Node * n)2423 void includeRubyModules(Node *n) {
2424 String *mixin = Getattr(n, "feature:mixin");
2425 if (mixin) {
2426 List *modules = Split(mixin, ',', INT_MAX);
2427 if (modules && Len(modules) > 0) {
2428 Iterator mod = First(modules);
2429 while (mod.item) {
2430 if (Len(mod.item) > 0) {
2431 Printf(klass->init, "rb_include_module(%s, rb_eval_string(\"%s\"));\n", klass->vname, mod.item);
2432 }
2433 mod = Next(mod);
2434 }
2435 }
2436 Delete(modules);
2437 }
2438 }
2439
handleBaseClasses(Node * n)2440 void handleBaseClasses(Node *n) {
2441 List *baselist = Getattr(n, "bases");
2442 if (baselist && Len(baselist)) {
2443 Iterator base = First(baselist);
2444 while (base.item && GetFlag(base.item, "feature:ignore")) {
2445 base = Next(base);
2446 }
2447 while (base.item) {
2448 String *basename = Getattr(base.item, "name");
2449 String *basenamestr = SwigType_namestr(basename);
2450 RClass *super = RCLASS(classes, Char(basenamestr));
2451 Delete(basenamestr);
2452 if (super) {
2453 SwigType *btype = NewString(basename);
2454 SwigType_add_pointer(btype);
2455 SwigType_remember(btype);
2456 SwigType *smart = Swig_cparse_smartptr(base.item);
2457 if (smart) {
2458 SwigType_add_pointer(smart);
2459 SwigType_remember(smart);
2460 }
2461 String *bmangle = SwigType_manglestr(smart ? smart : btype);
2462 if (multipleInheritance) {
2463 Insert(bmangle, 0, "((swig_class *) SWIGTYPE");
2464 Append(bmangle, "->clientdata)->mImpl");
2465 Printv(klass->init, "rb_include_module(", klass->mImpl, ", ", bmangle, ");\n", NIL);
2466 } else {
2467 Insert(bmangle, 0, "((swig_class *) SWIGTYPE");
2468 Append(bmangle, "->clientdata)->klass");
2469 Replaceall(klass->init, "$super", bmangle);
2470 }
2471 Delete(bmangle);
2472 Delete(smart);
2473 Delete(btype);
2474 }
2475 base = Next(base);
2476 while (base.item && GetFlag(base.item, "feature:ignore")) {
2477 base = Next(base);
2478 }
2479 if (!multipleInheritance) {
2480 /* Warn about multiple inheritance for additional base class(es) */
2481 while (base.item) {
2482 if (GetFlag(base.item, "feature:ignore")) {
2483 base = Next(base);
2484 continue;
2485 }
2486 String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
2487 String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
2488 Swig_warning(WARN_RUBY_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
2489 "Warning for %s, base %s ignored. Multiple inheritance is not supported in Ruby.\n", proxyclassname, baseclassname);
2490 base = Next(base);
2491 }
2492 }
2493 }
2494 }
2495 }
2496
2497 /**
2498 * Check to see if a %markfunc was specified.
2499 */
handleMarkFuncDirective(Node * n)2500 void handleMarkFuncDirective(Node *n) {
2501 String *markfunc = Getattr(n, "feature:markfunc");
2502 if (markfunc) {
2503 Printf(klass->init, "SwigClass%s.mark = (void (*)(void *)) %s;\n", klass->name, markfunc);
2504 } else {
2505 Printf(klass->init, "SwigClass%s.mark = 0;\n", klass->name);
2506 }
2507 }
2508
2509 /**
2510 * Check to see if a %freefunc was specified.
2511 */
handleFreeFuncDirective(Node * n)2512 void handleFreeFuncDirective(Node *n) {
2513 String *freefunc = Getattr(n, "feature:freefunc");
2514 if (freefunc) {
2515 Printf(klass->init, "SwigClass%s.destroy = (void (*)(void *)) %s;\n", klass->name, freefunc);
2516 } else {
2517 if (klass->destructor_defined) {
2518 Printf(klass->init, "SwigClass%s.destroy = (void (*)(void *)) free_%s;\n", klass->name, klass->mname);
2519 }
2520 }
2521 }
2522
2523 /**
2524 * Check to see if tracking is enabled for this class.
2525 */
handleTrackDirective(Node * n)2526 void handleTrackDirective(Node *n) {
2527 int trackObjects = GetFlag(n, "feature:trackobjects");
2528 if (trackObjects) {
2529 Printf(klass->init, "SwigClass%s.trackObjects = 1;\n", klass->name);
2530 } else {
2531 Printf(klass->init, "SwigClass%s.trackObjects = 0;\n", klass->name);
2532 }
2533 }
2534
2535 /* ----------------------------------------------------------------------
2536 * classHandler()
2537 * ---------------------------------------------------------------------- */
2538
classHandler(Node * n)2539 virtual int classHandler(Node *n) {
2540 String* docs = docstring(n, AUTODOC_CLASS);
2541 Printf(f_wrappers, "%s", docs);
2542 Delete(docs);
2543
2544 String *name = Getattr(n, "name");
2545 String *symname = Getattr(n, "sym:name");
2546 String *namestr = SwigType_namestr(name); // does template expansion
2547
2548 klass = RCLASS(classes, Char(namestr));
2549 assert(klass != 0);
2550 Delete(namestr);
2551 String *valid_name = NewString(symname);
2552 validate_const_name(Char(valid_name), "class");
2553
2554 Clear(klass->type);
2555 Printv(klass->type, Getattr(n, "classtype"), NIL);
2556 Printv(f_wrappers, "static swig_class SwigClass", valid_name, ";\n\n", NIL);
2557 Printv(klass->init, "\n", tab4, NIL);
2558
2559 if (!useGlobalModule) {
2560 Printv(klass->init, klass->vname, " = rb_define_class_under(", modvar, ", \"", klass->name, "\", $super);\n", NIL);
2561 } else {
2562 Printv(klass->init, klass->vname, " = rb_define_class(\"", klass->name,
2563 "\", $super);\n", NIL);
2564 }
2565
2566 if (multipleInheritance) {
2567 Printv(klass->init, klass->mImpl, " = rb_define_module_under(", klass->vname, ", \"Impl\");\n", NIL);
2568 }
2569
2570 SwigType *tt = NewString(name);
2571 SwigType_add_pointer(tt);
2572 SwigType_remember(tt);
2573 SwigType *smart = Swig_cparse_smartptr(n);
2574 if (smart) {
2575 SwigType_add_pointer(smart);
2576 SwigType_remember(smart);
2577 }
2578 String *tm = SwigType_manglestr(smart ? smart : tt);
2579 Printf(klass->init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) &SwigClass%s);\n", tm, valid_name);
2580 Delete(tm);
2581 Delete(smart);
2582 Delete(tt);
2583 Delete(valid_name);
2584
2585 includeRubyModules(n);
2586
2587 Printv(klass->init, "$allocator", NIL);
2588 Printv(klass->init, "$initializer", NIL);
2589
2590 Language::classHandler(n);
2591
2592 handleBaseClasses(n);
2593 handleMarkFuncDirective(n);
2594 handleFreeFuncDirective(n);
2595 handleTrackDirective(n);
2596
2597 if (multipleInheritance) {
2598 Printv(klass->init, "rb_include_module(", klass->vname, ", ", klass->mImpl, ");\n", NIL);
2599 }
2600
2601 String *s = NewString("");
2602 Printv(s, tab4, "rb_undef_alloc_func(", klass->vname, ");\n", NIL);
2603 Replaceall(klass->init, "$allocator", s);
2604 Replaceall(klass->init, "$initializer", "");
2605
2606 if (GetFlag(n, "feature:exceptionclass")) {
2607 Replaceall(klass->init, "$super", "rb_eRuntimeError");
2608 } else {
2609 Replaceall(klass->init, "$super", "rb_cObject");
2610 }
2611 Delete(s);
2612
2613 Printv(f_init, klass->init, NIL);
2614 klass = 0;
2615 return SWIG_OK;
2616 }
2617
2618 /* ----------------------------------------------------------------------
2619 * memberfunctionHandler()
2620 *
2621 * Method for adding C++ member function
2622 *
2623 * By default, we're going to create a function of the form :
2624 *
2625 * Foo_bar(this,args)
2626 *
2627 * Where Foo is the classname, bar is the member name and the this pointer
2628 * is explicitly attached to the beginning.
2629 *
2630 * The renaming only applies to the member function part, not the full
2631 * classname.
2632 *
2633 * --------------------------------------------------------------------- */
2634
memberfunctionHandler(Node * n)2635 virtual int memberfunctionHandler(Node *n) {
2636 current = MEMBER_FUNC;
2637
2638 String* docs = docstring(n, AUTODOC_METHOD);
2639 Printf(f_wrappers, "%s", docs);
2640 Delete(docs);
2641
2642 Language::memberfunctionHandler(n);
2643 current = NO_CPP;
2644 return SWIG_OK;
2645 }
2646
2647 /* ---------------------------------------------------------------------
2648 * constructorHandler()
2649 *
2650 * Method for adding C++ member constructor
2651 * -------------------------------------------------------------------- */
2652
set_director_ctor_code(Node * n)2653 void set_director_ctor_code(Node *n) {
2654 /* director ctor code is specific for each class */
2655 Delete(director_prot_ctor_code);
2656 director_prot_ctor_code = NewString("");
2657 Node *pn = Swig_methodclass(n);
2658 String *symname = Getattr(pn, "sym:name");
2659 String *name = Copy(symname);
2660 char *cname = Char(name);
2661 if (cname)
2662 cname[0] = (char)toupper(cname[0]);
2663 Printv(director_prot_ctor_code,
2664 "if ( $comparison ) { /* subclassed */\n",
2665 " $director_new \n",
2666 "} else {\n", " rb_raise(rb_eNameError,\"accessing abstract class or protected constructor\"); \n", " return Qnil;\n", "}\n", NIL);
2667 Delete(director_ctor_code);
2668 director_ctor_code = NewString("");
2669 Printv(director_ctor_code, "if ( $comparison ) { /* subclassed */\n", " $director_new \n", "} else {\n", " $nondirector_new \n", "}\n", NIL);
2670 Delete(name);
2671 }
2672
constructorHandler(Node * n)2673 virtual int constructorHandler(Node *n) {
2674 int use_director = Swig_directorclass(n);
2675 if (use_director) {
2676 set_director_ctor_code(n);
2677 }
2678
2679 /* First wrap the allocate method */
2680 current = CONSTRUCTOR_ALLOCATE;
2681 Swig_name_register("construct", "%n%c_allocate");
2682
2683 Language::constructorHandler(n);
2684
2685 String* docs = docstring(n, AUTODOC_CTOR);
2686 Printf(f_wrappers, "%s", docs);
2687 Delete(docs);
2688
2689 /*
2690 * If we're wrapping the constructor of a C++ director class, prepend a new parameter
2691 * to receive the scripting language object (e.g. 'self')
2692 *
2693 */
2694 Swig_save("ruby:constructorHandler", n, "parms", NIL);
2695 if (use_director) {
2696 Parm *parms = Getattr(n, "parms");
2697 Parm *self;
2698 String *name = NewString("self");
2699 String *type = NewString("VALUE");
2700 self = NewParm(type, name, n);
2701 Delete(type);
2702 Delete(name);
2703 Setattr(self, "lname", "Qnil");
2704 if (parms)
2705 set_nextSibling(self, parms);
2706 Setattr(n, "parms", self);
2707 Setattr(n, "wrap:self", "1");
2708 Delete(self);
2709 }
2710
2711 /* Now do the instance initialize method */
2712 current = CONSTRUCTOR_INITIALIZE;
2713 Swig_name_register("construct", "new_%n%c");
2714 Language::constructorHandler(n);
2715
2716 /* Restore original parameter list */
2717 Delattr(n, "wrap:self");
2718 Swig_restore(n);
2719
2720 /* Done */
2721 Swig_name_unregister("construct");
2722 current = NO_CPP;
2723 klass->constructor_defined = 1;
2724 return SWIG_OK;
2725 }
2726
copyconstructorHandler(Node * n)2727 virtual int copyconstructorHandler(Node *n) {
2728 int use_director = Swig_directorclass(n);
2729 if (use_director) {
2730 set_director_ctor_code(n);
2731 }
2732
2733 /* First wrap the allocate method */
2734 current = CONSTRUCTOR_ALLOCATE;
2735 Swig_name_register("construct", "%n%c_allocate");
2736
2737 return Language::copyconstructorHandler(n);
2738 }
2739
2740
2741 /* ---------------------------------------------------------------------
2742 * destructorHandler()
2743 * -------------------------------------------------------------------- */
2744
destructorHandler(Node * n)2745 virtual int destructorHandler(Node *n) {
2746
2747 /* Do no spit free function if user defined his own for this class */
2748 Node *pn = Swig_methodclass(n);
2749 String *freefunc = Getattr(pn, "feature:freefunc");
2750 if (freefunc) return SWIG_OK;
2751
2752 current = DESTRUCTOR;
2753 Language::destructorHandler(n);
2754
2755 freefunc = NewString("");
2756 String *freebody = NewString("");
2757 String *pname0 = Swig_cparm_name(0, 0);
2758
2759 Printv(freefunc, "free_", klass->mname, NIL);
2760 Printv(freebody, "SWIGINTERN void\n", freefunc, "(void *self) {\n", NIL);
2761 Printv(freebody, tab4, klass->type, " *", pname0, " = (", klass->type, " *)self;\n", NIL);
2762 Printv(freebody, tab4, NIL);
2763
2764 /* Check to see if object tracking is activated for the class
2765 that owns this destructor. */
2766 if (GetFlag(pn, "feature:trackobjects")) {
2767 Printf(freebody, "SWIG_RubyRemoveTracking(%s);\n", pname0);
2768 Printv(freebody, tab4, NIL);
2769 }
2770
2771 if (Extend) {
2772 String *wrap = Getattr(n, "wrap:code");
2773 if (wrap) {
2774 Printv(f_wrappers, wrap, NIL);
2775 }
2776 /* Printv(freebody, Swig_name_destroy(name), "(", pname0, ")", NIL); */
2777 Printv(freebody, Getattr(n, "wrap:action"), "\n", NIL);
2778 } else {
2779 String *action = Getattr(n, "wrap:action");
2780 if (action) {
2781 Printv(freebody, action, "\n", NIL);
2782 } else {
2783 /* In the case swig emits no destroy function. */
2784 if (CPlusPlus)
2785 Printf(freebody, "delete %s;\n", pname0);
2786 else
2787 Printf(freebody, "free((char*) %s);\n", pname0);
2788 }
2789 }
2790
2791 Printv(freebody, "}\n\n", NIL);
2792
2793 Printv(f_wrappers, freebody, NIL);
2794
2795 klass->destructor_defined = 1;
2796 current = NO_CPP;
2797 Delete(freefunc);
2798 Delete(freebody);
2799 Delete(pname0);
2800 return SWIG_OK;
2801 }
2802
2803 /* ---------------------------------------------------------------------
2804 * membervariableHandler()
2805 *
2806 * This creates a pair of functions to set/get the variable of a member.
2807 * -------------------------------------------------------------------- */
2808
membervariableHandler(Node * n)2809 virtual int membervariableHandler(Node *n) {
2810 String* docs = docstring(n, AUTODOC_GETTER);
2811 Printf(f_wrappers, "%s", docs);
2812 Delete(docs);
2813
2814 if (is_assignable(n)) {
2815 String* docs = docstring(n, AUTODOC_SETTER);
2816 Printf(f_wrappers, "%s", docs);
2817 Delete(docs);
2818 }
2819
2820 current = MEMBER_VAR;
2821 Language::membervariableHandler(n);
2822 current = NO_CPP;
2823 return SWIG_OK;
2824 }
2825
2826 /* -----------------------------------------------------------------------
2827 * staticmemberfunctionHandler()
2828 *
2829 * Wrap a static C++ function
2830 * ---------------------------------------------------------------------- */
2831
staticmemberfunctionHandler(Node * n)2832 virtual int staticmemberfunctionHandler(Node *n) {
2833 String* docs = docstring(n, AUTODOC_STATICFUNC);
2834 Printf(f_wrappers, "%s", docs);
2835 Delete(docs);
2836
2837 current = STATIC_FUNC;
2838 Language::staticmemberfunctionHandler(n);
2839 current = NO_CPP;
2840 return SWIG_OK;
2841 }
2842
2843 /* ----------------------------------------------------------------------
2844 * memberconstantHandler()
2845 *
2846 * Create a C++ constant
2847 * --------------------------------------------------------------------- */
2848
memberconstantHandler(Node * n)2849 virtual int memberconstantHandler(Node *n) {
2850 String* docs = docstring(n, AUTODOC_STATICFUNC);
2851 Printf(f_wrappers, "%s", docs);
2852 Delete(docs);
2853
2854 current = CLASS_CONST;
2855 Language::memberconstantHandler(n);
2856 current = NO_CPP;
2857 return SWIG_OK;
2858 }
2859
2860 /* ---------------------------------------------------------------------
2861 * staticmembervariableHandler()
2862 * --------------------------------------------------------------------- */
2863
staticmembervariableHandler(Node * n)2864 virtual int staticmembervariableHandler(Node *n) {
2865 String* docs = docstring(n, AUTODOC_GETTER);
2866 Printf(f_wrappers, "%s", docs);
2867 Delete(docs);
2868
2869 if (is_assignable(n)) {
2870 String* docs = docstring(n, AUTODOC_SETTER);
2871 Printf(f_wrappers, "%s", docs);
2872 Delete(docs);
2873 }
2874
2875 current = STATIC_VAR;
2876 Language::staticmembervariableHandler(n);
2877 current = NO_CPP;
2878 return SWIG_OK;
2879 }
2880
2881 /* C++ director class generation */
classDirector(Node * n)2882 virtual int classDirector(Node *n) {
2883 return Language::classDirector(n);
2884 }
2885
classDirectorInit(Node * n)2886 virtual int classDirectorInit(Node *n) {
2887 String *declaration;
2888 declaration = Swig_director_declaration(n);
2889 Printf(f_directors_h, "\n");
2890 Printf(f_directors_h, "%s\n", declaration);
2891 Printf(f_directors_h, "public:\n");
2892 Delete(declaration);
2893 return Language::classDirectorInit(n);
2894 }
2895
classDirectorEnd(Node * n)2896 virtual int classDirectorEnd(Node *n) {
2897 Printf(f_directors_h, "};\n\n");
2898 return Language::classDirectorEnd(n);
2899 }
2900
2901 /* ------------------------------------------------------------
2902 * classDirectorConstructor()
2903 * ------------------------------------------------------------ */
2904
classDirectorConstructor(Node * n)2905 virtual int classDirectorConstructor(Node *n) {
2906 Node *parent = Getattr(n, "parentNode");
2907 String *sub = NewString("");
2908 String *decl = Getattr(n, "decl");
2909 String *supername = Swig_class_name(parent);
2910 String *classname = NewString("");
2911 Printf(classname, "SwigDirector_%s", supername);
2912
2913 /* insert self parameter */
2914 Parm *p;
2915 ParmList *superparms = Getattr(n, "parms");
2916 ParmList *parms = CopyParmList(superparms);
2917 String *type = NewString("VALUE");
2918 p = NewParm(type, NewString("self"), n);
2919 set_nextSibling(p, parms);
2920 parms = p;
2921
2922 if (!Getattr(n, "defaultargs")) {
2923 /* constructor */
2924 {
2925 Wrapper *w = NewWrapper();
2926 String *call;
2927 String *basetype = Getattr(parent, "classtype");
2928 String *target = Swig_method_decl(0, decl, classname, parms, 0);
2929 call = Swig_csuperclass_call(0, basetype, superparms);
2930 Printf(w->def, "%s::%s: %s, Swig::Director(self) { }", classname, target, call);
2931 Delete(target);
2932 Wrapper_print(w, f_directors);
2933 Delete(call);
2934 DelWrapper(w);
2935 }
2936
2937 /* constructor header */
2938 {
2939 String *target = Swig_method_decl(0, decl, classname, parms, 1);
2940 Printf(f_directors_h, " %s;\n", target);
2941 Delete(target);
2942 }
2943 }
2944
2945 Delete(sub);
2946 Delete(classname);
2947 Delete(supername);
2948 Delete(parms);
2949 return Language::classDirectorConstructor(n);
2950 }
2951
2952 /* ------------------------------------------------------------
2953 * classDirectorDefaultConstructor()
2954 * ------------------------------------------------------------ */
2955
classDirectorDefaultConstructor(Node * n)2956 virtual int classDirectorDefaultConstructor(Node *n) {
2957 String *classname;
2958 Wrapper *w;
2959 classname = Swig_class_name(n);
2960 w = NewWrapper();
2961 Printf(w->def, "SwigDirector_%s::SwigDirector_%s(VALUE self) : Swig::Director(self) { }", classname, classname);
2962 Wrapper_print(w, f_directors);
2963 DelWrapper(w);
2964 Printf(f_directors_h, " SwigDirector_%s(VALUE self);\n", classname);
2965 Delete(classname);
2966 return Language::classDirectorDefaultConstructor(n);
2967 }
2968
2969 /* ---------------------------------------------------------------
2970 * exceptionSafeMethodCall()
2971 *
2972 * Emit a virtual director method to pass a method call on to the
2973 * underlying Ruby instance.
2974 *
2975 * --------------------------------------------------------------- */
2976
exceptionSafeMethodCall(String * className,Node * n,Wrapper * w,int argc,String * args,bool initstack)2977 void exceptionSafeMethodCall(String *className, Node *n, Wrapper *w, int argc, String *args, bool initstack) {
2978 Wrapper *body = NewWrapper();
2979 Wrapper *rescue = NewWrapper();
2980
2981 String *methodName = Getattr(n, "sym:name");
2982
2983 String *bodyName = NewStringf("%s_%s_body", className, methodName);
2984 String *rescueName = NewStringf("%s_%s_rescue", className, methodName);
2985 String *depthCountName = NewStringf("%s_%s_call_depth", className, methodName);
2986
2987 // Check for an exception typemap of some kind
2988 String *tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
2989 if (!tm) {
2990 tm = Getattr(n, "feature:director:except");
2991 }
2992
2993 if ((tm != 0) && (Len(tm) > 0) && (Strcmp(tm, "1") != 0)) {
2994 // Declare a global to hold the depth count
2995 if (!Getattr(n, "sym:nextSibling")) {
2996 Printf(body->def, "static int %s = 0;\n", depthCountName);
2997
2998 // Function body
2999 Printf(body->def, "VALUE %s(VALUE data) {\n", bodyName);
3000 Wrapper_add_localv(body, "args", "Swig::body_args *", "args", "= reinterpret_cast<Swig::body_args *>(data)", NIL);
3001 Wrapper_add_localv(body, Swig_cresult_name(), "VALUE", Swig_cresult_name(), "= Qnil", NIL);
3002 Printf(body->code, "%s++;\n", depthCountName);
3003 Printv(body->code, Swig_cresult_name(), " = rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL);
3004 Printf(body->code, "%s--;\n", depthCountName);
3005 Printv(body->code, "return ", Swig_cresult_name(), ";\n", NIL);
3006 Printv(body->code, "}", NIL);
3007
3008 // Exception handler
3009 Printf(rescue->def, "VALUE %s(VALUE args, VALUE error) {\n", rescueName);
3010 Replaceall(tm, "$error", "error");
3011 Printf(rescue->code, "%s--;\n", depthCountName);
3012 Printf(rescue->code, "if (%s == 0) ", depthCountName);
3013 Printv(rescue->code, Str(tm), "\n", NIL);
3014 Printv(rescue->code, "rb_exc_raise(error);\n", NIL);
3015 Printv(rescue->code, "return Qnil;\n", NIL);
3016 Printv(rescue->code, "}", NIL);
3017 }
3018
3019 // Main code
3020 Wrapper_add_localv(w, "args", "Swig::body_args", "args", NIL);
3021 Wrapper_add_localv(w, "status", "int", "status", NIL);
3022 Printv(w->code, "args.recv = swig_get_self();\n", NIL);
3023 Printf(w->code, "args.id = rb_intern(\"%s\");\n", methodName);
3024 Printf(w->code, "args.argc = %d;\n", argc);
3025 if (argc > 0) {
3026 Printf(w->code, "args.argv = new VALUE[%d];\n", argc);
3027 for (int i = 0; i < argc; i++) {
3028 Printf(w->code, "args.argv[%d] = obj%d;\n", i, i);
3029 }
3030 } else {
3031 Printv(w->code, "args.argv = 0;\n", NIL);
3032 }
3033 Printf(w->code, "%s = rb_protect(PROTECTFUNC(%s), reinterpret_cast<VALUE>(&args), &status);\n", Swig_cresult_name(), bodyName);
3034 if ( initstack ) Printf(w->code, "SWIG_RELEASE_STACK;\n");
3035 Printf(w->code, "if (status) {\n");
3036 Printf(w->code, "VALUE lastErr = rb_gv_get(\"$!\");\n");
3037 Printf(w->code, "%s(reinterpret_cast<VALUE>(&args), lastErr);\n", rescueName);
3038 Printf(w->code, "}\n");
3039 if (argc > 0) {
3040 Printv(w->code, "delete [] args.argv;\n", NIL);
3041 }
3042 // Dump wrapper code
3043 Wrapper_print(body, f_directors_helpers);
3044 Wrapper_print(rescue, f_directors_helpers);
3045 } else {
3046 if (argc > 0) {
3047 Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), %d%s);\n", Swig_cresult_name(), methodName, argc, args);
3048 } else {
3049 Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), 0, Qnil);\n", Swig_cresult_name(), methodName);
3050 }
3051 if ( initstack ) Printf(w->code, "SWIG_RELEASE_STACK;\n");
3052 }
3053
3054 // Clean up
3055 Delete(bodyName);
3056 Delete(rescueName);
3057 Delete(depthCountName);
3058 DelWrapper(body);
3059 DelWrapper(rescue);
3060 }
3061
classDirectorMethod(Node * n,Node * parent,String * super)3062 virtual int classDirectorMethod(Node *n, Node *parent, String *super) {
3063 int is_void = 0;
3064 int is_pointer = 0;
3065 String *decl = Getattr(n, "decl");
3066 String *name = Getattr(n, "name");
3067 String *classname = Getattr(parent, "sym:name");
3068 String *c_classname = Getattr(parent, "name");
3069 String *symname = Getattr(n, "sym:name");
3070 String *declaration = NewString("");
3071 ParmList *l = Getattr(n, "parms");
3072 Wrapper *w = NewWrapper();
3073 String *tm;
3074 String *wrap_args = NewString("");
3075 String *returntype = Getattr(n, "type");
3076 Parm *p;
3077 String *value = Getattr(n, "value");
3078 String *storage = Getattr(n, "storage");
3079 bool pure_virtual = false;
3080 int status = SWIG_OK;
3081 int idx;
3082 bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
3083 bool asvoid = checkAttribute( n, "feature:numoutputs", "0") ? true : false;
3084 bool initstack = checkAttribute( n, "feature:initstack", "1") ? true : false;
3085
3086 if (Cmp(storage, "virtual") == 0) {
3087 if (Cmp(value, "0") == 0) {
3088 pure_virtual = true;
3089 }
3090 }
3091 String *overnametmp = NewString(Getattr(n, "sym:name"));
3092 if (Getattr(n, "sym:overloaded")) {
3093 Printf(overnametmp, "::%s", Getattr(n, "sym:overname"));
3094 }
3095
3096 /* determine if the method returns a pointer */
3097 is_pointer = SwigType_ispointer_return(decl);
3098 is_void = (!Cmp(returntype, "void") && !is_pointer);
3099
3100 /* virtual method definition */
3101 String *target;
3102 String *pclassname = NewStringf("SwigDirector_%s", classname);
3103 String *qualified_name = NewStringf("%s::%s", pclassname, name);
3104 SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
3105 target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
3106 Printf(w->def, "%s", target);
3107 Delete(qualified_name);
3108 Delete(target);
3109 /* header declaration */
3110 target = Swig_method_decl(rtype, decl, name, l, 1);
3111 Printf(declaration, " virtual %s", target);
3112 Delete(target);
3113
3114 // Get any exception classes in the throws typemap
3115 if (Getattr(n, "noexcept")) {
3116 Append(w->def, " noexcept");
3117 Append(declaration, " noexcept");
3118 }
3119 ParmList *throw_parm_list = 0;
3120
3121 if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
3122 Parm *p;
3123 int gencomma = 0;
3124
3125 Append(w->def, " throw(");
3126 Append(declaration, " throw(");
3127
3128 if (throw_parm_list)
3129 Swig_typemap_attach_parms("throws", throw_parm_list, 0);
3130 for (p = throw_parm_list; p; p = nextSibling(p)) {
3131 if (Getattr(p, "tmap:throws")) {
3132 if (gencomma++) {
3133 Append(w->def, ", ");
3134 Append(declaration, ", ");
3135 }
3136
3137 Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
3138 Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
3139 }
3140 }
3141
3142 Append(w->def, ")");
3143 Append(declaration, ")");
3144 }
3145
3146 Append(w->def, " {");
3147 Append(declaration, ";\n");
3148
3149 if (initstack && !(ignored_method && !pure_virtual)) {
3150 Append(w->def, "\nSWIG_INIT_STACK;\n");
3151 }
3152
3153 /* declare method return value
3154 * if the return value is a reference or const reference, a specialized typemap must
3155 * handle it, including declaration of c_result ($result).
3156 */
3157 if (!is_void && (!ignored_method || pure_virtual)) {
3158 if (!SwigType_isclass(returntype)) {
3159 if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
3160 String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
3161 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
3162 Delete(construct_result);
3163 } else {
3164 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
3165 }
3166 } else {
3167 String *cres = SwigType_lstr(returntype, "c_result");
3168 Printf(w->code, "%s;\n", cres);
3169 Delete(cres);
3170 }
3171 }
3172
3173 if (ignored_method) {
3174 if (!pure_virtual) {
3175 if (!is_void)
3176 Printf(w->code, "return ");
3177 String *super_call = Swig_method_call(super, l);
3178 Printf(w->code, "%s;\n", super_call);
3179 Delete(super_call);
3180 } else {
3181 Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
3182 SwigType_namestr(name));
3183 }
3184 } else {
3185 /* attach typemaps to arguments (C/C++ -> Ruby) */
3186 String *arglist = NewString("");
3187
3188 Swig_director_parms_fixup(l);
3189
3190 Swig_typemap_attach_parms("in", l, 0);
3191 Swig_typemap_attach_parms("directorin", l, w);
3192 Swig_typemap_attach_parms("directorargout", l, w);
3193
3194 char source[256];
3195
3196 int outputs = 0;
3197 if (!is_void && !asvoid)
3198 outputs++;
3199
3200 /* build argument list and type conversion string */
3201 idx = 0; p = l;
3202 while ( p ) {
3203
3204 if (Getattr(p, "tmap:ignore")) {
3205 p = Getattr(p, "tmap:ignore:next");
3206 continue;
3207 }
3208
3209 if (Getattr(p, "tmap:directorargout") != 0)
3210 outputs++;
3211
3212 if ( checkAttribute( p, "tmap:in:numinputs", "0") ) {
3213 p = Getattr(p, "tmap:in:next");
3214 continue;
3215 }
3216
3217 String *parameterName = Getattr(p, "name");
3218 String *parameterType = Getattr(p, "type");
3219
3220 Putc(',', arglist);
3221 if ((tm = Getattr(p, "tmap:directorin")) != 0) {
3222 sprintf(source, "obj%d", idx++);
3223 String *input = NewString(source);
3224 Setattr(p, "emit:directorinput", input);
3225 Replaceall(tm, "$input", input);
3226 Replaceall(tm, "$owner", "0");
3227 Delete(input);
3228 Printv(wrap_args, tm, "\n", NIL);
3229 Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL);
3230 Printv(arglist, source, NIL);
3231 p = Getattr(p, "tmap:directorin:next");
3232 continue;
3233 } else if (Cmp(parameterType, "void")) {
3234 /**
3235 * Special handling for pointers to other C++ director classes.
3236 * Ideally this would be left to a typemap, but there is currently no
3237 * way to selectively apply the dynamic_cast<> to classes that have
3238 * directors. In other words, the type "SwigDirector_$1_lname" only exists
3239 * for classes with directors. We avoid the problem here by checking
3240 * module.wrap::directormap, but it's not clear how to get a typemap to
3241 * do something similar. Perhaps a new default typemap (in addition
3242 * to SWIGTYPE) called DIRECTORTYPE?
3243 */
3244 if (SwigType_ispointer(parameterType) || SwigType_isreference(parameterType)) {
3245 Node *modname = Getattr(parent, "module");
3246 Node *target = Swig_directormap(modname, parameterType);
3247 sprintf(source, "obj%d", idx++);
3248 String *nonconst = 0;
3249 /* strip pointer/reference --- should move to Swig/stype.c */
3250 String *nptype = NewString(Char(parameterType) + 2);
3251 /* name as pointer */
3252 String *ppname = Copy(parameterName);
3253 if (SwigType_isreference(parameterType)) {
3254 Insert(ppname, 0, "&");
3255 }
3256 /* if necessary, cast away const since Ruby doesn't support it! */
3257 if (SwigType_isconst(nptype)) {
3258 nonconst = NewStringf("nc_tmp_%s", parameterName);
3259 String *nonconst_i = NewStringf("= const_cast< %s >(%s)", SwigType_lstr(parameterType, 0), ppname);
3260 Wrapper_add_localv(w, nonconst, SwigType_lstr(parameterType, 0), nonconst, nonconst_i, NIL);
3261 Delete(nonconst_i);
3262 Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number,
3263 "Target language argument '%s' discards const in director method %s::%s.\n", SwigType_str(parameterType, parameterName),
3264 SwigType_namestr(c_classname), SwigType_namestr(name));
3265 } else {
3266 nonconst = Copy(ppname);
3267 }
3268 Delete(nptype);
3269 Delete(ppname);
3270 String *mangle = SwigType_manglestr(parameterType);
3271 if (target) {
3272 String *director = NewStringf("director_%s", mangle);
3273 Wrapper_add_localv(w, director, "Swig::Director *", director, "= 0", NIL);
3274 Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL);
3275 Printf(wrap_args, "%s = dynamic_cast<Swig::Director *>(%s);\n", director, nonconst);
3276 Printf(wrap_args, "if (!%s) {\n", director);
3277 Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
3278 Printf(wrap_args, "} else {\n");
3279 Printf(wrap_args, "%s = %s->swig_get_self();\n", source, director);
3280 Printf(wrap_args, "}\n");
3281 Delete(director);
3282 Printv(arglist, source, NIL);
3283 } else {
3284 Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL);
3285 Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
3286 //Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE_p_%s, 0);\n",
3287 // source, nonconst, base);
3288 Printv(arglist, source, NIL);
3289 }
3290 Delete(mangle);
3291 Delete(nonconst);
3292 } else {
3293 Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
3294 "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(parameterType, 0),
3295 SwigType_namestr(c_classname), SwigType_namestr(name));
3296 status = SWIG_NOWRAP;
3297 break;
3298 }
3299 }
3300 p = nextSibling(p);
3301 }
3302
3303 /* declare Ruby return value */
3304 String *value_result = NewStringf("VALUE SWIGUNUSED %s", Swig_cresult_name());
3305 Wrapper_add_local(w, Swig_cresult_name(), value_result);
3306 Delete(value_result);
3307
3308 /* wrap complex arguments to VALUEs */
3309 Printv(w->code, wrap_args, NIL);
3310
3311 /* pass the method call on to the Ruby object */
3312 exceptionSafeMethodCall(classname, n, w, idx, arglist, initstack);
3313
3314 /*
3315 * Ruby method may return a simple object, or an Array of objects.
3316 * For in/out arguments, we have to extract the appropriate VALUEs from the Array,
3317 * then marshal everything back to C/C++ (return value and output arguments).
3318 */
3319
3320 /* Marshal return value and other outputs (if any) from VALUE to C/C++ type */
3321
3322 String *cleanup = NewString("");
3323 String *outarg = NewString("");
3324
3325 if (outputs > 1) {
3326 Wrapper_add_local(w, "output", "VALUE output");
3327 Printf(w->code, "if (TYPE(%s) != T_ARRAY) {\n", Swig_cresult_name());
3328 Printf(w->code, "Ruby_DirectorTypeMismatchException(\"Ruby method failed to return an array.\");\n");
3329 Printf(w->code, "}\n");
3330 }
3331
3332 idx = 0;
3333
3334 /* Marshal return value */
3335 if (!is_void) {
3336 tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
3337 if (tm != 0) {
3338 if (outputs > 1 && !asvoid ) {
3339 Printf(w->code, "output = rb_ary_entry(%s, %d);\n", Swig_cresult_name(), idx++);
3340 Replaceall(tm, "$input", "output");
3341 } else {
3342 Replaceall(tm, "$input", Swig_cresult_name());
3343 }
3344 /* TODO check this */
3345 if (Getattr(n, "wrap:disown")) {
3346 Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
3347 } else {
3348 Replaceall(tm, "$disown", "0");
3349 }
3350 Replaceall(tm, "$result", "c_result");
3351 Printv(w->code, tm, "\n", NIL);
3352 } else {
3353 Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
3354 "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0),
3355 SwigType_namestr(c_classname), SwigType_namestr(name));
3356 status = SWIG_ERROR;
3357 }
3358 }
3359
3360 /* Marshal outputs */
3361 for (p = l; p;) {
3362 if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
3363 if (outputs > 1) {
3364 Printf(w->code, "output = rb_ary_entry(%s, %d);\n", Swig_cresult_name(), idx++);
3365 Replaceall(tm, "$result", "output");
3366 } else {
3367 Replaceall(tm, "$result", Swig_cresult_name());
3368 }
3369 Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
3370 Printv(w->code, tm, "\n", NIL);
3371 p = Getattr(p, "tmap:directorargout:next");
3372 } else {
3373 p = nextSibling(p);
3374 }
3375 }
3376
3377 Delete(arglist);
3378 Delete(cleanup);
3379 Delete(outarg);
3380 }
3381
3382 /* any existing helper functions to handle this? */
3383 if (!is_void) {
3384 if (!(ignored_method && !pure_virtual)) {
3385 String *rettype = SwigType_str(returntype, 0);
3386 if (!SwigType_isreference(returntype)) {
3387 Printf(w->code, "return (%s) c_result;\n", rettype);
3388 } else {
3389 Printf(w->code, "return (%s) *c_result;\n", rettype);
3390 }
3391 Delete(rettype);
3392 }
3393 }
3394
3395 Printf(w->code, "}\n");
3396
3397 // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
3398 String *inline_extra_method = NewString("");
3399 if (dirprot_mode() && !is_public(n) && !pure_virtual) {
3400 Printv(inline_extra_method, declaration, NIL);
3401 String *extra_method_name = NewStringf("%sSwigPublic", name);
3402 Replaceall(inline_extra_method, name, extra_method_name);
3403 Replaceall(inline_extra_method, ";\n", " {\n ");
3404 if (!is_void)
3405 Printf(inline_extra_method, "return ");
3406 String *methodcall = Swig_method_call(super, l);
3407 Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
3408 Delete(methodcall);
3409 Delete(extra_method_name);
3410 }
3411
3412 /* emit the director method */
3413 if (status == SWIG_OK) {
3414 if (!Getattr(n, "defaultargs")) {
3415 Replaceall(w->code, "$symname", symname);
3416 Wrapper_print(w, f_directors);
3417 Printv(f_directors_h, declaration, NIL);
3418 Printv(f_directors_h, inline_extra_method, NIL);
3419 }
3420 }
3421
3422 /* clean up */
3423 Delete(wrap_args);
3424 Delete(pclassname);
3425 DelWrapper(w);
3426 return status;
3427 }
3428
classDirectorConstructors(Node * n)3429 virtual int classDirectorConstructors(Node *n) {
3430 return Language::classDirectorConstructors(n);
3431 }
3432
classDirectorMethods(Node * n)3433 virtual int classDirectorMethods(Node *n) {
3434 return Language::classDirectorMethods(n);
3435 }
3436
classDirectorDisown(Node * n)3437 virtual int classDirectorDisown(Node *n) {
3438 return Language::classDirectorDisown(n);
3439 }
3440
runtimeCode()3441 String *runtimeCode() {
3442 String *s = NewString("");
3443 String *shead = Swig_include_sys("rubyhead.swg");
3444 if (!shead) {
3445 Printf(stderr, "*** Unable to open 'rubyhead.swg'\n");
3446 } else {
3447 Append(s, shead);
3448 Delete(shead);
3449 }
3450 String *serrors = Swig_include_sys("rubyerrors.swg");
3451 if (!serrors) {
3452 Printf(stderr, "*** Unable to open 'rubyerrors.swg'\n");
3453 } else {
3454 Append(s, serrors);
3455 Delete(serrors);
3456 }
3457 String *strack = Swig_include_sys("rubytracking.swg");
3458 if (!strack) {
3459 Printf(stderr, "*** Unable to open 'rubytracking.swg'\n");
3460 } else {
3461 Append(s, strack);
3462 Delete(strack);
3463 }
3464 String *sapi = Swig_include_sys("rubyapi.swg");
3465 if (!sapi) {
3466 Printf(stderr, "*** Unable to open 'rubyapi.swg'\n");
3467 } else {
3468 Append(s, sapi);
3469 Delete(sapi);
3470 }
3471 String *srun = Swig_include_sys("rubyrun.swg");
3472 if (!srun) {
3473 Printf(stderr, "*** Unable to open 'rubyrun.swg'\n");
3474 } else {
3475 Append(s, srun);
3476 Delete(srun);
3477 }
3478 return s;
3479 }
3480
defaultExternalRuntimeFilename()3481 String *defaultExternalRuntimeFilename() {
3482 return NewString("swigrubyrun.h");
3483 }
3484
3485 /*----------------------------------------------------------------------
3486 * kwargsSupport()
3487 *--------------------------------------------------------------------*/
3488
kwargsSupport() const3489 bool kwargsSupport() const {
3490 // kwargs support isn't actually implemented, but changing to return false may break something now as it turns on compactdefaultargs
3491 return true;
3492 }
3493 }; /* class RUBY */
3494
3495 /* -----------------------------------------------------------------------------
3496 * swig_ruby() - Instantiate module
3497 * ----------------------------------------------------------------------------- */
3498
new_swig_ruby()3499 static Language *new_swig_ruby() {
3500 return new RUBY();
3501 }
swig_ruby(void)3502 extern "C" Language *swig_ruby(void) {
3503 return new_swig_ruby();
3504 }
3505
3506
3507 /*
3508 * Local Variables:
3509 * c-basic-offset: 2
3510 * End:
3511 */
3512