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
10char cvsroot_ruby_cxx[] = "$Id: ruby.cxx 11246 2009-06-05 17:19:29Z wsfulton $";
11
12#include "swigmod.h"
13#include "cparse.h"
14static 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
22class RClass {
23private:
24  String *temp;
25
26public:
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 */
119enum 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
130static const char *usage = "\
131Ruby 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
146class RUBY:public Language {
147private:
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
748public:
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
3415static Language *new_swig_ruby() {
3416  return new RUBY();
3417}
3418extern "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 */
3428