PageRenderTime 138ms CodeModel.GetById 14ms app.highlight 111ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/Source/Modules/octave.cxx

#
C++ | 1538 lines | 1321 code | 174 blank | 43 comment | 218 complexity | f3f72fba08e816cc68b50c688c50702c MD5 | raw file
   1/* -----------------------------------------------------------------------------
   2 * This file is part of SWIG, which is licensed as a whole under version 3 
   3 * (or any later version) of the GNU General Public License. Some additional
   4 * terms also apply to certain portions of SWIG. The full details of the SWIG
   5 * license and copyrights can be found in the LICENSE and COPYRIGHT files
   6 * included with the SWIG source code as distributed by the SWIG developers
   7 * and at http://www.swig.org/legal.html.
   8 *
   9 * octave.cxx
  10 *
  11 * Octave language module for SWIG.
  12 * ----------------------------------------------------------------------------- */
  13
  14char cvsroot_octave_cxx[] = "$Id$";
  15
  16#include "swigmod.h"
  17
  18static bool global_load = true;
  19static String *global_name = 0;
  20static String *op_prefix   = 0;
  21
  22static const char *usage = (char *) "\
  23Octave Options (available with -octave)\n\
  24     -global         - Load all symbols into the global namespace [default]\n\
  25     -globals <name> - Set <name> used to access C global variables [default: 'cvar']\n\
  26                         - Use '.' to load C global variables into module namespace\n\
  27     -noglobal       - Do not load all symbols into the global namespace\n\
  28     -opprefix <str> - Prefix <str> for global operator functions [default: 'op_']\n\
  29\n";
  30
  31
  32class OCTAVE:public Language {
  33private:
  34  File *f_begin;
  35  File *f_runtime;
  36  File *f_header;
  37  File *f_doc;
  38  File *f_wrappers;
  39  File *f_init;
  40  File *f_initbeforefunc;
  41  File *f_directors;
  42  File *f_directors_h;
  43  String *s_global_tab;
  44  String *s_members_tab;
  45  String *class_name;
  46
  47  int have_constructor;
  48  int have_destructor;
  49  String *constructor_name;
  50
  51  Hash *docs;
  52
  53public:
  54   OCTAVE():f_begin(0), f_runtime(0), f_header(0), f_doc(0), f_wrappers(0),
  55	    f_init(0), f_initbeforefunc(0), f_directors(0), f_directors_h(0), 
  56	    s_global_tab(0), s_members_tab(0), class_name(0) {
  57     /* Add code to manage protected constructors and directors */
  58     director_prot_ctor_code = NewString("");
  59     Printv(director_prot_ctor_code,
  60	    "if ( $comparison ) { /* subclassed */\n",
  61	    "  $director_new \n",
  62	    "} else {\n", "  error(\"accessing abstract class or protected constructor\"); \n", "  SWIG_fail;\n", "}\n", NIL);
  63
  64     enable_cplus_runtime_mode();
  65     allow_overloading();
  66     director_multiple_inheritance = 1;
  67     director_language = 1;
  68     docs = NewHash();
  69   }
  70
  71  virtual void main(int argc, char *argv[]) {
  72    for (int i = 1; i < argc; i++) {
  73      if (argv[i]) {
  74	if (strcmp(argv[i], "-help") == 0) {
  75	  fputs(usage, stdout);
  76	} else if (strcmp(argv[i], "-global") == 0) {
  77          global_load = true;
  78          Swig_mark_arg(i);
  79	} else if (strcmp(argv[i], "-noglobal") == 0) {
  80          global_load = false;
  81          Swig_mark_arg(i);
  82	} else if (strcmp(argv[i], "-globals") == 0) {
  83	  if (argv[i + 1]) {
  84	    global_name = NewString(argv[i + 1]);
  85	    Swig_mark_arg(i);
  86	    Swig_mark_arg(i + 1);
  87	    i++;
  88	  } else {
  89	    Swig_arg_error();
  90	  }
  91	} else if (strcmp(argv[i], "-opprefix") == 0) {
  92	  if (argv[i + 1]) {
  93	    op_prefix = NewString(argv[i + 1]);
  94	    Swig_mark_arg(i);
  95	    Swig_mark_arg(i + 1);
  96	    i++;
  97	  } else {
  98	    Swig_arg_error();
  99	  }
 100        }            
 101      }
 102    }
 103
 104    if (!global_name)
 105      global_name = NewString("cvar");
 106    if (!op_prefix)
 107      op_prefix = NewString("op_");
 108
 109    SWIG_library_directory("octave");
 110    Preprocessor_define("SWIGOCTAVE 1", 0);
 111    SWIG_config_file("octave.swg");
 112    SWIG_typemap_lang("octave");
 113    allow_overloading();
 114  }
 115
 116  virtual int top(Node *n) {
 117    {
 118      Node *mod = Getattr(n, "module");
 119      if (mod) {
 120	Node *options = Getattr(mod, "options");
 121	if (options) {
 122	  int dirprot = 0;
 123	  if (Getattr(options, "dirprot")) {
 124	    dirprot = 1;
 125	  }
 126	  if (Getattr(options, "nodirprot")) {
 127	    dirprot = 0;
 128	  }
 129	  if (Getattr(options, "directors")) {
 130	    allow_directors();
 131	    if (dirprot)
 132	      allow_dirprot();
 133	  }
 134	}
 135      }
 136    }
 137
 138    String *module = Getattr(n, "name");
 139    String *outfile = Getattr(n, "outfile");
 140    f_begin = NewFile(outfile, "w", SWIG_output_files());
 141    if (!f_begin) {
 142      FileErrorDisplay(outfile);
 143      SWIG_exit(EXIT_FAILURE);
 144    }
 145    f_runtime = NewString("");
 146    f_header = NewString("");
 147    f_doc = NewString("");
 148    f_wrappers = NewString("");
 149    f_init = NewString("");
 150    f_initbeforefunc = NewString("");
 151    f_directors_h = NewString("");
 152    f_directors = NewString("");
 153    s_global_tab = NewString("");
 154    Swig_register_filebyname("begin", f_begin);
 155    Swig_register_filebyname("runtime", f_runtime);
 156    Swig_register_filebyname("header", f_header);
 157    Swig_register_filebyname("doc", f_doc);
 158    Swig_register_filebyname("wrapper", f_wrappers);
 159    Swig_register_filebyname("init", f_init);
 160    Swig_register_filebyname("initbeforefunc", f_initbeforefunc);
 161    Swig_register_filebyname("director", f_directors);
 162    Swig_register_filebyname("director_h", f_directors_h);
 163
 164    Swig_banner(f_begin);
 165
 166    Printf(f_runtime, "\n");
 167    Printf(f_runtime, "#define SWIGOCTAVE\n");
 168    Printf(f_runtime, "#define SWIG_name_d      \"%s\"\n", module);
 169    Printf(f_runtime, "#define SWIG_name        %s\n", module);
 170
 171    Printf(f_runtime, "\n");
 172    Printf(f_runtime, "#define SWIG_global_load      %s\n", global_load ? "true" : "false");
 173    Printf(f_runtime, "#define SWIG_global_name      \"%s\"\n", global_name);
 174    Printf(f_runtime, "#define SWIG_op_prefix        \"%s\"\n", op_prefix);
 175    Printf(f_runtime, "#define SWIG_atexit_func      swig_atexit_%s\n", module);
 176
 177    if (directorsEnabled()) {
 178      Printf(f_runtime, "#define SWIG_DIRECTORS\n");
 179      Swig_banner(f_directors_h);
 180      if (dirprot_mode()) {
 181	//      Printf(f_directors_h, "#include <map>\n");
 182	//      Printf(f_directors_h, "#include <string>\n\n");
 183      }
 184    }
 185
 186    Printf(f_runtime, "\n");
 187
 188    Printf(s_global_tab, "\nstatic const struct swig_octave_member swig_globals[] = {\n");
 189    Printf(f_init, "static void SWIG_init_user(octave_swig_type* module_ns)\n{\n");
 190
 191    if (!CPlusPlus)
 192      Printf(f_header,"extern \"C\" {\n");
 193
 194    Language::top(n);
 195
 196    if (!CPlusPlus)
 197      Printf(f_header,"}\n");
 198
 199    if (Len(docs))
 200      emit_doc_texinfo();
 201
 202    if (directorsEnabled())
 203      Swig_insert_file("director.swg", f_runtime);
 204
 205    Printf(f_init, "}\n");
 206    Printf(s_global_tab, "{0,0,0,0,0}\n};\n");
 207
 208    Printv(f_wrappers, s_global_tab, NIL);
 209    SwigType_emit_type_table(f_runtime, f_wrappers);
 210    Dump(f_runtime, f_begin);
 211    Dump(f_header, f_begin);
 212    Dump(f_doc, f_begin);
 213    if (directorsEnabled()) {
 214      Dump(f_directors_h, f_begin);
 215      Dump(f_directors, f_begin);
 216    }
 217    Dump(f_wrappers, f_begin);
 218    Dump(f_initbeforefunc, f_begin);
 219    Wrapper_pretty_print(f_init, f_begin);
 220
 221    Delete(s_global_tab);
 222    Delete(f_initbeforefunc);
 223    Delete(f_init);
 224    Delete(f_wrappers);
 225    Delete(f_doc);
 226    Delete(f_header);
 227    Delete(f_directors);
 228    Delete(f_directors_h);
 229    Close(f_begin);
 230    Delete(f_runtime);
 231    Delete(f_begin);
 232
 233    return SWIG_OK;
 234  }
 235
 236  String *texinfo_escape(String *_s) {
 237    const char* s=(const char*)Data(_s);
 238    while (*s&&(*s=='\t'||*s=='\r'||*s=='\n'||*s==' '))
 239      ++s;
 240    String *r = NewString("");
 241    for (int j=0;s[j];++j) {
 242      if (s[j] == '\n') {
 243	Append(r, "\\n\\\n");
 244      } else if (s[j] == '\r') {
 245	Append(r, "\\r");
 246      } else if (s[j] == '\t') {
 247	Append(r, "\\t");
 248      } else if (s[j] == '\\') {
 249	Append(r, "\\\\");
 250      } else if (s[j] == '\'') {
 251	Append(r, "\\\'");
 252      } else if (s[j] == '\"') {
 253	Append(r, "\\\"");
 254      } else
 255	Putc(s[j], r);
 256    }
 257    return r;
 258  }
 259  void emit_doc_texinfo() {
 260    for (Iterator it = First(docs); it.key; it = Next(it)) {
 261      String *wrap_name = it.key;
 262
 263      String *synopsis = Getattr(it.item, "synopsis");
 264      String *decl_info = Getattr(it.item, "decl_info");
 265      String *cdecl_info = Getattr(it.item, "cdecl_info");
 266      String *args_info = Getattr(it.item, "args_info");
 267
 268      String *doc_str = NewString("");
 269      Printv(doc_str, synopsis, decl_info, cdecl_info, args_info, NIL);
 270      String *escaped_doc_str = texinfo_escape(doc_str);
 271
 272      if (Len(doc_str)>0) {
 273	Printf(f_doc,"const char* %s_texinfo = ",wrap_name);
 274	Printf(f_doc,"\"-*- texinfo -*-\\n\\\n%s", escaped_doc_str);
 275	if (Len(decl_info))
 276	  Printf(f_doc,"\\n\\\n@end deftypefn");
 277	Printf(f_doc,"\";\n");
 278      }
 279
 280      Delete(escaped_doc_str);
 281      Delete(doc_str);
 282      Delete(wrap_name);
 283    }
 284    Printf(f_doc,"\n");
 285  }
 286  bool is_empty_doc_node(Node* n) {
 287    if (!n)
 288      return true;
 289    String *synopsis = Getattr(n, "synopsis");
 290    String *decl_info = Getattr(n, "decl_info");
 291    String *cdecl_info = Getattr(n, "cdecl_info");
 292    String *args_info = Getattr(n, "args_info");
 293    return !Len(synopsis) && !Len(decl_info) && 
 294      !Len(cdecl_info) && !Len(args_info);
 295  }
 296  String *texinfo_name(Node* n) {
 297    String *tname = NewString("");
 298    String *iname = Getattr(n, "sym:name");
 299    String *wname = Swig_name_wrapper(iname);
 300    Node* d = Getattr(docs, wname);
 301
 302    if (is_empty_doc_node(d))
 303      Printf(tname, "0");
 304    else
 305      Printf(tname, "%s_texinfo", wname);
 306
 307    return tname;
 308  }
 309  void process_autodoc(Node *n) {
 310    String *iname = Getattr(n, "sym:name");
 311    String *name = Getattr(n, "name");
 312    String *wname = Swig_name_wrapper(iname);
 313    String *str = Getattr(n, "feature:docstring");
 314    bool autodoc_enabled = !Cmp(Getattr(n, "feature:autodoc"), "1");
 315    Node* d = Getattr(docs, wname);
 316    if (!d) {
 317      d = NewHash();
 318      Setattr(d, "synopsis", NewString(""));
 319      Setattr(d, "decl_info", NewString(""));
 320      Setattr(d, "cdecl_info", NewString(""));
 321      Setattr(d, "args_info", NewString(""));
 322      Setattr(docs, wname, d);
 323    }
 324
 325    String *synopsis = Getattr(d, "synopsis");
 326    String *decl_info = Getattr(d, "decl_info");
 327    //    String *cdecl_info = Getattr(d, "cdecl_info");
 328    String *args_info = Getattr(d, "args_info");
 329
 330    // * couldn't we just emit the docs here?
 331
 332    if (autodoc_enabled) {
 333      String *decl_str = NewString("");
 334      String *args_str = NewString("");
 335      make_autodocParmList(n, decl_str, args_str);
 336      Append(decl_info, "@deftypefn {Loadable Function} ");
 337
 338      SwigType *type = Getattr(n, "type");
 339      if (type && Strcmp(type, "void")) {
 340	type = SwigType_base(type);
 341	Node *lookup = Swig_symbol_clookup(type, 0);
 342	if (lookup)
 343	  type = Getattr(lookup, "sym:name");
 344	Append(decl_info, "@var{retval} = ");
 345	String *type_str = NewString("");
 346	Printf(type_str, "@var{retval} is of type %s. ", type);
 347	Append(args_str, type_str);
 348	Delete(type_str);
 349      }
 350
 351      Append(decl_info, name);
 352      Append(decl_info, " (");
 353      Append(decl_info, decl_str);
 354      Append(decl_info, ")\n");
 355      Append(args_info, args_str);
 356      Delete(decl_str);
 357      Delete(args_str);
 358    }
 359
 360    if (str && Len(str) > 0) {
 361      // strip off {} if necessary
 362      char *t = Char(str);
 363      if (*t == '{') {
 364	Delitem(str, 0);
 365	Delitem(str, DOH_END);
 366      }
 367
 368      // emit into synopsis section
 369      Append(synopsis, str);
 370    }
 371  }
 372
 373  virtual int importDirective(Node *n) {
 374    String *modname = Getattr(n, "module");
 375    if (modname)
 376      Printf(f_init, "feval(\"%s\",octave_value_list(),0);\n", modname);
 377    return Language::importDirective(n);
 378  }
 379
 380  const char *get_implicitconv_flag(Node *n) {
 381    int conv = 0;
 382    if (n && GetFlag(n, "feature:implicitconv")) {
 383      conv = 1;
 384    }
 385    return conv ? "SWIG_POINTER_IMPLICIT_CONV" : "0";
 386  }
 387
 388  /* -----------------------------------------------------------------------------
 389   * addMissingParameterNames()
 390   *  For functions that have not had nameless parameters set in the Language class.
 391   *
 392   * Inputs: 
 393   *   plist - entire parameter list
 394   *   arg_offset - argument number for first parameter
 395   * Side effects:
 396   *   The "lname" attribute in each parameter in plist will be contain a parameter name
 397   * ----------------------------------------------------------------------------- */
 398
 399  void addMissingParameterNames(ParmList *plist, int arg_offset) {
 400    Parm *p = plist;
 401    int i = arg_offset;
 402    while (p) {
 403      if (!Getattr(p, "lname")) {
 404	String *pname = Swig_cparm_name(p, i);
 405	Delete(pname);
 406      }
 407      i++;
 408      p = nextSibling(p);
 409    }
 410  }
 411
 412  void make_autodocParmList(Node *n, String *decl_str, String *args_str) {
 413    String *pdocs = 0;
 414    ParmList *plist = CopyParmList(Getattr(n, "parms"));
 415    Parm *p;
 416    Parm *pnext;
 417    int start_arg_num = is_wrapping_class() ? 1 : 0;
 418
 419    addMissingParameterNames(plist, start_arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
 420
 421    Swig_typemap_attach_parms("in", plist, 0);
 422    Swig_typemap_attach_parms("doc", plist, 0);
 423
 424    for (p = plist; p; p = pnext) {
 425
 426      String *tm = Getattr(p, "tmap:in");
 427      if (tm) {
 428	pnext = Getattr(p, "tmap:in:next");
 429	if (checkAttribute(p, "tmap:in:numinputs", "0")) {
 430	  continue;
 431	}
 432      } else {
 433	pnext = nextSibling(p);
 434      }
 435
 436      String *name = 0;
 437      String *type = 0;
 438      String *value = 0;
 439      String *pdoc = Getattr(p, "tmap:doc");
 440      if (pdoc) {
 441	name = Getattr(p, "tmap:doc:name");
 442	type = Getattr(p, "tmap:doc:type");
 443	value = Getattr(p, "tmap:doc:value");
 444      }
 445
 446      // Note: the generated name should be consistent with that in kwnames[]
 447      name = name ? name : Getattr(p, "name");
 448      name = name ? name : Getattr(p, "lname");
 449      name = Swig_name_make(p, 0, name, 0, 0); // rename parameter if a keyword
 450
 451      type = type ? type : Getattr(p, "type");
 452      value = value ? value : Getattr(p, "value");
 453
 454      if (SwigType_isvarargs(type))
 455	break;
 456
 457      String *tex_name = NewString("");
 458      if (name)
 459	Printf(tex_name, "@var{%s}", name);
 460      else
 461	Printf(tex_name, "@var{?}");
 462
 463      if (Len(decl_str))
 464	Append(decl_str, ", ");
 465      Append(decl_str, tex_name);
 466
 467      if (value) {
 468	String *new_value = convertValue(value, Getattr(p, "type"));
 469	if (new_value) {
 470	  value = new_value;
 471	} else {
 472	  Node *lookup = Swig_symbol_clookup(value, 0);
 473	  if (lookup)
 474	    value = Getattr(lookup, "sym:name");
 475	}
 476	Printf(decl_str, " = %s", value);
 477      }
 478
 479      Node *nn = classLookup(Getattr(p, "type"));
 480      String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
 481      Printf(args_str, "%s is of type %s. ", tex_name, type_str);
 482
 483      Delete(type_str);
 484      Delete(tex_name);
 485      Delete(name);
 486    }
 487    if (pdocs)
 488      Setattr(n, "feature:pdocs", pdocs);
 489    Delete(plist);
 490  }
 491
 492  /* ------------------------------------------------------------
 493   * convertValue()
 494   *    Check if string v can be an Octave value literal,
 495   *    (eg. number or string), or translate it to an Octave literal.
 496   * ------------------------------------------------------------ */
 497  String *convertValue(String *v, SwigType *t) {
 498    if (v && Len(v) > 0) {
 499      char fc = (Char(v))[0];
 500      if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) {
 501	/* number or string (or maybe NULL pointer) */
 502	if (SwigType_ispointer(t) && Strcmp(v, "0") == 0)
 503	  return NewString("None");
 504	else
 505	  return v;
 506      }
 507      if (Strcmp(v, "NULL") == 0)
 508	return SwigType_ispointer(t) ? NewString("nil") : NewString("0");
 509      else if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0)
 510	return NewString("true");
 511      else if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0)
 512	return NewString("false");
 513      if (Strcmp(v, "true") == 0 || Strcmp(v, "FALSE") == 0)
 514	return NewString("true");
 515      if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0)
 516	return NewString("false");
 517    }
 518    return 0;
 519  }
 520
 521  virtual int functionWrapper(Node *n) {
 522    Wrapper *f = NewWrapper();
 523    Parm *p;
 524    String *tm;
 525    int j;
 526
 527    String *nodeType = Getattr(n, "nodeType");
 528    int constructor = (!Cmp(nodeType, "constructor"));
 529    int destructor = (!Cmp(nodeType, "destructor"));
 530    String *storage = Getattr(n, "storage");
 531
 532    bool overloaded = !!Getattr(n, "sym:overloaded");
 533    bool last_overload = overloaded && !Getattr(n, "sym:nextSibling");
 534    String *iname = Getattr(n, "sym:name");
 535    String *wname = Swig_name_wrapper(iname);
 536    String *overname = Copy(wname);
 537    SwigType *d = Getattr(n, "type");
 538    ParmList *l = Getattr(n, "parms");
 539
 540    if (!overloaded && !addSymbol(iname, n))
 541      return SWIG_ERROR;
 542
 543    if (overloaded)
 544      Append(overname, Getattr(n, "sym:overname"));
 545
 546    Printv(f->def, "static octave_value_list ", overname, " (const octave_value_list& args, int nargout) {", NIL);
 547
 548    emit_parameter_variables(l, f);
 549    emit_attach_parmmaps(l, f);
 550    Setattr(n, "wrap:parms", l);
 551
 552    int num_arguments = emit_num_arguments(l);
 553    int num_required = emit_num_required(l);
 554    int varargs = emit_isvarargs(l);
 555    char source[64];
 556
 557    Printf(f->code, "if (!SWIG_check_num_args(\"%s\",args.length(),%i,%i,%i)) " 
 558	   "{\n SWIG_fail;\n }\n", iname, num_arguments, num_required, varargs);
 559
 560    if (constructor && num_arguments == 1 && num_required == 1) {
 561      if (Cmp(storage, "explicit") == 0) {
 562	Node *parent = Swig_methodclass(n);
 563	if (GetFlag(parent, "feature:implicitconv")) {
 564	  String *desc = NewStringf("SWIGTYPE%s", SwigType_manglestr(Getattr(n, "type")));
 565	  Printf(f->code, "if (SWIG_CheckImplicit(%s)) SWIG_fail;\n", desc);
 566	  Delete(desc);
 567	}
 568      }
 569    }
 570
 571    for (j = 0, p = l; j < num_arguments; ++j) {
 572      while (checkAttribute(p, "tmap:in:numinputs", "0")) {
 573	p = Getattr(p, "tmap:in:next");
 574      }
 575
 576      SwigType *pt = Getattr(p, "type");
 577
 578      String *tm = Getattr(p, "tmap:in");
 579      if (tm) {
 580	if (!tm || checkAttribute(p, "tmap:in:numinputs", "0")) {
 581	  p = nextSibling(p);
 582	  continue;
 583	}
 584
 585	sprintf(source, "args(%d)", j);
 586	Setattr(p, "emit:input", source);
 587
 588	Replaceall(tm, "$source", Getattr(p, "emit:input"));
 589	Replaceall(tm, "$input", Getattr(p, "emit:input"));
 590	Replaceall(tm, "$target", Getattr(p, "lname"));
 591
 592	if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
 593	  Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
 594	} else {
 595	  Replaceall(tm, "$disown", "0");
 596	}
 597
 598	if (Getattr(p, "tmap:in:implicitconv")) {
 599	  const char *convflag = "0";
 600	  if (!Getattr(p, "hidden")) {
 601	    SwigType *ptype = Getattr(p, "type");
 602	    convflag = get_implicitconv_flag(classLookup(ptype));
 603	  }
 604	  Replaceall(tm, "$implicitconv", convflag);
 605	  Setattr(p, "implicitconv", convflag);
 606	}
 607
 608	String *getargs = NewString("");
 609	if (j >= num_required)
 610	  Printf(getargs, "if (%d<args.length()) {\n%s\n}", j, tm);
 611	else
 612	  Printv(getargs, tm, NIL);
 613	Printv(f->code, getargs, "\n", NIL);
 614	Delete(getargs);
 615
 616	p = Getattr(p, "tmap:in:next");
 617	continue;
 618      } else {
 619	Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
 620	break;
 621      }
 622    }
 623
 624    // Check for trailing varargs
 625    if (varargs) {
 626      if (p && (tm = Getattr(p, "tmap:in"))) {
 627	Replaceall(tm, "$input", "varargs");
 628	Printv(f->code, tm, "\n", NIL);
 629      }
 630    }
 631
 632    // Insert constraint checking code
 633    for (p = l; p;) {
 634      if ((tm = Getattr(p, "tmap:check"))) {
 635	Replaceall(tm, "$target", Getattr(p, "lname"));
 636	Printv(f->code, tm, "\n", NIL);
 637	p = Getattr(p, "tmap:check:next");
 638      } else {
 639	p = nextSibling(p);
 640      }
 641    }
 642
 643    // Insert cleanup code
 644    String *cleanup = NewString("");
 645    for (p = l; p;) {
 646      if ((tm = Getattr(p, "tmap:freearg"))) {
 647	if (Getattr(p, "tmap:freearg:implicitconv")) {
 648	  const char *convflag = "0";
 649	  if (!Getattr(p, "hidden")) {
 650	    SwigType *ptype = Getattr(p, "type");
 651	    convflag = get_implicitconv_flag(classLookup(ptype));
 652	  }
 653	  if (strcmp(convflag, "0") == 0) {
 654	    tm = 0;
 655	  }
 656	}
 657	if (tm && (Len(tm) != 0)) {
 658	  Replaceall(tm, "$source", Getattr(p, "lname"));
 659	  Printv(cleanup, tm, "\n", NIL);
 660	}
 661	p = Getattr(p, "tmap:freearg:next");
 662      } else {
 663	p = nextSibling(p);
 664      }
 665    }
 666
 667    // Insert argument output code
 668    String *outarg = NewString("");
 669    for (p = l; p;) {
 670      if ((tm = Getattr(p, "tmap:argout"))) {
 671	Replaceall(tm, "$source", Getattr(p, "lname"));
 672	Replaceall(tm, "$target", "_outp");
 673	Replaceall(tm, "$result", "_outp");
 674	Replaceall(tm, "$arg", Getattr(p, "emit:input"));
 675	Replaceall(tm, "$input", Getattr(p, "emit:input"));
 676	Printv(outarg, tm, "\n", NIL);
 677	p = Getattr(p, "tmap:argout:next");
 678      } else {
 679	p = nextSibling(p);
 680      }
 681    }
 682
 683    int director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
 684    if (director_method) {
 685      Wrapper_add_local(f, "upcall", "bool upcall = false");
 686      Append(f->code, "upcall = !!dynamic_cast<Swig::Director*>(arg1);\n");
 687    }
 688
 689    Setattr(n, "wrap:name", overname);
 690
 691    Swig_director_emit_dynamic_cast(n, f);
 692    String *actioncode = emit_action(n);
 693
 694    Wrapper_add_local(f, "_out", "octave_value_list _out");
 695    Wrapper_add_local(f, "_outp", "octave_value_list *_outp=&_out");
 696    Wrapper_add_local(f, "_outv", "octave_value _outv");
 697
 698    // Return the function value
 699    if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
 700      Replaceall(tm, "$source", Swig_cresult_name());
 701      Replaceall(tm, "$target", "_outv");
 702      Replaceall(tm, "$result", "_outv");
 703
 704      if (GetFlag(n, "feature:new"))
 705	Replaceall(tm, "$owner", "1");
 706      else
 707	Replaceall(tm, "$owner", "0");
 708
 709      Printf(f->code, "%s\n", tm);
 710      Printf(f->code, "if (_outv.is_defined()) _outp = " "SWIG_Octave_AppendOutput(_outp, _outv);\n");
 711      Delete(tm);
 712    } else {
 713      Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), iname);
 714    }
 715    emit_return_variable(n, d, f);
 716
 717    Printv(f->code, outarg, NIL);
 718    Printv(f->code, cleanup, NIL);
 719
 720    if (GetFlag(n, "feature:new")) {
 721      if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
 722	Replaceall(tm, "$source", Swig_cresult_name());
 723	Printf(f->code, "%s\n", tm);
 724      }
 725    }
 726
 727    if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
 728      Replaceall(tm, "$source", Swig_cresult_name());
 729      Replaceall(tm, "$result", "_outv");
 730      Printf(f->code, "%s\n", tm);
 731      Delete(tm);
 732    }
 733
 734    Printf(f->code, "fail:\n");	// we should free locals etc if this happens
 735    Printf(f->code, "return _out;\n");
 736    Printf(f->code, "}\n");
 737
 738    Replaceall(f->code, "$symname", iname);
 739    Wrapper_print(f, f_wrappers);
 740    DelWrapper(f);
 741
 742    if (last_overload)
 743      dispatchFunction(n);
 744
 745    if (!overloaded || last_overload) {
 746      process_autodoc(n);
 747      String *tname = texinfo_name(n);
 748      Printf(s_global_tab, "{\"%s\",%s,0,0,2,%s},\n", iname, wname, tname);
 749      Delete(tname);
 750    }
 751
 752    Delete(overname);
 753    Delete(wname);
 754    Delete(cleanup);
 755    Delete(outarg);
 756
 757    return SWIG_OK;
 758  }
 759
 760  void dispatchFunction(Node *n) {
 761    Wrapper *f = NewWrapper();
 762
 763    String *iname = Getattr(n, "sym:name");
 764    String *wname = Swig_name_wrapper(iname);
 765    int maxargs;
 766    String *dispatch = Swig_overload_dispatch(n, "return %s(args, nargout);", &maxargs);
 767    String *tmp = NewString("");
 768
 769    Printv(f->def, "static octave_value_list ", wname, " (const octave_value_list& args, int nargout) {", NIL);
 770    Wrapper_add_local(f, "argc", "int argc = args.length()");
 771    Printf(tmp, "octave_value_ref argv[%d]={", maxargs);
 772    for (int j = 0; j < maxargs; ++j)
 773      Printf(tmp, "%soctave_value_ref(args,%d)", j ? "," : " ", j);
 774    Printf(tmp, "}");
 775    Wrapper_add_local(f, "argv", tmp);
 776    Printv(f->code, dispatch, "\n", NIL);
 777    Printf(f->code, "error(\"No matching function for overload\");\n", iname);
 778    Printf(f->code, "return octave_value_list();\n");
 779    Printv(f->code, "}\n", NIL);
 780
 781    Wrapper_print(f, f_wrappers);
 782    Delete(tmp);
 783    DelWrapper(f);
 784    Delete(dispatch);
 785    Delete(wname);
 786  }
 787
 788  virtual int variableWrapper(Node *n) {
 789    String *name = Getattr(n, "name");
 790    String *iname = Getattr(n, "sym:name");
 791    SwigType *t = Getattr(n, "type");
 792
 793    if (!addSymbol(iname, n))
 794      return SWIG_ERROR;
 795
 796    String *tm;
 797    Wrapper *getf = NewWrapper();
 798    Wrapper *setf = NewWrapper();
 799
 800    String *getname = Swig_name_get(NSPACE_TODO, iname);
 801    String *setname = Swig_name_set(NSPACE_TODO, iname);
 802
 803    Printf(setf->def, "static octave_value_list _wrap_%s(const octave_value_list& args,int nargout) {", setname);
 804    Printf(setf->def, "if (!SWIG_check_num_args(\"%s_set\",args.length(),1,1,0)) return octave_value_list();", iname);
 805    if (is_assignable(n)) {
 806      Setattr(n, "wrap:name", setname);
 807      if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
 808	Replaceall(tm, "$source", "args(0)");
 809	Replaceall(tm, "$target", name);
 810	Replaceall(tm, "$input", "args(0)");
 811	if (Getattr(n, "tmap:varin:implicitconv")) {
 812	  Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
 813	}
 814	emit_action_code(n, setf->code, tm);
 815	Delete(tm);
 816      } else {
 817	Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0));
 818      }
 819      Append(setf->code, "fail:\n");
 820      Printf(setf->code, "return octave_value_list();\n");
 821    } else {
 822      Printf(setf->code, "return octave_set_immutable(args,nargout);");
 823    }
 824    Append(setf->code, "}\n");
 825    Wrapper_print(setf, f_wrappers);
 826
 827    Setattr(n, "wrap:name", getname);
 828    int addfail = 0;
 829    Printf(getf->def, "static octave_value_list _wrap_%s(const octave_value_list& args,int nargout) {", getname);
 830    Wrapper_add_local(getf, "obj", "octave_value obj");
 831    if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
 832      Replaceall(tm, "$source", name);
 833      Replaceall(tm, "$target", "obj");
 834      Replaceall(tm, "$result", "obj");
 835      addfail = emit_action_code(n, getf->code, tm);
 836      Delete(tm);
 837    } else {
 838      Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
 839    }
 840    Append(getf->code, "  return obj;\n");
 841    if (addfail) {
 842      Append(getf->code, "fail:\n");
 843      Append(getf->code, "  return octave_value_list();\n");
 844    }
 845    Append(getf->code, "}\n");
 846    Wrapper_print(getf, f_wrappers);
 847
 848    Printf(s_global_tab, "{\"%s\",0,_wrap_%s,_wrap_%s,2,0},\n", iname, getname, setname);
 849
 850    return SWIG_OK;
 851  }
 852
 853  virtual int constantWrapper(Node *n) {
 854    String *name = Getattr(n, "name");
 855    String *iname = Getattr(n, "sym:name");
 856    SwigType *type = Getattr(n, "type");
 857    String *rawval = Getattr(n, "rawval");
 858    String *value = rawval ? rawval : Getattr(n, "value");
 859    String *cppvalue = Getattr(n, "cppvalue");
 860    String *tm;
 861
 862    if (!addSymbol(iname, n))
 863      return SWIG_ERROR;
 864
 865    if (SwigType_type(type) == T_MPOINTER) {
 866      String *wname = Swig_name_wrapper(iname);
 867      String *str = SwigType_str(type, wname);
 868      Printf(f_header, "static %s = %s;\n", str, value);
 869      Delete(str);
 870      value = wname;
 871    }
 872    if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
 873      Replaceall(tm, "$source", value);
 874      Replaceall(tm, "$target", name);
 875      Replaceall(tm, "$value", cppvalue ? cppvalue : value);
 876      Replaceall(tm, "$nsname", iname);
 877      Printf(f_init, "%s\n", tm);
 878    } else {
 879      Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
 880      return SWIG_NOWRAP;
 881    }
 882
 883    return SWIG_OK;
 884  }
 885
 886  virtual int nativeWrapper(Node *n) {
 887    return Language::nativeWrapper(n);
 888  }
 889
 890  virtual int enumDeclaration(Node *n) {
 891    return Language::enumDeclaration(n);
 892  }
 893
 894  virtual int enumvalueDeclaration(Node *n) {
 895    return Language::enumvalueDeclaration(n);
 896  }
 897
 898  virtual int classDeclaration(Node *n) {
 899    return Language::classDeclaration(n);
 900  }
 901
 902  virtual int classHandler(Node *n) {
 903    have_constructor = 0;
 904    have_destructor = 0;
 905    constructor_name = 0;
 906
 907    class_name = Getattr(n, "sym:name");
 908
 909    if (!addSymbol(class_name, n))
 910      return SWIG_ERROR;
 911
 912    // This is a bug, due to the fact that swig_type -> octave_class mapping
 913    // is 1-to-n.
 914    static Hash *emitted = NewHash();
 915    String *mangled_classname = Swig_name_mangle(Getattr(n, "name"));
 916    if (Getattr(emitted, mangled_classname)) {
 917      Delete(mangled_classname);
 918      return SWIG_NOWRAP;
 919    }
 920    Setattr(emitted, mangled_classname, "1");
 921    Delete(mangled_classname);
 922
 923    assert(!s_members_tab);
 924    s_members_tab = NewString("");
 925    Printv(s_members_tab, "static swig_octave_member swig_", class_name, "_members[] = {\n", NIL);
 926
 927    Language::classHandler(n);
 928
 929    SwigType *t = Copy(Getattr(n, "name"));
 930    SwigType_add_pointer(t);
 931
 932    String *wrap_class = NewStringf("&_wrap_class_%s", class_name);
 933    SwigType_remember_clientdata(t, wrap_class);
 934
 935    int use_director = Swig_directorclass(n);
 936    if (use_director) {
 937      String *nspace = Getattr(n, "sym:nspace");
 938      String *cname = Swig_name_disown(nspace, class_name);
 939      String *wcname = Swig_name_wrapper(cname);
 940      String *disown_shadow = NewString("");
 941      Printf(disown_shadow, "static octave_value_list %s_shadow " "(const octave_value_list& args, int nargout) {\n", wcname);
 942      Printf(disown_shadow, "  if (args.length()!=1) {\n");
 943      Printf(disown_shadow, "    error(\"disown takes no arguments\");\n");
 944      Printf(disown_shadow, "    return octave_value_list();\n");
 945      Printf(disown_shadow, "  }\n");
 946      Printf(disown_shadow, "  %s (args, nargout);\n", wcname);
 947      Printf(disown_shadow, "  return args;\n");
 948      Printf(disown_shadow, "}\n");
 949      Printv(f_wrappers, disown_shadow, NIL);
 950      Delete(disown_shadow);
 951      Printf(s_members_tab, "{\"__disown\",%s_shadow,0,0,0,0},\n", wcname);
 952      Delete(wcname);
 953      Delete(cname);
 954    }
 955
 956    Printf(s_members_tab, "{0,0,0,0}\n};\n");
 957    Printv(f_wrappers, s_members_tab, NIL);
 958
 959    String *base_class_names = NewString("");
 960    String *base_class = NewString("");
 961    List *baselist = Getattr(n, "bases");
 962    if (baselist && Len(baselist)) {
 963      Iterator b;
 964      int index = 0;
 965      b = First(baselist);
 966      while (b.item) {
 967	String *bname = Getattr(b.item, "name");
 968	if ((!bname) || GetFlag(b.item, "feature:ignore") || (!Getattr(b.item, "module"))) {
 969	  b = Next(b);
 970	  continue;
 971	}
 972
 973	String *bname_mangled = SwigType_manglestr(SwigType_add_pointer(Copy(bname)));
 974	Printf(base_class_names, "\"%s\",", bname_mangled);
 975	Printf(base_class, "0,");
 976	b = Next(b);
 977	index++;
 978	Delete(bname_mangled);
 979      }
 980    }
 981
 982    Printv(f_wrappers, "static const char *swig_", class_name, "_base_names[] = {", base_class_names, "0};\n", NIL);
 983    Printv(f_wrappers, "static const swig_type_info *swig_", class_name, "_base[] = {", base_class, "0};\n", NIL);
 984    Printv(f_wrappers, "static swig_octave_class _wrap_class_", class_name, " = {\"", class_name, "\", &SWIGTYPE", SwigType_manglestr(t), ",", NIL);
 985    Printv(f_wrappers, Swig_directorclass(n) ? "1," : "0,", NIL);
 986    if (have_constructor) {
 987      String *nspace = Getattr(n, "sym:nspace");
 988      String *cname = Swig_name_construct(nspace, constructor_name);
 989      String *wcname = Swig_name_wrapper(cname);
 990      String *tname = texinfo_name(n);
 991      Printf(f_wrappers, "%s,%s,", wcname, tname);
 992      Delete(tname);
 993      Delete(wcname);
 994      Delete(cname);
 995    } else
 996      Printv(f_wrappers, "0,0,", NIL);
 997    if (have_destructor) {
 998      String *nspace = Getattr(n, "sym:nspace");
 999      String *cname = Swig_name_destroy(nspace, class_name);
1000      String *wcname = Swig_name_wrapper(cname);
1001      Printf(f_wrappers, "%s,", wcname);
1002      Delete(wcname);
1003      Delete(cname);
1004    } else
1005      Printv(f_wrappers, "0", ",", NIL);
1006    Printf(f_wrappers, "swig_%s_members,swig_%s_base_names,swig_%s_base };\n\n", class_name, class_name, class_name);
1007
1008    Delete(base_class);
1009    Delete(base_class_names);
1010    Delete(t);
1011    Delete(s_members_tab);
1012    s_members_tab = 0;
1013    class_name = 0;
1014
1015    return SWIG_OK;
1016  }
1017
1018  virtual int memberfunctionHandler(Node *n) {
1019    Language::memberfunctionHandler(n);
1020
1021    assert(s_members_tab);
1022    assert(class_name);
1023    String *name = Getattr(n, "name");
1024    String *iname = GetChar(n, "sym:name");
1025    String *realname = iname ? iname : name;
1026    String *wname = Getattr(n, "wrap:name");
1027    assert(wname);
1028
1029    if (!Getattr(n, "sym:nextSibling")) {
1030      String *tname = texinfo_name(n);
1031      String *rname = Copy(wname);
1032      bool overloaded = !!Getattr(n, "sym:overloaded");
1033      if (overloaded)
1034        Delslice(rname, Len(rname) - Len(Getattr(n, "sym:overname")), DOH_END);
1035      Printf(s_members_tab, "{\"%s\",%s,0,0,0,%s},\n", 
1036	     realname, rname, tname);
1037      Delete(rname);
1038      Delete(tname);
1039    }
1040
1041    return SWIG_OK;
1042  }
1043
1044  virtual int membervariableHandler(Node *n) {
1045    Setattr(n, "feature:autodoc", "0");
1046
1047    Language::membervariableHandler(n);
1048
1049    assert(s_members_tab);
1050    assert(class_name);
1051    String *symname = Getattr(n, "sym:name");
1052    String *getname = Swig_name_wrapper(Swig_name_get(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)));
1053    String *setname = GetFlag(n, "feature:immutable") ?
1054	NewString("octave_set_immutable") : Swig_name_wrapper(Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)));
1055    assert(s_members_tab);
1056
1057    Printf(s_members_tab, "{\"%s\",0,%s,%s,0,0},\n", symname, getname, setname);
1058
1059    Delete(getname);
1060    Delete(setname);
1061    return SWIG_OK;
1062  }
1063
1064  virtual int constructorHandler(Node *n) {
1065    have_constructor = 1;
1066    if (!constructor_name)
1067      constructor_name = NewString(Getattr(n, "sym:name"));
1068
1069    int use_director = Swig_directorclass(n);
1070    if (use_director) {
1071      Parm *parms = Getattr(n, "parms");
1072      Parm *self;
1073      String *name = NewString("self");
1074      String *type = NewString("void");
1075      SwigType_add_pointer(type);
1076      self = NewParm(type, name, n);
1077      Delete(type);
1078      Delete(name);
1079      Setattr(self, "lname", "self_obj");
1080      if (parms)
1081	set_nextSibling(self, parms);
1082      Setattr(n, "parms", self);
1083      Setattr(n, "wrap:self", "1");
1084      Setattr(n, "hidden", "1");
1085      Delete(self);
1086    }
1087
1088    return Language::constructorHandler(n);
1089  }
1090
1091  virtual int destructorHandler(Node *n) {
1092    have_destructor = 1;
1093    return Language::destructorHandler(n);
1094  }
1095
1096  virtual int staticmemberfunctionHandler(Node *n) {
1097    Language::staticmemberfunctionHandler(n);
1098
1099    assert(s_members_tab);
1100    assert(class_name);
1101    String *name = Getattr(n, "name");
1102    String *iname = GetChar(n, "sym:name");
1103    String *realname = iname ? iname : name;
1104    String *wname = Getattr(n, "wrap:name");
1105    assert(wname);
1106
1107    if (!Getattr(n, "sym:nextSibling")) {
1108      String *tname = texinfo_name(n);
1109      String *rname = Copy(wname);
1110      bool overloaded = !!Getattr(n, "sym:overloaded");
1111      if (overloaded)
1112        Delslice(rname, Len(rname) - Len(Getattr(n, "sym:overname")), DOH_END);
1113      Printf(s_members_tab, "{\"%s\",%s,0,0,1,%s},\n", 
1114	     realname, rname, tname);
1115      Delete(rname);
1116      Delete(tname);
1117    }
1118    
1119    return SWIG_OK;
1120  }
1121
1122  virtual int memberconstantHandler(Node *n) {
1123    return Language::memberconstantHandler(n);
1124  }
1125
1126  virtual int staticmembervariableHandler(Node *n) {
1127    Setattr(n, "feature:autodoc", "0");
1128
1129    Language::staticmembervariableHandler(n);
1130
1131    if (!GetFlag(n, "wrappedasconstant")) {
1132      assert(s_members_tab);
1133      assert(class_name);
1134      String *symname = Getattr(n, "sym:name");
1135      String *getname = Swig_name_wrapper(Swig_name_get(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)));
1136      String *setname = GetFlag(n, "feature:immutable") ?
1137	  NewString("octave_set_immutable") : Swig_name_wrapper(Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)));
1138      assert(s_members_tab);
1139
1140      Printf(s_members_tab, "{\"%s\",0,%s,%s,1,0},\n", symname, getname, setname);
1141
1142      Delete(getname);
1143      Delete(setname);
1144    }
1145    return SWIG_OK;
1146  }
1147
1148  int classDirectorInit(Node *n) {
1149    String *declaration = Swig_director_declaration(n);
1150    Printf(f_directors_h, "\n");
1151    Printf(f_directors_h, "%s\n", declaration);
1152    Printf(f_directors_h, "public:\n");
1153    Delete(declaration);
1154    return Language::classDirectorInit(n);
1155  }
1156
1157  int classDirectorEnd(Node *n) {
1158    Printf(f_directors_h, "};\n\n");
1159    return Language::classDirectorEnd(n);
1160  }
1161
1162  int classDirectorConstructor(Node *n) {
1163    Node *parent = Getattr(n, "parentNode");
1164    String *sub = NewString("");
1165    String *decl = Getattr(n, "decl");
1166    String *supername = Swig_class_name(parent);
1167    String *classname = NewString("");
1168    Printf(classname, "SwigDirector_%s", supername);
1169
1170    // insert self parameter
1171    Parm *p;
1172    ParmList *superparms = Getattr(n, "parms");
1173    ParmList *parms = CopyParmList(superparms);
1174    String *type = NewString("void");
1175    SwigType_add_pointer(type);
1176    p = NewParm(type, NewString("self"), n);
1177    set_nextSibling(p, parms);
1178    parms = p;
1179
1180    if (!Getattr(n, "defaultargs")) {
1181      // constructor
1182      {
1183	Wrapper *w = NewWrapper();
1184	String *call;
1185	String *basetype = Getattr(parent, "classtype");
1186	String *target = Swig_method_decl(0, decl, classname, parms, 0, 0);
1187	call = Swig_csuperclass_call(0, basetype, superparms);
1188	Printf(w->def, "%s::%s: %s," "\nSwig::Director(static_cast<%s*>(this)) { \n", classname, target, call, basetype);
1189	Append(w->def, "}\n");
1190	Delete(target);
1191	Wrapper_print(w, f_directors);
1192	Delete(call);
1193	DelWrapper(w);
1194      }
1195
1196      // constructor header
1197      {
1198	String *target = Swig_method_decl(0, decl, classname, parms, 0, 1);
1199	Printf(f_directors_h, "    %s;\n", target);
1200	Delete(target);
1201      }
1202    }
1203
1204    Delete(sub);
1205    Delete(classname);
1206    Delete(supername);
1207    Delete(parms);
1208    return Language::classDirectorConstructor(n);
1209  }
1210
1211  int classDirectorDefaultConstructor(Node *n) {
1212    String *classname = Swig_class_name(n);
1213    {
1214      Wrapper *w = NewWrapper();
1215      Printf(w->def, "SwigDirector_%s::SwigDirector_%s(void* self) :"
1216	     "\nSwig::Director((octave_swig_type*)self,static_cast<%s*>(this)) { \n", classname, classname, classname);
1217      Append(w->def, "}\n");
1218      Wrapper_print(w, f_directors);
1219      DelWrapper(w);
1220    }
1221    Printf(f_directors_h, "    SwigDirector_%s(octave_swig_type* self);\n", classname);
1222    Delete(classname);
1223    return Language::classDirectorDefaultConstructor(n);
1224  }
1225
1226  int classDirectorMethod(Node *n, Node *parent, String *super) {
1227    int is_void = 0;
1228    int is_pointer = 0;
1229    String *decl;
1230    String *type;
1231    String *name;
1232    String *classname;
1233    String *c_classname = Getattr(parent, "name");
1234    String *symname = Getattr(n, "sym:name");
1235    String *declaration;
1236    ParmList *l;
1237    Wrapper *w;
1238    String *tm;
1239    String *wrap_args = NewString("");
1240    String *return_type;
1241    String *value = Getattr(n, "value");
1242    String *storage = Getattr(n, "storage");
1243    bool pure_virtual = false;
1244    int status = SWIG_OK;
1245    int idx;
1246    bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
1247
1248    if (Cmp(storage, "virtual") == 0) {
1249      if (Cmp(value, "0") == 0) {
1250	pure_virtual = true;
1251      }
1252    }
1253
1254    classname = Getattr(parent, "sym:name");
1255    type = Getattr(n, "type");
1256    name = Getattr(n, "name");
1257
1258    w = NewWrapper();
1259    declaration = NewString("");
1260
1261    // determine if the method returns a pointer
1262    decl = Getattr(n, "decl");
1263    is_pointer = SwigType_ispointer_return(decl);
1264    is_void = (!Cmp(type, "void") && !is_pointer);
1265
1266    // form complete return type
1267    return_type = Copy(type);
1268    {
1269      SwigType *t = Copy(decl);
1270      SwigType *f = 0;
1271      f = SwigType_pop_function(t);
1272      SwigType_push(return_type, t);
1273      Delete(f);
1274      Delete(t);
1275    }
1276
1277    // virtual method definition
1278    l = Getattr(n, "parms");
1279    String *target;
1280    String *pclassname = NewStringf("SwigDirector_%s", classname);
1281    String *qualified_name = NewStringf("%s::%s", pclassname, name);
1282    SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
1283    target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
1284    Printf(w->def, "%s", target);
1285    Delete(qualified_name);
1286    Delete(target);
1287
1288    // header declaration
1289    target = Swig_method_decl(rtype, decl, name, l, 0, 1);
1290    Printf(declaration, "    virtual %s", target);
1291    Delete(target);
1292
1293    // Get any exception classes in the throws typemap
1294    ParmList *throw_parm_list = 0;
1295
1296    if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
1297      Parm *p;
1298      int gencomma = 0;
1299
1300      Append(w->def, " throw(");
1301      Append(declaration, " throw(");
1302
1303      if (throw_parm_list)
1304	Swig_typemap_attach_parms("throws", throw_parm_list, 0);
1305      for (p = throw_parm_list; p; p = nextSibling(p)) {
1306	if ((tm = Getattr(p, "tmap:throws"))) {
1307	  if (gencomma++) {
1308	    Append(w->def, ", ");
1309	    Append(declaration, ", ");
1310	  }
1311	  String *str = SwigType_str(Getattr(p, "type"), 0);
1312	  Append(w->def, str);
1313	  Append(declaration, str);
1314	  Delete(str);
1315	}
1316      }
1317
1318      Append(w->def, ")");
1319      Append(declaration, ")");
1320    }
1321
1322    Append(w->def, " {");
1323    Append(declaration, ";\n");
1324
1325    // declare method return value 
1326    // if the return value is a reference or const reference, a specialized typemap must
1327    // handle it, including declaration of c_result ($result).
1328    if (!is_void) {
1329      if (!(ignored_method && !pure_virtual)) {
1330	String *cres = SwigType_lstr(return_type, "c_result");
1331	Printf(w->code, "%s;\n", cres);
1332	Delete(cres);
1333      }
1334    }
1335
1336    if (ignored_method) {
1337      if (!pure_virtual) {
1338	if (!is_void)
1339	  Printf(w->code, "return ");
1340	String *super_call = Swig_method_call(super, l);
1341	Printf(w->code, "%s;\n", super_call);
1342	Delete(super_call);
1343      } else {
1344	Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
1345	       SwigType_namestr(name));
1346      }
1347    } else {
1348      // attach typemaps to arguments (C/C++ -> Python)
1349      String *parse_args = NewString("");
1350
1351      Swig_director_parms_fixup(l);
1352
1353      Swig_typemap_attach_parms("in", l, 0);
1354      Swig_typemap_attach_parms("directorin", l, 0);
1355      Swig_typemap_attach_parms("directorargout", l, w);
1356
1357      Parm *p;
1358
1359      int outputs = 0;
1360      if (!is_void)
1361	outputs++;
1362
1363      // build argument list and type conversion string
1364      idx = 0;
1365      p = l;
1366      while (p) {
1367	if (checkAttribute(p, "tmap:in:numinputs", "0")) {
1368	  p = Getattr(p, "tmap:in:next");
1369	  continue;
1370	}
1371
1372	if (Getattr(p, "tmap:directorargout") != 0)
1373	  outputs++;
1374
1375	String *pname = Getattr(p, "name");
1376	String *ptype = Getattr(p, "type");
1377	Wrapper_add_local(w, "tmpv", "octave_value tmpv");
1378
1379	if ((tm = Getattr(p, "tmap:directorin")) != 0) {
1380	  String *parse = Getattr(p, "tmap:directorin:parse");
1381	  if (!parse) {
1382	    Setattr(p, "emit:directorinput", "tmpv");
1383	    Replaceall(tm, "$input", "tmpv");
1384	    Replaceall(tm, "$owner", "0");
1385	    Printv(wrap_args, tm, "\n", NIL);
1386	    Printf(wrap_args, "args.append(tmpv);\n");
1387	    Putc('O', parse_args);
1388	  } else {
1389	    Append(parse_args, parse);
1390	    Setattr(p, "emit:directorinput", pname);
1391	    Replaceall(tm, "$input", pname);
1392	    Replaceall(tm, "$owner", "0");
1393	    if (Len(tm) == 0)
1394	      Append(tm, pname);
1395	  }
1396	  p = Getattr(p, "tmap:directorin:next");
1397	  continue;
1398	} else if (Cmp(ptype, "void")) {
1399	  Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
1400		       "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
1401		       SwigType_namestr(c_classname), SwigType_namestr(name));
1402	  status = SWIG_NOWRAP;
1403	  break;
1404	}
1405	p = nextSibling(p);
1406      }
1407
1408      String *method_name = Getattr(n, "sym:name");
1409
1410      Printv(w->code, wrap_args, NIL);
1411
1412      // emit method invocation
1413      Wrapper_add_local(w, "args", "octave_value_list args");
1414      Wrapper_add_local(w, "out", "octave_value_list out");
1415      Wrapper_add_local(w, "idx", "std::list<octave_value_list> idx");
1416      Printf(w->code, "idx.push_back(octave_value_list(\"%s\"));\n", method_name);
1417      Printf(w->code, "idx.push_back(args);\n");
1418      Printf(w->code, "out=swig_get_self()->subsref(\".(\",idx,%d);\n", outputs);
1419
1420      String *cleanup = NewString("");
1421      String *outarg = NewString("");
1422      idx = 0;
1423
1424      // marshal return value
1425      if (!is_void) {
1426	Printf(w->code, "if (out.length()<%d) {\n", outputs);
1427	Printf(w->code, "Swig::DirectorTypeMismatchException::raise(\"Octave "
1428	       "method %s.%s failed to return the required number " "of arguments.\");\n", classname, method_name);
1429	Printf(w->code, "}\n");
1430
1431	Setattr(n, "type", return_type);
1432	tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
1433	Setattr(n, "type", type);
1434	if (tm != 0) {
1435	  char temp[24];
1436	  sprintf(temp, "out(%d)", idx);
1437	  Replaceall(tm, "$input", temp);
1438	  //    Replaceall(tm, "$argnum", temp);
1439	  Replaceall(tm, "$disown", Getattr(n, "wrap:disown") ? "SWIG_POINTER_DISOWN" : "0");
1440	  if (Getattr(n, "tmap:directorout:implicitconv")) {
1441	    Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
1442	  }
1443	  Replaceall(tm, "$result", "c_result");
1444	  Printv(w->code, tm, "\n", NIL);
1445	  Delete(tm);
1446	} else {
1447	  Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
1448		       "Unable to use return type %s in director method %s::%s (skipping method).\n",
1449		       SwigType_str(return_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
1450	  status = SWIG_ERROR;
1451	}
1452      }
1453      idx++;
1454
1455      // marshal outputs
1456      for (p = l; p;) {
1457	if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
1458	  char temp[24];
1459	  sprintf(temp, "out(%d)", idx);
1460	  Replaceall(tm, "$result", temp);
1461	  Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
1462	  Printv(w->code, tm, "\n", NIL);
1463	  p = Getattr(p, "tmap:directorargout:next");
1464	} else {
1465	  p = nextSibling(p);
1466	}
1467      }
1468
1469      Delete(parse_args);
1470      Delete(cleanup);
1471      Delete(outarg);
1472    }
1473
1474    if (!is_void) {
1475      if (!(ignored_method && !pure_virtual)) {
1476	String *rettype = SwigType_str(return_type, 0);
1477	if (!SwigType_isreference(return_type)) {
1478	  Printf(w->code, "return (%s) c_result;\n", rettype);
1479	} else {
1480	  Printf(w->code, "return (%s) *c_result;\n", rettype);
1481	}
1482	Delete(rettype);
1483      }
1484    }
1485
1486    Append(w->code, "}\n");
1487
1488    // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
1489    String *inline_extra_method = NewString("");
1490    if (dirprot_mode() && !is_public(n) && !pure_virtual) {
1491      Printv(inline_extra_method, declaration, NIL);
1492      String *extra_method_name = NewStringf("%sSwigPublic", name);
1493      Replaceall(inline_extra_method, name, extra_method_name);
1494      Replaceall(inline_extra_method, ";\n", " {\n      ");
1495      if (!is_void)
1496	Printf(inline_extra_method, "return ");
1497      String *methodcall = Swig_method_call(super, l);
1498      Printv(inline_extra_method, methodcall, ";\n    }\n", NIL);
1499      Delete(methodcall);
1500      Delete(extra_method_name);
1501    }
1502    // emit the director method
1503    if (status == SWIG_OK) {
1504      if (!Getattr(n, "defaultargs")) {
1505	Replaceall(w->code, "$symname", symname);
1506	Wrapper_print(w, f_directors);
1507	Printv(f_directors_h, declaration, NIL);
1508	Printv(f_directors_h, inline_extra_method, NIL);
1509      }
1510    }
1511    // clean up
1512    Delete(wrap_args);
1513    Delete(return_type);
1514    Delete(pclassname);
1515    DelWrapper(w);
1516    return status;
1517  }
1518
1519  String *runtimeCode() {
1520    String *s = NewString("");
1521    String *srun = Swig_include_sys("octrun.swg");
1522    if (!srun) {
1523      Printf(stderr, "*** Unable to open 'octrun.swg'\n");
1524    } else {
1525      Append(s, srun);
1526      Delete(srun);
1527    }
1528    return s;
1529  }
1530
1531  String *defaultExternalRuntimeFilename() {
1532    return NewString("swigoctaverun.h");
1533  }
1534};
1535
1536extern "C" Language *swig_octave(void) {
1537  return new OCTAVE();
1538}