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