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