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