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