From 336b50b43ddf1f3c63ca5aaa6e1f596203de3d5d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 14 May 2008 22:12:31 +0000 Subject: [PATCH] Add the optimal attribute to the out typemap for more optimal code generation when returning objects by value git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@10450 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- CHANGES.current | 6 + Doc/Manual/Contents.html | 3 +- Doc/Manual/Typemaps.html | 210 ++++++++++++++++- Doc/Manual/Warnings.html | 4 + Lib/allegrocl/allegrocl.swg | 3 +- Lib/cffi/cffi.swg | 3 +- Lib/chicken/chicken.swg | 4 +- Lib/csharp/csharp.swg | 2 +- Lib/guile/typemaps.i | 4 +- Lib/java/java.swg | 2 +- Lib/lua/luatypemaps.swg | 2 +- Lib/modula3/modula3.swg | 2 +- Lib/ocaml/typemaps.i | 2 +- Lib/php4/php4.swg | 2 +- Lib/pike/pike.swg | 2 +- Source/Include/swigwarn.h | 2 + Source/Modules/allegrocl.cxx | 50 ++-- Source/Modules/cffi.cxx | 47 ++-- Source/Modules/chicken.cxx | 23 +- Source/Modules/csharp.cxx | 44 ++-- Source/Modules/directors.cxx | 25 ++ Source/Modules/emit.cxx | 117 +++++----- Source/Modules/guile.cxx | 56 ++--- Source/Modules/java.cxx | 58 ++--- Source/Modules/lua.cxx | 11 +- Source/Modules/modula3.cxx | 19 +- Source/Modules/mzscheme.cxx | 18 +- Source/Modules/ocaml.cxx | 23 +- Source/Modules/octave.cxx | 12 +- Source/Modules/perl5.cxx | 12 +- Source/Modules/php4.cxx | 42 ++-- Source/Modules/pike.cxx | 19 +- Source/Modules/python.cxx | 35 ++- Source/Modules/r.cxx | 426 +---------------------------------- Source/Modules/ruby.cxx | 123 +++++----- Source/Modules/swigmod.h | 8 +- Source/Modules/tcl8.cxx | 13 +- Source/Swig/swig.h | 1 + Source/Swig/typemap.c | 124 +++++++--- 39 files changed, 726 insertions(+), 833 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 42c694ebe..53352513e 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,6 +1,12 @@ Version 1.3.36 (in progress) ============================= +05/14/2008: wsfulton + Add an optimisation for functions that return objects by value, reducing + the number of copies of the object that are made. Implemented using an + optional attribute in the "out" typemap called "optimal". Details in + Typemaps.html. + 05/11/2008: olly [PHP] Check for %feature("notabstract") when generating PHP5 class wrapper. diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 86908fdad..5c7a18eaf 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -379,6 +379,7 @@
  • Implementing constraints with typemaps
  • Typemaps for multiple languages +
  • Optimal code generation when returning by value
  • Multi-argument typemaps
  • The run-time type checker -
  • Cross language polymorphism using directors (experimental) +
  • Cross language polymorphism using directors
  • Typemaps for multiple languages +
  • Optimal code generation when returning by value
  • Multi-argument typemaps
  • The run-time type checker -

    10.9.1 Implementation

    +

    10.10.1 Implementation

    @@ -3096,7 +3288,7 @@ structures rather than creating new ones. These swig_module_info structures are chained together in a circularly linked list.

    -

    10.9.2 Usage

    +

    10.10.2 Usage

    This section covers how to use these functions from typemaps. To learn how to @@ -3190,7 +3382,7 @@ probably just look at the output of SWIG to get a better sense for how types are managed.

    -

    10.10 Typemaps and overloading

    +

    10.11 Typemaps and overloading

    @@ -3499,7 +3691,7 @@ Subsequent "in" typemaps would then perform more extensive type-checking.

  • -

    10.11 More about %apply and %clear

    +

    10.12 More about %apply and %clear

    @@ -3584,7 +3776,7 @@ example: -

    10.12 Reducing wrapper code size

    +

    10.13 Reducing wrapper code size

    @@ -3665,7 +3857,7 @@ convert_float_array(PyObject *input, int size) { -

    10.13 Passing data between typemaps

    +

    10.14 Passing data between typemaps

    @@ -3702,7 +3894,7 @@ sure that the typemaps sharing information have exactly the same types and names

    -

    10.14 Where to go for more information?

    +

    10.15 Where to go for more information?

    diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index 6a851b3a7..39d5d3f01 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -482,8 +482,12 @@ example.i(4): Syntax error in input.

  • 469. No or improper directorin typemap defined for type
  • 470. Thread/reentrant unsafe wrapping, consider returning by value instead.
  • 471. Unable to use return type type in director method +
  • 474. Method method usage of the optimal attribute in the out typemap at file:line ignored as the following cannot be used to generate optimal code: code +
  • 475. Multiple calls to method might be generated due to optimal attribute usage in the out typemap at file:line. + +

    14.9.5 Code generation (500-599)

    diff --git a/Lib/allegrocl/allegrocl.swg b/Lib/allegrocl/allegrocl.swg index 4355209b5..0ae8ed76c 100644 --- a/Lib/allegrocl/allegrocl.swg +++ b/Lib/allegrocl/allegrocl.swg @@ -137,12 +137,13 @@ SWIG_TYPECHECK_STRING_ARRAY 1140 %typemap(lispclass) double "cl:double-float"; %typemap(lispclass) char * "cl:string"; +%typemap(out) void ""; %typemap(out) bool "$result = (int)$1;"; %typemap(out) char, unsigned char, signed char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long, - float, double, long double, char *, void *, void, + float, double, long double, char *, void *, enum SWIGTYPE, SWIGTYPE *, SWIGTYPE[ANY], SWIGTYPE & "$result = $1;"; #ifdef __cplusplus diff --git a/Lib/cffi/cffi.swg b/Lib/cffi/cffi.swg index 6f5db28d6..63bd0b040 100644 --- a/Lib/cffi/cffi.swg +++ b/Lib/cffi/cffi.swg @@ -80,12 +80,13 @@ SWIGTYPE[ANY], SWIGTYPE & "$1 = $input;"; %typemap(in) SWIGTYPE "$1 = *$input;"; +%typemap(out) void ""; %typemap(out) bool "$result = (int)$1;"; %typemap(out) char, unsigned char, signed char, short, signed short, unsigned short, int, signed int, unsigned int, long, signed long, unsigned long, - float, double, long double, char *, void *, void, + float, double, long double, char *, void * enum SWIGTYPE, SWIGTYPE *, SWIGTYPE[ANY], SWIGTYPE & "$result = $1;"; #ifdef __cplusplus diff --git a/Lib/chicken/chicken.swg b/Lib/chicken/chicken.swg index 00c657b77..d8b71874e 100644 --- a/Lib/chicken/chicken.swg +++ b/Lib/chicken/chicken.swg @@ -330,7 +330,7 @@ SIMPLE_TYPEMAP(double, C_c_double, C_flonum, C_swig_is_number, (double), C_SIZEO { $&1_ltype resultptr; C_word *known_space = C_alloc(C_SIZEOF_SWIG_POINTER); - resultptr = new $1_ltype(($1_ltype &) $1); + resultptr = new $1_ltype((const $1_ltype &) $1); $result = SWIG_NewPointerObj(resultptr, $&1_descriptor, 1); } #else @@ -348,7 +348,7 @@ SIMPLE_TYPEMAP(double, C_c_double, C_flonum, C_swig_is_number, (double), C_SIZEO { $&1_ltype resultptr; C_word *known_space = C_alloc(C_SIZEOF_SWIG_POINTER); - resultptr = new $1_ltype(($1_ltype&) $1); + resultptr = new $1_ltype((const $1_ltype&) $1); $result = SWIG_NewPointerObj(resultptr, $&1_descriptor, 0); } #else diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg index ed7d6fb3b..35e5c26d7 100644 --- a/Lib/csharp/csharp.swg +++ b/Lib/csharp/csharp.swg @@ -376,7 +376,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(out) SWIGTYPE #ifdef __cplusplus -%{ $result = new $1_ltype(($1_ltype &)$1); %} +%{ $result = new $1_ltype((const $1_ltype &)$1); %} #else { $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype)); diff --git a/Lib/guile/typemaps.i b/Lib/guile/typemaps.i index c088ccaea..d9f972850 100644 --- a/Lib/guile/typemaps.i +++ b/Lib/guile/typemaps.i @@ -119,7 +119,7 @@ #ifdef __cplusplus { $&1_ltype resultptr; - resultptr = new $1_ltype(($1_ltype &) $1); + resultptr = new $1_ltype((const $1_ltype &) $1); $result = SWIG_NewPointerObj (resultptr, $&1_descriptor, 1); } #else @@ -135,7 +135,7 @@ #ifdef __cplusplus { $&1_ltype resultptr; - resultptr = new $1_ltype(($1_ltype&) $1); + resultptr = new $1_ltype((const $1_ltype&) $1); $result = SWIG_NewPointerObj (resultptr, $&1_descriptor, 0); } #else diff --git a/Lib/java/java.swg b/Lib/java/java.swg index cf9dbec4e..b7c5607c3 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -579,7 +579,7 @@ %typemap(out) SWIGTYPE #ifdef __cplusplus -%{ *($&1_ltype*)&$result = new $1_ltype(($1_ltype &)$1); %} +%{ *($&1_ltype*)&$result = new $1_ltype((const $1_ltype &)$1); %} #else { $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype)); diff --git a/Lib/lua/luatypemaps.swg b/Lib/lua/luatypemaps.swg index f1ece2007..462d6a055 100644 --- a/Lib/lua/luatypemaps.swg +++ b/Lib/lua/luatypemaps.swg @@ -189,7 +189,7 @@ $1=&temp;%} #ifdef __cplusplus %typemap(out) SWIGTYPE { - $&1_ltype resultptr = new $1_ltype(($1_ltype &) $1); + $&1_ltype resultptr = new $1_ltype((const $1_ltype &) $1); SWIG_NewPointerObj(L,(void *) resultptr,$&1_descriptor,1); SWIG_arg++; } #else diff --git a/Lib/modula3/modula3.swg b/Lib/modula3/modula3.swg index 683b72167..6a1b4d94d 100644 --- a/Lib/modula3/modula3.swg +++ b/Lib/modula3/modula3.swg @@ -455,7 +455,7 @@ $1 = &temp; %} $1 = *argp; %} %typemap(out) SWIGTYPE #ifdef __cplusplus -%{*($&1_ltype*)&$result = new $1_ltype(($1_ltype &)$1); %} +%{*($&1_ltype*)&$result = new $1_ltype((const $1_ltype &)$1); %} #else { $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype)); diff --git a/Lib/ocaml/typemaps.i b/Lib/ocaml/typemaps.i index b082d062b..7f978bf7f 100644 --- a/Lib/ocaml/typemaps.i +++ b/Lib/ocaml/typemaps.i @@ -76,7 +76,7 @@ %typemap(out) SWIGTYPE { /* %typemap(out) SWIGTYPE */ - $&1_ltype temp = new $ltype(($1_ltype &) $1); + $&1_ltype temp = new $ltype((const $1_ltype &) $1); CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr"); if( fromval ) { $result = callback(*fromval,caml_val_ptr((void *)temp,$&1_descriptor)); diff --git a/Lib/php4/php4.swg b/Lib/php4/php4.swg index 1b81c65e5..feaee68f6 100644 --- a/Lib/php4/php4.swg +++ b/Lib/php4/php4.swg @@ -211,7 +211,7 @@ %typemap(out) SWIGTYPE #ifdef __cplusplus { - $&1_ltype resultobj = new $1_ltype(($1_ltype &) $1); + $&1_ltype resultobj = new $1_ltype((const $1_ltype &) $1); SWIG_SetPointerZval(return_value, (void *)resultobj, $&1_descriptor, 1); } #else diff --git a/Lib/pike/pike.swg b/Lib/pike/pike.swg index 483ba761f..e72da8fba 100644 --- a/Lib/pike/pike.swg +++ b/Lib/pike/pike.swg @@ -136,7 +136,7 @@ extern "C" { #ifdef __cplusplus { $&1_ltype resultptr; - resultptr = new $1_ltype(($1_ltype &) $1); + resultptr = new $1_ltype((const $1_ltype &) $1); push_object(SWIG_NewPointerObj((void *) resultptr, $&1_descriptor, 1)); } #else diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index 5c6634063..174e8b001 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -161,6 +161,8 @@ #define WARN_TYPEMAP_DIRECTOROUT_UNDEF 471 #define WARN_TYPEMAP_TYPECHECK_UNDEF 472 #define WARN_TYPEMAP_DIRECTOROUT_PTR 473 +#define WARN_TYPEMAP_OUT_OPTIMAL_IGNORED 474 +#define WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE 475 /* -- Fragments -- */ #define WARN_FRAGMENT_NOT_FOUND 490 diff --git a/Source/Modules/allegrocl.cxx b/Source/Modules/allegrocl.cxx index ae50597d1..a4450f85d 100644 --- a/Source/Modules/allegrocl.cxx +++ b/Source/Modules/allegrocl.cxx @@ -2517,7 +2517,7 @@ int ALLEGROCL::emit_defun(Node *n, File *f_cl) { int ALLEGROCL::functionWrapper(Node *n) { ParmList *parms = CopyParmList(Getattr(n, "parms")); - Wrapper *wrap = NewWrapper(); + Wrapper *f = NewWrapper(); String *raw_return_type = Swig_typemap_lookup_new("ctype", n, "", 0); SwigType *return_type = Swig_cparse_type(raw_return_type); @@ -2528,18 +2528,18 @@ int ALLEGROCL::functionWrapper(Node *n) { if (!is_void_return) { String *lresult_init = NewStringf("= (%s)0", raw_return_type); - Wrapper_add_localv(wrap, "lresult", + Wrapper_add_localv(f, "lresult", SwigType_lstr(SwigType_ltype(return_type), "lresult"), lresult_init, NIL); Delete(lresult_init); } // Emit all of the local variables for holding arguments. - emit_args(Getattr(n, "type"), parms, wrap); + emit_parameter_variables(parms, f); // Attach the standard typemaps - Swig_typemap_attach_parms("ctype", parms, wrap); - Swig_typemap_attach_parms("lin", parms, wrap); - emit_attach_parmmaps(parms, wrap); + Swig_typemap_attach_parms("ctype", parms, f); + Swig_typemap_attach_parms("lin", parms, f); + emit_attach_parmmaps(parms, f); String *mangled = mangle_name(n); Node *overloaded = Getattr(n, "sym:overloaded"); @@ -2562,7 +2562,7 @@ int ALLEGROCL::functionWrapper(Node *n) { emit_buffered_defuns(n); emit_dispatch_defun(n); } - DelWrapper(wrap); + DelWrapper(f); return SWIG_OK; } } @@ -2609,7 +2609,7 @@ int ALLEGROCL::functionWrapper(Node *n) { // canThrow(n, "in", p); Replaceall(parm_code, "$input", arg); Setattr(p, "emit:input", arg); - Printf(wrap->code, "%s\n", parm_code); + Printf(f->code, "%s\n", parm_code); p = Getattr(p, "tmap:in:next"); } @@ -2619,28 +2619,30 @@ int ALLEGROCL::functionWrapper(Node *n) { // Emit the function definition String *signature = SwigType_str(return_type, name_and_parms); - Printf(wrap->def, "EXPORT %s {", signature); + Printf(f->def, "EXPORT %s {", signature); if (CPlusPlus) - Printf(wrap->code, " try {\n"); - emit_action(n, wrap); - if (!is_void_return) { - String *result_convert = Swig_typemap_lookup_new("out", n, "result", 0); - Replaceall(result_convert, "$result", "lresult"); - Printf(wrap->code, "%s\n", result_convert); - Printf(wrap->code, " return lresult;\n"); - Delete(result_convert); - } + Printf(f->code, " try {\n"); + + String *actioncode = emit_action(n); + + String *result_convert = Swig_typemap_lookup_out("out", n, "result", f, actioncode); + Replaceall(result_convert, "$result", "lresult"); + Printf(f->code, "%s\n", result_convert); + Printf(f->code, " return lresult;\n"); + Delete(result_convert); + emit_return_variable(n, Getattr(n, "type"), f); + if (CPlusPlus) { - Printf(wrap->code, " } catch (...) {\n"); + Printf(f->code, " } catch (...) {\n"); if (!is_void_return) - Printf(wrap->code, " return (%s)0;\n", raw_return_type); - Printf(wrap->code, " }\n"); + Printf(f->code, " return (%s)0;\n", raw_return_type); + Printf(f->code, " }\n"); } - Printf(wrap->code, "}\n"); + Printf(f->code, "}\n"); /* print this when in C mode? make this a command-line arg? */ if (Generate_Wrapper) - Wrapper_print(wrap, f_cxx); + Wrapper_print(f, f_cxx); String *f_buffer = NewString(""); @@ -2656,7 +2658,7 @@ int ALLEGROCL::functionWrapper(Node *n) { } } - DelWrapper(wrap); + DelWrapper(f); return SWIG_OK; } diff --git a/Source/Modules/cffi.cxx b/Source/Modules/cffi.cxx index a173e5e08..66aed51e8 100644 --- a/Source/Modules/cffi.cxx +++ b/Source/Modules/cffi.cxx @@ -354,7 +354,7 @@ int CFFI::functionWrapper(Node *n) { ParmList *parms = Getattr(n, "parms"); String *iname = Getattr(n, "sym:name"); - Wrapper *wrap = NewWrapper(); + Wrapper *f = NewWrapper(); String *raw_return_type = Swig_typemap_lookup_new("ctype", n, "", 0); SwigType *return_type = Swig_cparse_type(raw_return_type); @@ -364,7 +364,7 @@ int CFFI::functionWrapper(Node *n) { if (!is_void_return) { String *lresult_init = NewStringf("lresult = (%s)0", raw_return_type); - Wrapper_add_localv(wrap, "lresult", raw_return_type, lresult_init, NIL); + Wrapper_add_localv(f, "lresult", raw_return_type, lresult_init, NIL); Delete(lresult_init); } @@ -373,7 +373,7 @@ int CFFI::functionWrapper(Node *n) { overname = Getattr(n, "sym:overname"); } else { if (!addSymbol(iname, n)) { - DelWrapper(wrap); + DelWrapper(f); return SWIG_ERROR; } } @@ -385,11 +385,11 @@ int CFFI::functionWrapper(Node *n) { Setattr(n, "wrap:name", wname); // Emit all of the local variables for holding arguments. - emit_args(Getattr(n, "type"), parms, wrap); + emit_parameter_variables(parms, f); // Attach the standard typemaps - Swig_typemap_attach_parms("ctype", parms, wrap); - emit_attach_parmmaps(parms, wrap); + Swig_typemap_attach_parms("ctype", parms, f); + emit_attach_parmmaps(parms, f); int num_arguments = emit_num_arguments(parms); String *name_and_parms = NewStringf("%s (", wname); @@ -426,7 +426,7 @@ int CFFI::functionWrapper(Node *n) { { Replaceall(parm_code, "$input", arg); Setattr(p, "emit:input", arg); - Printf(wrap->code, "%s\n", parm_code); + Printf(f->code, "%s\n", parm_code); p = Getattr(p, "tmap:in:next"); } @@ -436,25 +436,26 @@ int CFFI::functionWrapper(Node *n) { // Emit the function definition String *signature = SwigType_str(return_type, name_and_parms); - Printf(wrap->def, "EXPORT %s {", signature); - Printf(wrap->code, " try {\n"); - emit_action(n, wrap); - if (!is_void_return) { - String *result_convert = Swig_typemap_lookup_new("out", n, "result", 0); - Replaceall(result_convert, "$result", "lresult"); - Printf(wrap->code, "%s\n", result_convert); - Printf(wrap->code, " return lresult;\n"); - Delete(result_convert); - } + Printf(f->def, "EXPORT %s {", signature); + Printf(f->code, " try {\n"); - Printf(wrap->code, " } catch (...) {\n"); + String *actioncode = emit_action(n); + + String *result_convert = Swig_typemap_lookup_out("out", n, "result", f, actioncode); + Replaceall(result_convert, "$result", "lresult"); + Printf(f->code, "%s\n", result_convert); + Printf(f->code, " return lresult;\n"); + Delete(result_convert); + emit_return_variable(n, Getattr(n, "type"), f); + + Printf(f->code, " } catch (...) {\n"); if (!is_void_return) - Printf(wrap->code, " return (%s)0;\n", raw_return_type); - Printf(wrap->code, " }\n"); - Printf(wrap->code, "}\n"); + Printf(f->code, " return (%s)0;\n", raw_return_type); + Printf(f->code, " }\n"); + Printf(f->code, "}\n"); if (CPlusPlus) - Wrapper_print(wrap, f_cxx); + Wrapper_print(f, f_cxx); if (CPlusPlus) { emit_defun(n, wname); @@ -482,7 +483,7 @@ int CFFI::functionWrapper(Node *n) { // } Delete(wname); - DelWrapper(wrap); + DelWrapper(f); return SWIG_OK; } diff --git a/Source/Modules/chicken.cxx b/Source/Modules/chicken.cxx index a908d9b52..712da552e 100644 --- a/Source/Modules/chicken.cxx +++ b/Source/Modules/chicken.cxx @@ -368,7 +368,7 @@ int CHICKEN::functionWrapper(Node *n) { Wrapper_add_local(f, "resultobj", "C_word resultobj"); /* Write code to extract function parameters. */ - emit_args(d, l, f); + emit_parameter_variables(l, f); /* Attach the standard typemaps */ emit_attach_parmmaps(l, f); @@ -501,11 +501,6 @@ int CHICKEN::functionWrapper(Node *n) { } } - Setattr(n, "wrap:name", wname); - - /* Emit the function call */ - emit_action(n, f); - /* Insert argument output code */ have_argout = 0; for (p = l; p;) { @@ -514,7 +509,7 @@ int CHICKEN::functionWrapper(Node *n) { if (!have_argout) { have_argout = 1; // Print initial argument output code - Printf(f->code, "SWIG_Chicken_SetupArgout\n"); + Printf(argout, "SWIG_Chicken_SetupArgout\n"); } Replaceall(tm, "$source", Getattr(p, "lname")); @@ -528,8 +523,13 @@ int CHICKEN::functionWrapper(Node *n) { } } + Setattr(n, "wrap:name", wname); + + /* Emit the function call */ + String *actioncode = emit_action(n); + /* Return the function value */ - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { Replaceall(tm, "$source", "result"); Replaceall(tm, "$target", "resultobj"); Replaceall(tm, "$result", "resultobj"); @@ -547,6 +547,7 @@ int CHICKEN::functionWrapper(Node *n) { } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name); } + emit_return_variable(n, d, f); /* Insert the argumetn output code */ Printv(f->code, argout, NIL); @@ -731,7 +732,7 @@ int CHICKEN::variableWrapper(Node *n) { Replaceall(tm, "$target", name); Replaceall(tm, "$input", "value"); /* Printv(f->code, tm, "\n",NIL); */ - emit_action_code(n, f, tm); + emit_action_code(n, f->code, tm); } else { Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0)); } @@ -753,7 +754,7 @@ int CHICKEN::variableWrapper(Node *n) { Replaceall(tm, "$target", "resultobj"); Replaceall(tm, "$result", "resultobj"); /* Printf(f->code, "%s\n", tm); */ - emit_action_code(n, f, tm); + emit_action_code(n, f->code, tm); } else { Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); } @@ -926,7 +927,7 @@ int CHICKEN::constantWrapper(Node *n) { Replaceall(tm, "$target", "resultobj"); Replaceall(tm, "$result", "resultobj"); /* Printf(f->code, "%s\n", tm); */ - emit_action_code(n, f, tm); + emit_action_code(n, f->code, tm); } else { Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); } diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 8597d731e..5a3c14139 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -757,7 +757,7 @@ public: Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL); // Emit all of the local variables for holding arguments. - emit_args(t, l, f); + emit_parameter_variables(l, f); /* Attach the standard typemaps */ emit_attach_parmmaps(l, f); @@ -901,25 +901,26 @@ public: } } - if (Cmp(nodeType(n), "constant") == 0) { - // Wrapping a constant hack - Swig_save("functionWrapper", n, "wrap:action", NIL); - - // below based on Swig_VargetToFunction() - SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n)); - Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value"))); - } - // Now write code to make the function call - if (!native_function_flag) - emit_action(n, f); - - if (Cmp(nodeType(n), "constant") == 0) - Swig_restore(n); - - /* Return value if necessary */ String *null_attribute = 0; + // Now write code to make the function call if (!native_function_flag) { - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + if (Cmp(nodeType(n), "constant") == 0) { + // Wrapping a constant hack + Swig_save("functionWrapper", n, "wrap:action", NIL); + + // below based on Swig_VargetToFunction() + SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n)); + Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value"))); + } + + Swig_director_emit_dynamic_cast(n, f); + String *actioncode = emit_action(n); + + if (Cmp(nodeType(n), "constant") == 0) + Swig_restore(n); + + /* Return value if necessary */ + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { canThrow(n, "out", n); Replaceall(tm, "$source", "result"); /* deprecated */ Replaceall(tm, "$target", "jresult"); /* deprecated */ @@ -937,6 +938,7 @@ public: } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), Getattr(n, "name")); } + emit_return_variable(n, t, f); } /* Output argument output code */ @@ -3463,9 +3465,6 @@ public: // Get any Java exception classes in the throws typemap ParmList *throw_parm_list = NULL; - if ((tm = Swig_typemap_lookup_new("out", n, "", 0))) - addThrows(n, "tmap:out", n); - if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { int gencomma = 0; @@ -3507,8 +3506,7 @@ public: if (!is_void) { Parm *tp = NewParmFromNode(returntype, empty_str, n); - tm = Swig_typemap_lookup_new("csdirectorout", tp, "", 0); - if (tm) { + if ((tm = Swig_typemap_lookup_new("csdirectorout", tp, "", 0))) { substituteClassname(returntype, tm); Replaceall(tm, "$cscall", upcall); diff --git a/Source/Modules/directors.cxx b/Source/Modules/directors.cxx index 9426fb379..4363cd813 100644 --- a/Source/Modules/directors.cxx +++ b/Source/Modules/directors.cxx @@ -261,3 +261,28 @@ String *Swig_method_decl(SwigType *returntype, SwigType *decl, const String_or_c return result; } + +/* ----------------------------------------------------------------------------- + * Swig_director_emit_dynamic_cast() + * + * In order to call protected virtual director methods from the target language, we need + * to add an extra dynamic_cast to call the public C++ wrapper in the director class. + * Also for non-static protected members when the allprotected option is on. + * ----------------------------------------------------------------------------- */ +void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f) { + // TODO: why is the storage element removed in staticmemberfunctionHandler ?? + if ((!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall"))) || + (is_non_virtual_protected_access(n) && !(checkAttribute(n, "staticmemberfunctionHandler:storage", "static") || + checkAttribute(n, "storage", "static")) + && !Equal(nodeType(n), "constructor"))) { + Node *parent = Getattr(n, "parentNode"); + String *symname = Getattr(parent, "sym:name"); + String *dirname = NewStringf("SwigDirector_%s", symname); + String *dirdecl = NewStringf("%s *darg = 0", dirname); + Wrapper_add_local(f, "darg", dirdecl); + Printf(f->code, "darg = dynamic_cast<%s *>(arg1);\n", dirname); + Delete(dirname); + Delete(dirdecl); + } +} + diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx index 5f36a7ec7..ee28f3a7d 100644 --- a/Source/Modules/emit.cxx +++ b/Source/Modules/emit.cxx @@ -12,16 +12,47 @@ char cvsroot_emit_cxx[] = "$Id$"; #include "swigmod.h" /* ----------------------------------------------------------------------------- - * emit_args() + * emit_return_variable() * - * Creates a list of variable declarations for both the return value - * and function parameters. - * - * The return value is always called result and arguments arg0, arg1, arg2, etc... - * Returns the number of parameters associated with a function. + * Emits a variable declaration for a function return value. + * The variable name is always called result. + * n => Node of the method being wrapped + * rt => the return type + * f => the wrapper to generate code into * ----------------------------------------------------------------------------- */ -void emit_args(SwigType *rt, ParmList *l, Wrapper *f) { +void emit_return_variable(Node *n, SwigType *rt, Wrapper *f) { + + if (!GetFlag(n, "tmap:out:optimal")) { + if (rt && (SwigType_type(rt) != T_VOID)) { + SwigType *vt = cplus_value_type(rt); + SwigType *tt = vt ? vt : rt; + SwigType *lt = SwigType_ltype(tt); + String *lstr = SwigType_str(lt, "result"); + if (SwigType_ispointer(lt)) { + Wrapper_add_localv(f, "result", lstr, "= 0", NULL); + } else { + Wrapper_add_local(f, "result", lstr); + } + if (vt) { + Delete(vt); + } + Delete(lt); + Delete(lstr); + } + } +} + +/* ----------------------------------------------------------------------------- + * emit_parameter_variables() + * + * Emits a list of variable declarations for function parameters. + * The variable names are always called arg1, arg2, etc... + * l => the parameter list + * f => the wrapper to generate code into + * ----------------------------------------------------------------------------- */ + +void emit_parameter_variables(ParmList *l, Wrapper *f) { Parm *p; String *tm; @@ -29,24 +60,6 @@ void emit_args(SwigType *rt, ParmList *l, Wrapper *f) { /* Emit function arguments */ Swig_cargs(f, l); - /* Handle return type */ - if (rt && (SwigType_type(rt) != T_VOID)) { - SwigType *vt = cplus_value_type(rt); - SwigType *tt = vt ? vt : rt; - SwigType *lt = SwigType_ltype(tt); - String *lstr = SwigType_str(lt, "result"); - if (SwigType_ispointer(lt)) { - Wrapper_add_localv(f, "result", lstr, "= 0", NULL); - } else { - Wrapper_add_local(f, "result", lstr); - } - if (vt) { - Delete(vt); - } - Delete(lt); - Delete(lstr); - } - /* Attach typemaps to parameters */ /* Swig_typemap_attach_parms("ignore",l,f); */ @@ -78,7 +91,6 @@ void emit_args(SwigType *rt, ParmList *l, Wrapper *f) { p = nextSibling(p); } } - return; } /* ----------------------------------------------------------------------------- @@ -332,11 +344,13 @@ static void replace_contract_args(Parm *cp, Parm *rp, String *s) { #endif /* ----------------------------------------------------------------------------- - * int emit_action() + * int emit_action_code() * * Emits action code for a wrapper. Adds in exception handling code (%exception). + * eaction -> the action code to emit + * wrappercode -> the emitted code (output) * ----------------------------------------------------------------------------- */ -int emit_action_code(Node *n, Wrapper *f, String *eaction) { +int emit_action_code(Node *n, String *wrappercode, String *eaction) { assert(Getattr(n, "wrap:name")); /* Look for except feature (%exception) */ @@ -364,16 +378,23 @@ int emit_action_code(Node *n, Wrapper *f, String *eaction) { Delete(fulldecl); } } - Printv(f->code, tm, "\n", NIL); + Printv(wrappercode, tm, "\n", NIL); Delete(tm); return 1; } else { - Printv(f->code, eaction, "\n", NIL); + Printv(wrappercode, eaction, "\n", NIL); return 0; } } -void emit_action(Node *n, Wrapper *f) { +/* ----------------------------------------------------------------------------- + * int emit_action() + * + * Emits the call to the wrapped function. + * Adds in exception specification exception handling and %exception code. + * ----------------------------------------------------------------------------- */ +String *emit_action(Node *n) { + String *actioncode = NewStringEmpty(); String *tm; String *action; String *wrap; @@ -382,11 +403,10 @@ void emit_action(Node *n, Wrapper *f) { /* Look for fragments */ { - String *f; - f = Getattr(n, "feature:fragment"); - if (f) { + String *fragment = Getattr(n, "feature:fragment"); + if (fragment) { char *c, *tok; - String *t = Copy(f); + String *t = Copy(fragment); c = Char(t); tok = strtok(c, ","); while (tok) { @@ -416,27 +436,7 @@ void emit_action(Node *n, Wrapper *f) { action = Getattr(n, "wrap:action"); assert(action != 0); - - /* In order to call protected virtual director methods from the target language, we need - * to add an extra dynamic_cast to call the public C++ wrapper in the director class. - * Also for non-static protected members when the allprotected option is on. */ -// TODO: why is the storage element removed in staticmemberfunctionHandler ?? - if ((!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall"))) || - (is_non_virtual_protected_access(n) && !(checkAttribute(n, "staticmemberfunctionHandler:storage", "static") || - checkAttribute(n, "storage", "static")) - && !Equal(nodeType(n), "constructor"))) { - Node *parent = Getattr(n, "parentNode"); - String *symname = Getattr(parent, "sym:name"); - String *dirname = NewStringf("SwigDirector_%s", symname); - String *dirdecl = NewStringf("%s *darg = 0", dirname); - Wrapper_add_local(f, "darg", dirdecl); - Printf(f->code, "darg = dynamic_cast<%s *>(arg1);\n", dirname); - Delete(dirname); - Delete(dirdecl); - } - /* Get the return type */ - rt = Getattr(n, "type"); /* Emit contract code (if any) */ @@ -444,7 +444,7 @@ void emit_action(Node *n, Wrapper *f) { /* Preassertion */ tm = Getattr(n, "contract:preassert"); if (Len(tm)) { - Printv(f->code, tm, "\n", NIL); + Printv(actioncode, tm, "\n", NIL); } } /* Exception handling code */ @@ -495,7 +495,7 @@ void emit_action(Node *n, Wrapper *f) { } /* emit the except feature code */ - emit_action_code(n, f, eaction); + emit_action_code(n, actioncode, eaction); Delete(eaction); @@ -504,8 +504,9 @@ void emit_action(Node *n, Wrapper *f) { /* Postassertion */ tm = Getattr(n, "contract:postassert"); if (Len(tm)) { - Printv(f->code, tm, "\n", NIL); + Printv(actioncode, tm, "\n", NIL); } } + return actioncode; } diff --git a/Source/Modules/guile.cxx b/Source/Modules/guile.cxx index 95633410f..880a7fabf 100644 --- a/Source/Modules/guile.cxx +++ b/Source/Modules/guile.cxx @@ -687,7 +687,7 @@ public: Replaceall(proc_name, "_", "-"); /* Emit locals etc. into f->code; figure out which args to ignore */ - emit_args(d, l, f); + emit_parameter_variables(l, f); /* Attach the standard typemaps */ emit_attach_parmmaps(l, f); @@ -702,25 +702,6 @@ public: Wrapper_add_local(f, "gswig_result", "SCM gswig_result"); Wrapper_add_local(f, "gswig_list_p", "SWIGUNUSED int gswig_list_p = 0"); - /* Get the output typemap so we can start generating documentation. Don't - worry, the returned string is saved as 'tmap:out' */ - - Swig_typemap_lookup_new("out", n, "result", 0); - - if ((tm = Getattr(n, "tmap:out:doc"))) { - Printv(returns, tm, NIL); - if (Len(tm) > 0) - num_results = 1; - else - num_results = 0; - } else { - String *s = SwigType_str(d, 0); - Chop(s); - Printf(returns, "<%s>", s); - Delete(s); - num_results = 1; - } - /* Open prototype and signature */ Printv(f->def, "static SCM\n", wname, " (", NIL); @@ -830,6 +811,7 @@ public: /* Pass output arguments back to the caller. */ /* Insert argument output code */ + String *returns_argout = NewString(""); for (p = l; p;) { if ((tm = Getattr(p, "tmap:argout"))) { Replaceall(tm, "$source", Getattr(p, "lname")); @@ -838,7 +820,7 @@ public: Replaceall(tm, "$input", Getattr(p, "emit:input")); Printv(outarg, tm, "\n", NIL); if (procdoc) { - if (handle_documentation_typemap(returns, ", ", p, "tmap:argout:doc", "$NAME (of type $type)")) { + if (handle_documentation_typemap(returns_argout, ", ", p, "tmap:argout:doc", "$NAME (of type $type)")) { /* A documentation typemap that is not the empty string indicates that a value is returned to Scheme. */ num_results++; @@ -881,13 +863,14 @@ public: // Now write code to make the function call if (!use_scm_interface) Printv(f->code, tab4, "gh_defer_ints();\n", NIL); - emit_action(n, f); + + String *actioncode = emit_action(n); + if (!use_scm_interface) - Printv(f->code, tab4, "gh_allow_ints();\n", NIL); + Printv(actioncode, tab4, "gh_allow_ints();\n", NIL); // Now have return value, figure out what to do with it. - - if ((tm = Getattr(n, "tmap:out"))) { + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { Replaceall(tm, "$result", "gswig_result"); Replaceall(tm, "$target", "gswig_result"); Replaceall(tm, "$source", "result"); @@ -899,6 +882,24 @@ public: } else { throw_unhandled_guile_type_error(d); } + emit_return_variable(n, d, f); + + // Documentation + if ((tm = Getattr(n, "tmap:out:doc"))) { + Printv(returns, tm, NIL); + if (Len(tm) > 0) + num_results = 1; + else + num_results = 0; + } else { + String *s = SwigType_str(d, 0); + Chop(s); + Printf(returns, "<%s>", s); + Delete(s); + num_results = 1; + } + Append(returns, returns_argout); + // Dump the argument output code Printv(f->code, outarg, NIL); @@ -1123,6 +1124,7 @@ public: Delete(method_signature); Delete(primitive_args); Delete(doc_body); + Delete(returns_argout); Delete(returns); Delete(tmp); Delete(scheme_arg_names); @@ -1182,7 +1184,7 @@ public: Replaceall(tm, "$input", "s_0"); Replaceall(tm, "$target", name); /* Printv(f->code,tm,"\n",NIL); */ - emit_action_code(n, f, tm); + emit_action_code(n, f->code, tm); } else { throw_unhandled_guile_type_error(t); } @@ -1196,7 +1198,7 @@ public: Replaceall(tm, "$target", "gswig_result"); Replaceall(tm, "$result", "gswig_result"); /* Printv(f->code,tm,"\n",NIL); */ - emit_action_code(n, f, tm); + emit_action_code(n, f->code, tm); } else { throw_unhandled_guile_type_error(t); } diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 40c57a739..be1d6fd77 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -829,7 +829,7 @@ public: Printv(f->code, " (void)jcls;\n", NIL); // Emit all of the local variables for holding arguments. - emit_args(t, l, f); + emit_parameter_variables(l, f); /* Attach the standard typemaps */ emit_attach_parmmaps(l, f); @@ -980,27 +980,28 @@ public: } } - if (Cmp(nodeType(n), "constant") == 0) { - // Wrapping a constant hack - Swig_save("functionWrapper", n, "wrap:action", NIL); - - // below based on Swig_VargetToFunction() - SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n)); - Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value"))); - } - // Now write code to make the function call if (!native_function_flag) { - emit_action(n, f); + if (Cmp(nodeType(n), "constant") == 0) { + // Wrapping a constant hack + Swig_save("functionWrapper", n, "wrap:action", NIL); + + // below based on Swig_VargetToFunction() + SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n)); + Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value"))); + } + + // Now write code to make the function call + Swig_director_emit_dynamic_cast(n, f); + String *actioncode = emit_action(n); + // Handle exception classes specified in the "except" feature's "throws" attribute addThrows(n, "feature:except", n); - } - if (Cmp(nodeType(n), "constant") == 0) - Swig_restore(n); + if (Cmp(nodeType(n), "constant") == 0) + Swig_restore(n); - /* Return value if necessary */ - if (!native_function_flag) { - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + /* Return value if necessary */ + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { addThrows(n, "tmap:out", n); Replaceall(tm, "$source", "result"); /* deprecated */ Replaceall(tm, "$target", "jresult"); /* deprecated */ @@ -1017,6 +1018,7 @@ public: } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), Getattr(n, "name")); } + emit_return_variable(n, t, f); } /* Output argument output code */ @@ -3550,6 +3552,7 @@ public: * intermediate's upcall code */ if ((tm = Getattr(p, "tmap:jtype"))) { String *din = Copy(Getattr(p, "tmap:javadirectorin")); + addThrows(n, "tmap:javadirectorin", p); if (din) { Replaceall(din, "$module", module_class_name); @@ -3629,9 +3632,6 @@ public: // Get any Java exception classes in the throws typemap ParmList *throw_parm_list = NULL; - if ((tm = Swig_typemap_lookup_new("out", n, "", 0))) - addThrows(n, "tmap:out", n); - if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { int gencomma = 0; @@ -3661,12 +3661,6 @@ public: Append(w->def, " {"); Append(declaration, ";\n"); - /* Finish off the inherited upcall's definition */ - - Putc(')', callback_def); - generateThrowsClause(n, callback_def); - Printf(callback_def, " {\n"); - /* Emit the intermediate class's upcall to the actual class */ String *upcall = NewStringf("self.%s(%s)", symname, imcall_args); @@ -3674,14 +3668,17 @@ public: if (!is_void) { Parm *tp = NewParmFromNode(returntype, empty_str, n); - tm = Swig_typemap_lookup_new("javadirectorout", tp, "", 0); - if (tm) { + if ((tm = Swig_typemap_lookup_new("javadirectorout", tp, "", 0))) { + addThrows(n, "tmap:javadirectorout", tp); substituteClassname(returntype, tm); Replaceall(tm, "$javacall", upcall); Printf(callback_code, " return %s;\n", tm); } + if ((tm = Swig_typemap_lookup_new("out", tp, "", 0))) + addThrows(n, "tmap:out", tp); + Delete(tm); Delete(tp); } else @@ -3690,6 +3687,11 @@ public: Printf(callback_code, " }\n"); Delete(upcall); + /* Finish off the inherited upcall's definition */ + Putc(')', callback_def); + generateThrowsClause(n, callback_def); + Printf(callback_def, " {\n"); + if (!ignored_method) { /* Emit the actual upcall through */ String *imclass_desc = NewStringf("(%s)%s", jnidesc, jniret_desc); diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx index f5561bb81..a26bef356 100644 --- a/Source/Modules/lua.cxx +++ b/Source/Modules/lua.cxx @@ -362,7 +362,7 @@ public: we need to add a couple of local variables NEW LANGUAGE NOTE:END ************************************************/ Wrapper *f = NewWrapper(); - Wrapper_add_local(f, "SWIG_arg", "int SWIG_arg = -1"); + Wrapper_add_local(f, "SWIG_arg", "int SWIG_arg = 0"); String *wname = Swig_name_wrapper(iname); @@ -383,10 +383,9 @@ public: it will print int arg1; int arg2; - int result; NEW LANGUAGE NOTE:END ************************************************/ /* Write code to extract function parameters. */ - emit_args(d, l, f); + emit_parameter_variables(l, f); /* Attach the standard typemaps */ emit_attach_parmmaps(l, f); @@ -554,16 +553,15 @@ public: Setattr(n, "wrap:name", wname); /* Emit the function call */ - emit_action(n, f); + String *actioncode = emit_action(n); /* NEW LANGUAGE NOTE:*********************************************** FIXME: returns 1 if there is a void return type this is because there is a typemap for void NEW LANGUAGE NOTE:END ************************************************/ - Printv(f->code, "SWIG_arg=0;\n", NIL); // Return value if necessary - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { // managing the number of returning variables // if (numoutputs=Getattr(tm,"numoutputs")){ // int i=GetInt(tm,"numoutputs"); @@ -582,6 +580,7 @@ public: } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name); } + emit_return_variable(n, d, f); /* Output argument output code */ Printv(f->code, outarg, NIL); diff --git a/Source/Modules/modula3.cxx b/Source/Modules/modula3.cxx index 5791cca0d..edc5f736d 100644 --- a/Source/Modules/modula3.cxx +++ b/Source/Modules/modula3.cxx @@ -1304,7 +1304,7 @@ MODULA3(): Printv(f->def, " SWIGEXPORT ", c_return_type, " ", wname, "(", NIL); // Emit all of the local variables for holding arguments. - emit_args(t, l, f); + emit_parameter_variables(l, f); /* Attach the standard typemaps */ emit_attach_parmmaps(l, f); @@ -1420,17 +1420,15 @@ MODULA3(): // Now write code to make the function call if (!native_function_flag) { - emit_action(n, f); - } + String *actioncode = emit_action(n); - if (Cmp(nodeType(n), "constant") == 0) { - Swig_restore(n); - } + if (Cmp(nodeType(n), "constant") == 0) { + Swig_restore(n); + } - /* Return value if necessary */ - if (!native_function_flag) { - String *tm = getMappedTypeNew(n, "out", "result"); - if (tm != NIL) { + /* Return value if necessary */ + String *tm; + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { addThrows(throws_hash, "out", n); Replaceall(tm, "$source", "result"); /* deprecated */ Replaceall(tm, "$target", "cresult"); /* deprecated */ @@ -1441,6 +1439,7 @@ MODULA3(): } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), rawname); } + emit_return_variable(n, t, f); } /* Output argument output code */ diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx index e308aa30d..68f95ea43 100644 --- a/Source/Modules/mzscheme.cxx +++ b/Source/Modules/mzscheme.cxx @@ -271,12 +271,8 @@ public: macros. */ Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL); - // Declare return variable and arguments - // number of parameters - // they are called arg0, arg1, ... - // the return value is called result - - emit_args(d, l, f); + // Emit all of the local variables for holding arguments. + emit_parameter_variables(l, f); /* Attach the standard typemaps */ emit_attach_parmmaps(l, f); @@ -394,11 +390,10 @@ public: // Now write code to make the function call - emit_action(n, f); + String *actioncode = emit_action(n); // Now have return value, figure out what to do with it. - - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { Replaceall(tm, "$source", "result"); Replaceall(tm, "$target", "values[0]"); Replaceall(tm, "$result", "values[0]"); @@ -410,6 +405,7 @@ public: } else { throw_unhandled_mzscheme_type_error(d); } + emit_return_variable(n, d, f); // Dump the argument output code Printv(f->code, Char(outarg), NIL); @@ -539,7 +535,7 @@ public: Replaceall(tm, "$target", name); Replaceall(tm, "$input", "argv[0]"); /* Printv(f->code, tm, "\n",NIL); */ - emit_action_code(n, f, tm); + emit_action_code(n, f->code, tm); } else { throw_unhandled_mzscheme_type_error(t); } @@ -553,7 +549,7 @@ public: Replaceall(tm, "$target", "swig_result"); Replaceall(tm, "$result", "swig_result"); /* Printf (f->code, "%s\n", tm); */ - emit_action_code(n, f, tm); + emit_action_code(n, f->code, tm); } else { throw_unhandled_mzscheme_type_error(t); } diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx index 45b5bc9da..1dd368551 100755 --- a/Source/Modules/ocaml.cxx +++ b/Source/Modules/ocaml.cxx @@ -518,13 +518,8 @@ public: "argv = (CAML_VALUE *)malloc( argc * sizeof( CAML_VALUE ) );\n" "for( i = 0; i < argc; i++ ) {\n" " argv[i] = caml_list_nth(args,i);\n" "}\n", NIL); } - // Declare return variable and arguments - // number of parameters - // they are called arg0, arg1, ... - // the return value is called result - d = SwigType_typedef_qualified(d); - emit_args(d, l, f); + emit_parameter_variables(l, f); /* Attach the standard typemaps */ emit_attach_parmmaps(l, f); @@ -645,13 +640,12 @@ public: Wrapper_add_local(f, "upcall", "bool upcall = false"); Append(f->code, "upcall = (director);\n"); } + // Now write code to make the function call + Swig_director_emit_dynamic_cast(n, f); + String *actioncode = emit_action(n); - emit_action(n, f); - - // Now have return value, figure out what to do with it. - - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { Replaceall(tm, "$source", "swig_result"); Replaceall(tm, "$target", "rv"); Replaceall(tm, "$result", "rv"); @@ -660,6 +654,7 @@ public: } else { throw_unhandled_ocaml_type_error(d, "out"); } + emit_return_variable(n, d, f); // Dump the argument output code Printv(f->code, Char(outarg), NIL); @@ -810,7 +805,7 @@ public: Replaceall(tm, "$target", name); Replaceall(tm, "$input", "args"); /* Printv(f->code, tm, "\n",NIL); */ - emit_action_code(n, f, tm); + emit_action_code(n, f->code, tm); } else if ((tm = Swig_typemap_lookup_new("in", n, name, 0))) { Replaceall(tm, "$source", "args"); Replaceall(tm, "$target", name); @@ -828,14 +823,12 @@ public: Replaceall(tm, "$source", name); Replaceall(tm, "$target", "swig_result"); Replaceall(tm, "$result", "swig_result"); - /* Printf (f->code, "%s\n", tm); */ - emit_action_code(n, f, tm); + emit_action_code(n, f->code, tm); } else if ((tm = Swig_typemap_lookup_new("out", n, name, 0))) { Replaceall(tm, "$source", name); Replaceall(tm, "$target", "swig_result"); Replaceall(tm, "$result", "swig_result"); Printf(f->code, "%s\n", tm); - } else { throw_unhandled_ocaml_type_error(t, "varout/out"); } diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index cb36f0611..4bd5832bb 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -426,7 +426,7 @@ public: Printv(f->def, "static octave_value_list ", overname, " (const octave_value_list& args, int nargout) {", NIL); - emit_args(d, l, f); + emit_parameter_variables(l, f); emit_attach_parmmaps(l, f); Setattr(n, "wrap:parms", l); @@ -569,14 +569,15 @@ public: Setattr(n, "wrap:name", overname); - emit_action(n, f); + Swig_director_emit_dynamic_cast(n, f); + String *actioncode = emit_action(n); Wrapper_add_local(f, "_out", "octave_value_list _out"); Wrapper_add_local(f, "_outp", "octave_value_list *_outp=&_out"); Wrapper_add_local(f, "_outv", "octave_value _outv"); // Return the function value - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { Replaceall(tm, "$source", "result"); Replaceall(tm, "$target", "_outv"); Replaceall(tm, "$result", "_outv"); @@ -592,6 +593,7 @@ public: } else { 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); } + emit_return_variable(n, d, f); Printv(f->code, outarg, NIL); Printv(f->code, cleanup, NIL); @@ -690,7 +692,7 @@ public: if (Getattr(n, "tmap:varin:implicitconv")) { Replaceall(tm, "$implicitconv", get_implicitconv_flag(n)); } - emit_action_code(n, setf, tm); + emit_action_code(n, setf->code, tm); Delete(tm); } else { Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0)); @@ -711,7 +713,7 @@ public: Replaceall(tm, "$source", name); Replaceall(tm, "$target", "obj"); Replaceall(tm, "$result", "obj"); - addfail = emit_action_code(n, getf, tm); + addfail = emit_action_code(n, getf->code, tm); Delete(tm); } else { Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index c98b5882c..346dbaf28 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -589,7 +589,7 @@ public: Printv(f->def, "XS(", wname, ") {\n", "{\n", /* scope to destroy C++ objects before croaking */ NIL); - emit_args(d, l, f); + emit_parameter_variables(l, f); emit_attach_parmmaps(l, f); Setattr(n, "wrap:parms", l); @@ -722,9 +722,10 @@ public: /* Now write code to make the function call */ - emit_action(n, f); + Swig_director_emit_dynamic_cast(n, f); + String *actioncode = emit_action(n); - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { SwigType *t = Getattr(n, "type"); Replaceall(tm, "$source", "result"); Replaceall(tm, "$target", "ST(argvi)"); @@ -743,6 +744,7 @@ public: } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name); } + emit_return_variable(n, d, f); /* If there were any output args, take care of them. */ @@ -860,7 +862,7 @@ public: Replaceall(tm, "$target", name); Replaceall(tm, "$input", "sv"); /* Printf(setf->code,"%s\n", tm); */ - emit_action_code(n, setf, tm); + emit_action_code(n, setf->code, tm); } else { Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0)); return SWIG_NOWRAP; @@ -887,7 +889,7 @@ public: Replaceall(tm, "$shadow", "0"); } /* Printf(getf->code,"%s\n", tm); */ - addfail = emit_action_code(n, getf, tm); + addfail = emit_action_code(n, getf->code, tm); } else { Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); DelWrapper(setf); diff --git a/Source/Modules/php4.cxx b/Source/Modules/php4.cxx index 5cd5cf9ea..816a5801e 100644 --- a/Source/Modules/php4.cxx +++ b/Source/Modules/php4.cxx @@ -1007,7 +1007,7 @@ public: Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL); } - emit_args(d, l, f); + emit_parameter_variables(l, f); /* Attach standard typemaps */ emit_attach_parmmaps(l, f); @@ -1175,9 +1175,9 @@ public: Setattr(n, "wrap:name", wname); /* emit function call */ - emit_action(n, f); + String *actioncode = emit_action(n); - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { Replaceall(tm, "$input", "result"); Replaceall(tm, "$source", "result"); Replaceall(tm, "$target", "return_value"); @@ -1205,6 +1205,7 @@ public: } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name); } + emit_return_variable(n, d, f); if (outarg) { Printv(f->code, outarg, NIL); @@ -2679,24 +2680,23 @@ public: int CreateZendListDestructor(Node *n) { String *name = GetChar(Swig_methodclass(n), "name"); String *iname = GetChar(n, "sym:name"); - SwigType *d = Getattr(n, "type"); ParmList *l = Getattr(n, "parms"); String *destructorname = NewStringEmpty(); Printf(destructorname, "_%s", Swig_name_wrapper(iname)); Setattr(classnode, "destructor", destructorname); - Wrapper *df = NewWrapper(); - Printf(df->def, "/* This function is designed to be called by the zend list destructors */\n"); - Printf(df->def, "/* to typecast and do the actual destruction */\n"); - Printf(df->def, "static void %s(zend_rsrc_list_entry *rsrc, const char *type_name TSRMLS_DC) {\n", destructorname); + Wrapper *f = NewWrapper(); + Printf(f->def, "/* This function is designed to be called by the zend list destructors */\n"); + Printf(f->def, "/* to typecast and do the actual destruction */\n"); + Printf(f->def, "static void %s(zend_rsrc_list_entry *rsrc, const char *type_name TSRMLS_DC) {\n", destructorname); - Wrapper_add_localv(df, "value", "swig_object_wrapper *value=(swig_object_wrapper *) rsrc->ptr", NIL); - Wrapper_add_localv(df, "ptr", "void *ptr=value->ptr", NIL); - Wrapper_add_localv(df, "newobject", "int newobject=value->newobject", NIL); + Wrapper_add_localv(f, "value", "swig_object_wrapper *value=(swig_object_wrapper *) rsrc->ptr", NIL); + Wrapper_add_localv(f, "ptr", "void *ptr=value->ptr", NIL); + Wrapper_add_localv(f, "newobject", "int newobject=value->newobject", NIL); - emit_args(d, l, df); - emit_attach_parmmaps(l, df); + emit_parameter_variables(l, f); + emit_attach_parmmaps(l, f); // Get type of first arg, thing to be destructed // Skip ignored arguments @@ -2707,18 +2707,20 @@ public: } SwigType *pt = Getattr(p, "type"); - Printf(df->code, " efree(value);\n"); - Printf(df->code, " if (! newobject) return; /* can't delete it! */\n"); - Printf(df->code, " arg1 = (%s)SWIG_ZTS_ConvertResourceData(ptr,type_name,SWIGTYPE%s TSRMLS_CC);\n", SwigType_lstr(pt, 0), SwigType_manglestr(pt)); - Printf(df->code, " if (! arg1) zend_error(E_ERROR, \"%s resource already free'd\");\n", Char(name)); + Printf(f->code, " efree(value);\n"); + Printf(f->code, " if (! newobject) return; /* can't delete it! */\n"); + Printf(f->code, " arg1 = (%s)SWIG_ZTS_ConvertResourceData(ptr,type_name,SWIGTYPE%s TSRMLS_CC);\n", SwigType_lstr(pt, 0), SwigType_manglestr(pt)); + Printf(f->code, " if (! arg1) zend_error(E_ERROR, \"%s resource already free'd\");\n", Char(name)); Setattr(n, "wrap:name", destructorname); - emit_action(n, df); + String *actioncode = emit_action(n); + Append(f->code, actioncode); + Delete(actioncode); - Printf(df->code, "}\n"); + Printf(f->code, "}\n"); - Wrapper_print(df, s_wrappers); + Wrapper_print(f, s_wrappers); return SWIG_OK; diff --git a/Source/Modules/pike.cxx b/Source/Modules/pike.cxx index eb69ab9c3..61f6e90d7 100644 --- a/Source/Modules/pike.cxx +++ b/Source/Modules/pike.cxx @@ -288,8 +288,8 @@ public: Wrapper *f = NewWrapper(); - /* Write code to extract function parameters. */ - emit_args(d, l, f); + // Emit all of the local variables for holding arguments. + emit_parameter_variables(l, f); /* Attach the standard typemaps */ emit_attach_parmmaps(l, f); @@ -400,21 +400,21 @@ public: } /* Emit the function call */ - emit_action(n, f); + String *actioncode = emit_action(n); /* Clear the return stack */ - Printf(f->code, "pop_n_elems(args);\n"); + Printf(actioncode, "pop_n_elems(args);\n"); /* Return the function value */ if (current == CONSTRUCTOR) { - Printv(f->code, "THIS = (void *) result;\n", NIL); + Printv(actioncode, "THIS = (void *) result;\n", NIL); Printv(description, ", tVoid", NIL); } else if (current == DESTRUCTOR) { Printv(description, ", tVoid", NIL); } else { - // Wrapper_add_local(f, "resultobj", "struct object *resultobj"); Printv(description, ", ", NIL); - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { + actioncode = 0; Replaceall(tm, "$source", "result"); Replaceall(tm, "$target", "resultobj"); Replaceall(tm, "$result", "resultobj"); @@ -432,6 +432,11 @@ public: Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name); } } + if (actioncode) { + Append(f->code, actioncode); + Delete(actioncode); + } + emit_return_variable(n, d, f); /* Output argument output code */ Printv(f->code, outarg, NIL); diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 239f2405b..bb8b122d6 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1611,8 +1611,8 @@ public: Wrapper_add_local(f, "resultobj", "PyObject *resultobj = 0"); - /* Write code to extract function parameters. */ - emit_args(d, l, f); + // Emit all of the local variables for holding arguments. + emit_parameter_variables(l, f); /* Attach the standard typemaps */ emit_attach_parmmaps(l, f); @@ -1916,17 +1916,6 @@ public: } } - /* for constructor, determine if Python class has been subclassed. - * if so, create a director instance. otherwise, just create a normal instance. - */ - /* MOVED TO Swig_ConstructorToFunction() */ - /* - if (constructor && (Getattr(n, "wrap:self") != 0)) { - Wrapper_add_local(f, "subclassed", "int subclassed = 0"); - Append(f->code, "subclassed = (arg1 != Py_None);\n"); - } - */ - /* Emit the function call */ if (director_method) { Append(f->code, "try {\n"); @@ -1939,23 +1928,24 @@ public: Setattr(n, "wrap:name", wname); - emit_action(n, f); + Swig_director_emit_dynamic_cast(n, f); + String *actioncode = emit_action(n); if (director_method) { - Append(f->code, "} catch (Swig::DirectorException&) {\n"); - Append(f->code, " SWIG_fail;\n"); - Append(f->code, "}\n"); + Append(actioncode, "} catch (Swig::DirectorException&) {\n"); + Append(actioncode, " SWIG_fail;\n"); + Append(actioncode, "}\n"); } else { if (allow_thread) { - thread_end_allow(n, f->code); - Append(f->code, "}\n"); + thread_end_allow(n, actioncode); + Append(actioncode, "}\n"); } } /* This part below still needs cleanup */ /* Return the function value */ - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { if (funpack) { Replaceall(tm, "$self", "swig_obj[0]"); } else { @@ -2013,6 +2003,7 @@ public: } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name); } + emit_return_variable(n, d, f); /* Output argument output code */ Printv(f->code, outarg, NIL); @@ -2187,7 +2178,7 @@ public: if (Getattr(n, "tmap:varin:implicitconv")) { Replaceall(tm, "$implicitconv", get_implicitconv_flag(n)); } - emit_action_code(n, setf, tm); + emit_action_code(n, setf->code, tm); Delete(tm); } else { Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0)); @@ -2217,7 +2208,7 @@ public: Replaceall(tm, "$source", name); Replaceall(tm, "$target", "pyobj"); Replaceall(tm, "$result", "pyobj"); - addfail = emit_action_code(n, getf, tm); + addfail = emit_action_code(n, getf->code, tm); Delete(tm); } else { Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index ed8247e8b..570a4cead 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -354,7 +354,6 @@ protected: int outputRegistrationRoutines(File *out); int outputCommandLineArguments(File *out); - int generateCopyRoutinesObsolete(Node *n); int generateCopyRoutines(Node *n); int DumpCode(Node *n); @@ -619,7 +618,8 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { Printf(f->def, "%s %s(", rtype, funName); - emit_args(rettype, parms, f); + emit_parameter_variables(parms, f); + emit_return_variable(n, rettype, f); // emit_attach_parmmaps(parms,f); /* Using weird name and struct to avoid potential conflicts. */ @@ -630,7 +630,7 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { Wrapper_add_local(f, "r_nprotect", "int r_nprotect = 0"); // for use in converting arguments to R objects for call. Wrapper_add_local(f, "r_vmax", "char * r_vmax= 0"); // for use in converting arguments to R objects for call. - // Add local for error code in return value. This is not in emit_args because that assumes an out typemap + // Add local for error code in return value. This is not in emit_return_variable because that assumes an out typemap // whereas the type makes are reverse Wrapper_add_local(f, "ecode", "int ecode = 0"); @@ -1700,7 +1700,6 @@ int R::functionWrapper(Node *n) { ParmList *l = Getattr(n, "parms"); Parm *p; - String *returnTM = NULL; String *tm; p = l; @@ -1775,11 +1774,11 @@ int R::functionWrapper(Node *n) { Wrapper *f = NewWrapper(); Wrapper *sfun = NewWrapper(); - - int isVoidReturnType = 0; - returnTM = Swig_typemap_lookup_new("out", n, "result",0); - if(returnTM) - isVoidReturnType = (Strcmp(type, "void") == 0); + int isVoidReturnType = (Strcmp(type, "void") == 0); + // Need to use the unresolved return type since + // typedef resolution removes the const which causes a + // mismatch with the function action + emit_return_variable(n, unresolved_return_type, f); SwigType *rtype = Getattr(n, "type"); int addCopyParam = 0; @@ -1808,10 +1807,7 @@ int R::functionWrapper(Node *n) { Swig_typemap_attach_parms("scoerceout", l, f); Swig_typemap_attach_parms("scheck", l, f); - // Need to use the unresolved return type since - // typedef resolution removes the const which causes a - // mismatch with the function action - emit_args(unresolved_return_type, l, f); + emit_parameter_variables(l, f); emit_attach_parmmaps(l,f); Setattr(n,"wrap:parms",l); @@ -1989,16 +1985,9 @@ int R::functionWrapper(Node *n) { } } - - emit_action(n, f); - - - - String *outargs = NewString(""); int numOutArgs = isVoidReturnType ? -1 : 0; for(p = l, i = 0; p; i++) { - String *tm; if((tm = Getattr(p, "tmap:argout"))) { // String *lname = Getattr(p, "lname"); numOutArgs++; @@ -2017,9 +2006,10 @@ int R::functionWrapper(Node *n) { p = nextSibling(p); } + String *actioncode = emit_action(n); + /* Deal with the explicit return value. */ - if (returnTM) { - String *tm = returnTM; + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { SwigType *retType = Getattr(n, "type"); //Printf(stderr, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no"); /* if(SwigType_isarray(retType)) { @@ -2168,185 +2158,6 @@ int R::functionWrapper(Node *n) { return SWIG_OK; } - -int R::defineArrayAccessors(SwigType *type) { - - SwigType *base = SwigType_base(type); - String *rclass = NewStringf("%sArray", base); - char *prclassName = Char(rclass); - if(strncmp(prclassName, "struct ", 7) == 0) - prclassName += 7; - - Node *n = NewHash(); - Setattr(n, "type", base); - String *tm; - String *rclassName = getRClassName(base); - String *rclassBase = getRClassName(base, 0); - - String *cGetName = NewStringf("R_SWIG_%s_get_item_", prclassName); - String *cSetName = NewStringf("R_SWIG_%s_set_item_", prclassName); - - Wrapper *cGetItem = NewWrapper(); - - String *getItem = NewString(""), - *setItem = NewString(""); - - Printf(getItem, "function(x, i, j, ..., drop = TRUE) {\n"); - - Printf(getItem, "%sif(i < 1 || i > x@dims[1])\n%sstop('index must be between 1 and ', x@dims[1])\n", tab4, tab8); - Printf(getItem, "%s.Call('%s', x@ref, as.integer(i-1), PACKAGE = '%s')\n", tab4, cGetName, Rpackage); - Printf(getItem, "}\n"); - - - - Printf(setItem, "function(x, i, j, ..., value) {\n"); - - Printf(setItem, "%sif(i < 1 || i > x@dims[1])\n%sstop('index must be between 1 and ', x@dims[1])\n", tab4, tab8); - - /* Do the SCOERCEIN and the SCHECK here */ - tm = Swig_typemap_lookup_new("scoercein", n, "value", 0); - if(tm) { - Replaceall(tm, "$input", "s_value"); - Replaceall(tm, "$R_class", rclassName); - Replaceall(tm, "$*R_class", rclassBase); - - Printf(setItem, "%s%s\n", tab4, tm); - } - - tm = Swig_typemap_lookup_new("scheck", n, "value", 0); - if(tm) { - Replaceall(tm, "$input", "s_value"); - Replaceall(tm, "$R_class", rclassName); - Replaceall(tm, "$*R_class", rclassBase); - - Printf(setItem, "%s%s\n", tab4, tm); - } - - - - Printf(setItem, "%s.Call('%s', x@ref, as.integer(i-1), value, PACKAGE = '%s')\n", tab4, cSetName, Rpackage); - Printf(setItem, "%sx\n}\n", tab4); - - - - Printf(cGetItem->def, "SEXP\n%s(SEXP s_x, SEXP s_i)\n{\n", cGetName); - - String *tmp = NewStringf("%s *ptr", SwigType_lstr(base, 0)); - String *tmp1 = NewStringf("%s result", SwigType_lstr(base, 0)); - - Wrapper_add_localv(cGetItem, "r_vmax", "VMAXTYPE", "r_vmax = vmaxget()", NIL); - Wrapper_add_local(cGetItem, "ptr", tmp); - Wrapper_add_local(cGetItem, "r_ans", "SEXP r_ans"); - Wrapper_add_local(cGetItem, "result", tmp1); - Wrapper_add_local(cGetItem, "r_nprotect", "int r_nprotect = 0"); - - Printf(cGetItem->code, "ptr = (%s *) R_SWIG_resolveExternalRef(s_x, \"\", \"s_x\", 0);\n", SwigType_lstr(base, 0)); - Printf(cGetItem->code, "result = ptr[INTEGER(s_i)[0]];\n"); - - - tm = Swig_typemap_lookup_new("out", n, "result", 0); - if(tm) { - Replaceall(tm, "$result", "r_ans"); - Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); - Printf(cGetItem->code, "%s\n", tm); - } - - Delete(tmp); Delete(tmp1); - - Printf(cGetItem->code, "%s\nreturn r_ans;\n}\n\n", UnProtectWrapupCode); - - - /******************************/ - /* - R_SWIG_..._set_item(SEXP x, SEXP s_i, SEXP s_value) { - char *r_vmax = vmaxget(); - int r_nprotect = 0; - type *ptr, *el, value; - - ptr = (type *) R_SWIG_resolveExternalRef(s_x, "", "s_x", 0); - - ptr[INTEGER(s_i)[0]] = *el; - - cleanup - return - } - */ - Wrapper *cSetItem = NewWrapper(); - { - - Printf(cSetItem->def, "SEXP\n%s(SEXP s_x, SEXP s_i, SEXP s_value)\n{\n", cSetName); - - tmp = NewStringf("%s *ptr", SwigType_lstr(base, 0)); - tmp1 = NewStringf("%s value", SwigType_lstr(base, 0)); - - Wrapper_add_localv(cSetItem, "r_vmax", "VMAXTYPE", "r_vmax = vmaxget()", NIL); - Wrapper_add_local(cSetItem, "r_nprotect", "int r_nprotect = 0"); - - Wrapper_add_local(cSetItem, "ptr", tmp); - Wrapper_add_local(cSetItem, "value", tmp1); - Replaceall(tmp, "*ptr", "*el = &value"); - Wrapper_add_local(cSetItem, "el", tmp); - - Printf(cSetItem->code, - "ptr = (%s *) R_SWIG_resolveExternalRef(s_x, \"\", \"s_x\", 0);\n", - SwigType_lstr(base, 0)); - - - String *tm = Swig_typemap_lookup_new("in", n, "value", 0); - if(tm) { - String *rclassName = getRClassName(base); - String *rclassBase = getRClassName(base, 0); - Replaceall(tm, "$input", "s_value"); - Replaceall(tm, "$*1", "value"); - //XXX think about what we really mean here. - Replaceall(tm, "$1", "el"); - - Replaceall(tm, "$R_class", rclassName); - Replaceall(tm, "$*R_class", rclassBase); - - Printf(cSetItem->code, "%s\n", tm); - - Delete(rclassName); Delete(rclassBase); - } - Printf(cSetItem->code, "ptr[INTEGER(s_i)[0]] = *el;\n"); - } - Printf(cSetItem->code, "%s\nreturn R_NilValue;\n}\n\n", UnProtectWrapupCode); - - /*************************/ - - - Wrapper_print(cGetItem, f_wrapper); - Wrapper_print(cSetItem, f_wrapper); - - String *elClass = NewStringf("_p%s", SwigType_manglestr(base)); - if(!Getattr(SClassDefs, elClass)) { - if (debugMode) - Printf(stderr, " Defining class %s\n", elClass); - Printf(s_classes, "setClass('%s', contains = 'ExternalReference')\n", elClass); - //Add to namespace - Setattr(SClassDefs, elClass, elClass); - } - Delete(elClass); - - if(!Getattr(SClassDefs, rclassName)) { - Setattr(SClassDefs, rclassName, rclassName); - Printf(s_classes, "setClass('%s', contains = 'SWIGArray')\n", rclassName); - } - - Printf(s_classes, "setMethod('[', '%s',\n%s)\n", rclassName, getItem); - Printf(s_classes, "setMethod('[<-', '%s',\n%s)\n", rclassName, setItem); - - - Delete(n); - DelWrapper(cGetItem); - DelWrapper(cSetItem); - Delete(rclass); - Delete(cGetName); - - return SWIG_OK; -} - - /***************************************************** Add the specified routine name to the collection of generated routines that are called from R functions. @@ -2583,219 +2394,6 @@ int R::classDeclaration(Node *n) { in all cases. */ -// This procedure is for reference -int R::generateCopyRoutinesObsolete(Node *n) { - Wrapper *toC = NewWrapper(); - Wrapper *toCRef = NewWrapper(); - Wrapper *toR = NewWrapper(); - - Wrapper *copyToR = NewWrapper(); - Wrapper *copyToC = NewWrapper(); - - - String *name = Getattr(n, "name"); - String *tdname = Getattr(n, "tdname"); - String *kind = Getattr(n, "kind"); - String *type; - - if(Len(tdname)) { - type = Copy(tdname); - } else { - type = NewStringf("%s %s", kind, name); - } - - -#ifdef R_SWIG_VERBOSE - if (debugMode) - Printf(stderr, "generateCopyRoutines: name = %s, %s\n", name, type); -#endif - - String *rclassNameRef = getRClassName(type, 1); - String *copyRefRefName = NewStringf("R_swig_copy_%sRef_%sRef", rclassNameRef, rclassNameRef); - String *toCName = NewStringf("R_swig_copy_%sRef_to_C", name); - String *toRName = NewStringf("R_swig_copy_%sRef_to_R", name); - - addRegistrationRoutine(copyRefRefName, 2); - addRegistrationRoutine(toCName, 2); - addRegistrationRoutine(toRName, 1); - - Printf(toC->def, "int\n%s(SEXP sobj, %s *value)", toCName, type); - Printf(toR->def, "SEXP\n%s(%s *value)", toRName, type); - Printf(toCRef->def, "SEXP\n%s(SEXP s_src, SEXP s_dest) {", copyRefRefName); - - Delete(toCName); - Delete(toRName); - - String *tmp = NewStringf("%s *src", type); - Wrapper_add_local(toCRef, "src", tmp); - Delete(tmp); - tmp = NewStringf("%s *dest", type); - Wrapper_add_local(toCRef, "dest", tmp); - Delete(tmp); - - Printf(toCRef->code, "src = (%s *) R_SWIG_resolveExternalRef(s_src, \"%sRef\", \"s_src\", (Rboolean) FALSE);\n", - type, rclassNameRef); - Printf(toCRef->code, "dest = (%s *) R_SWIG_resolveExternalRef(s_dest, \"%sRef\", \"s_dest\", (Rboolean) FALSE);\n", - type, rclassNameRef); - Printf(toCRef->code, "memcpy(dest, src, sizeof(*src));\nreturn R_NilValue;\n}\n\n"); - - - - Wrapper_add_localv(toR, "r_obj", "SEXP", "r_obj", NIL); - Wrapper_add_localv(toR, "r_vmax", "VMAXTYPE", "r_vmax = vmaxget()", NIL); - Wrapper_add_localv(toR, "_tmp_sexp", "SEXP", "_tmp_sexp", NIL); - Wrapper_add_local(toR, "r_nprotect", "int r_nprotect = 0"); - Wrapper_add_local(toC, "ecode", "int ecode = 0"); - - Printf(copyToR->def, "%sCopyToR = function(value, obj = new(\"%s\"))\n{\n", name, name); - Printf(copyToC->def, "%sCopyToC = function(value, obj)\n{\n", name); - - - Printf(toR->code, "Rf_protect(r_obj = NEW_OBJECT(MAKE_CLASS(\"%s\")));\nr_nprotect++;\n\n", name); - - Wrapper_add_localv(toC, "_tmp_sexp", "SEXP", "_tmp_sexp", NIL); - - Node *c = firstChild(n); - // Swig_typemap_attach_parms("in", c, toR); - // Swig_typemap_attach_parms("out", c, toR); - - for(; c; c = nextSibling(c)) { - String *elName = Getattr(c, "name"); - if (!Len(elName)) { - continue; - } - String *tp = Swig_typemap_lookup_new("rtype", c, "", 0); - if(!tp) { - continue; - } - /* The S functions to get and set the member value. */ - String *symname = Getattr(c, "sym:name"); - String *ClassPrefix = Getattr(n, "sym:name"); - String *get = Swig_name_get(Swig_name_member(Char(ClassPrefix), symname)); - String *set = Swig_name_set(Swig_name_member(Char(ClassPrefix), symname)); - - -#if 0 - This is already done now in getRType(). - If that for some reason no longer gets called, this had better go back. - SwigType *elTT = Getattr(c, "type"); - SwigType *decl = Getattr(c, "decl"); - SwigType_push(elTT, decl); -#endif - - String *elNameT = replaceInitialDash(elName); - Printf(copyToR->code, "obj@%s = %s(value)\n", elNameT, get); - Printf(copyToC->code, "%s(obj, value@%s)\n", set, elNameT); - String *field = NewStringf("value->%s", elNameT); - Delete(elNameT); - SwigType *elType = Getattr(c, "type"); - - - String *tm = Swig_typemap_lookup_new("out", c, field, 0); - if(tm) { -#ifdef R_SWIG_VERBOSE - if (debugMode) - Printf(stderr, "Got conversion to R for '%s': '%s' '%s' -> '%s'\n", elName, elType, elTT, tm); -#endif - - //XXX Get the field in as the rhs. - // What about looking in the "memberin"/"memberout" typemaps. - Replaceall(tm, "$1", Char(field)); - Replaceall(tm, "$result", "_tmp_sexp"); - Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); - replaceRClass(tm,elType); - - - Printf(toR->code, "%s\nRf_protect(_tmp_sexp);\nr_nprotect++;\n", tm); - Printf(toR->code, "Rf_protect(r_obj = R_do_slot_assign(r_obj, Rf_mkString(\"%s\"), _tmp_sexp));\nr_nprotect++;\n\n", elName); - } else { - Printf(stderr, "*** Can't convert field %s in \n", elName); - } - - - - char *field_p = Char(field); - tm = Swig_typemap_lookup_new("in", c, field_p, 0); - if(tm && !GetFlag(c, "feature:immutable")) { - replaceRClass(tm,elType); - if (debugMode) - Printf(stderr, "typemap (in) for %s => %s\n", - SwigType_str(elType, 0), tm); - String *tmp1 = - NewStringf("%s val", SwigType_lstr(elType, 0)); - Wrapper_add_local(toC, "val", tmp1); - Replaceall(tm, "$input", "_tmp_sexp"); - if (debugMode) - Printf(stderr, "Got conversion to C for %s: %s. %s\n", - elName, tm, field); -#ifdef R_SWIG_VERBOSE -#endif - Printf(toC->code, "_tmp_sexp = GET_SLOT(sobj, Rf_mkString(\"%s\"));\n%s\n\n", elName, tm); - Delete(field); - } - /* - - Replaceall(conversion, "$1", field); - Printf(toC->code, "value->%s = ;\n", name); - */ - } - - Printv(toR->code, UnProtectWrapupCode, - "\nreturn(r_obj);\n}\n", NIL); - - Printf(toC->code, "\nreturn(1);\n}\n"); - - - Printf(f_wrapper, "%s;\n", toR->def); - Printf(f_wrapper, "%s;\n", toC->def); - - Printf(toR->def, "\n{\n"); - Printf(toC->def, "\n{\n"); - - String *rclassName = getRClassName(type, 0); // without the Ref. - - Printf(copyToR->code, "obj\n}\n\n"); - - Printf(sfile, "# Start definition of copy functions & methods for %s\n", rclassName); - - Wrapper_print(copyToR, sfile); - Printf(copyToC->code, "obj\n}\n\n"); - Wrapper_print(copyToC, sfile); - - - Printf(sfile, "# Start definition of copy methods for %s\n", rclassName); - Printf(sfile, "setMethod('copyToR', '%sRef', %sCopyToR)\n", rclassName, name); - Printf(sfile, "setMethod('copyToC', '%s', %sCopyToC)\n\n", rclassName, name); - Printv(sfile, "setMethod('copyToC', c('", rclassName, "Ref', '", rclassName, "Ref'),", - " function(value, obj) {\n", - tab4, ".Call(\"", copyRefRefName, "\", value, obj, PACKAGE = \"", - Rpackage, "\")\n})\n\n", NIL); - Printf(sfile, "# End definition of copy methods for %s\n", rclassName); - Printf(sfile, "# End definition of copy functions & methods for %s\n", rclassName); - - String *m = NewStringf("%sCopyToR", name); - addNamespaceMethod(m); - char *tt = Char(m); tt[Len(m)-1] = 'C'; - addNamespaceMethod(m); - Delete(m); - - - Delete(rclassName); - - DelWrapper(copyToR); - DelWrapper(copyToC); - - Wrapper_print(toR, f_wrapper); - Wrapper_print(toC, f_wrapper); - Wrapper_print(toCRef, f_wrapper); - - DelWrapper(toR); - DelWrapper(toC); - DelWrapper(toCRef); - - return SWIG_OK; -} - int R::generateCopyRoutines(Node *n) { Wrapper *copyToR = NewWrapper(); Wrapper *copyToC = NewWrapper(); diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 96165ae9b..399f74424 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -1649,7 +1649,7 @@ public: /* Emit arguments */ if (current != CONSTRUCTOR_ALLOCATE) { - emit_args(t, l, f); + emit_parameter_variables(l, f); } /* Attach standard typemaps */ @@ -1773,72 +1773,79 @@ public: Setattr(n, "wrap:name", wname); - emit_action(n, f); + Swig_director_emit_dynamic_cast(n, f); + String *actioncode = emit_action(n); if (director_method) { - Printf(f->code, "} catch (Swig::DirectorException& e) {\n"); - Printf(f->code, " rb_exc_raise(e.getError());\n"); - Printf(f->code, " SWIG_fail;\n"); - Printf(f->code, "}\n"); + Printf(actioncode, "} catch (Swig::DirectorException& e) {\n"); + Printf(actioncode, " rb_exc_raise(e.getError());\n"); + Printf(actioncode, " SWIG_fail;\n"); + Printf(actioncode, "}\n"); } - } - /* Return value if necessary */ - if (SwigType_type(t) != T_VOID && current != CONSTRUCTOR_ALLOCATE && current != CONSTRUCTOR_INITIALIZE) { - need_result = 1; - if (GetFlag(n, "feature:predicate")) { - Printv(f->code, tab4, "vresult = (result ? Qtrue : Qfalse);\n", NIL); - } else { - tm = Swig_typemap_lookup_new("out", n, "result", 0); - if (tm) { - Replaceall(tm, "$result", "vresult"); - Replaceall(tm, "$source", "result"); - Replaceall(tm, "$target", "vresult"); + /* Return value if necessary */ + if (SwigType_type(t) != T_VOID && current != CONSTRUCTOR_INITIALIZE) { + need_result = 1; + if (GetFlag(n, "feature:predicate")) { + Printv(actioncode, tab4, "vresult = (result ? Qtrue : Qfalse);\n", NIL); + } else { + tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode); + actioncode = 0; + if (tm) { + Replaceall(tm, "$result", "vresult"); + Replaceall(tm, "$source", "result"); + Replaceall(tm, "$target", "vresult"); - if (GetFlag(n, "feature:new")) - Replaceall(tm, "$owner", "SWIG_POINTER_OWN"); - else - Replaceall(tm, "$owner", "0"); + if (GetFlag(n, "feature:new")) + Replaceall(tm, "$owner", "SWIG_POINTER_OWN"); + else + Replaceall(tm, "$owner", "0"); #if 1 - // FIXME: this will not try to unwrap directors returned as non-director - // base class pointers! + // FIXME: this will not try to unwrap directors returned as non-director + // base class pointers! - /* New addition to unwrap director return values so that the original - * Ruby object is returned instead. - */ - bool unwrap = false; - String *decl = Getattr(n, "decl"); - int is_pointer = SwigType_ispointer_return(decl); - int is_reference = SwigType_isreference_return(decl); - if (is_pointer || is_reference) { - String *type = Getattr(n, "type"); - Node *parent = Swig_methodclass(n); - Node *modname = Getattr(parent, "module"); - Node *target = Swig_directormap(modname, type); - if (target) - unwrap = true; - } - if (unwrap) { - Wrapper_add_local(f, "director", "Swig::Director *director = 0"); - Printf(f->code, "director = dynamic_cast(result);\n"); - Printf(f->code, "if (director) {\n"); - Printf(f->code, " vresult = director->swig_get_self();\n"); - Printf(f->code, "} else {\n"); - Printf(f->code, "%s\n", tm); - Printf(f->code, "}\n"); - director_method = 0; - } else { - Printf(f->code, "%s\n", tm); - } + /* New addition to unwrap director return values so that the original + * Ruby object is returned instead. + */ + bool unwrap = false; + String *decl = Getattr(n, "decl"); + int is_pointer = SwigType_ispointer_return(decl); + int is_reference = SwigType_isreference_return(decl); + if (is_pointer || is_reference) { + String *type = Getattr(n, "type"); + Node *parent = Swig_methodclass(n); + Node *modname = Getattr(parent, "module"); + Node *target = Swig_directormap(modname, type); + if (target) + unwrap = true; + } + if (unwrap) { + Wrapper_add_local(f, "director", "Swig::Director *director = 0"); + Printf(f->code, "director = dynamic_cast(result);\n"); + Printf(f->code, "if (director) {\n"); + Printf(f->code, " vresult = director->swig_get_self();\n"); + Printf(f->code, "} else {\n"); + Printf(f->code, "%s\n", tm); + Printf(f->code, "}\n"); + director_method = 0; + } else { + Printf(f->code, "%s\n", tm); + } #else - Printf(f->code, "%s\n", tm); + Printf(f->code, "%s\n", tm); #endif - Delete(tm); - } else { - Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s.\n", SwigType_str(t, 0)); - } + Delete(tm); + } else { + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s.\n", SwigType_str(t, 0)); + } + } } + if (actioncode) { + Append(f->code, actioncode); + Delete(actioncode); + } + emit_return_variable(n, t, f); } /* Extra code needed for new and initialize methods */ @@ -2108,7 +2115,7 @@ public: Replaceall(tm, "$target", "_val"); Replaceall(tm, "$source", name); /* Printv(getf->code,tm, NIL); */ - addfail = emit_action_code(n, getf, tm); + addfail = emit_action_code(n, getf->code, tm); } else { Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); } @@ -2140,7 +2147,7 @@ public: Replaceall(tm, "$source", "_val"); Replaceall(tm, "$target", name); /* Printv(setf->code,tm,"\n",NIL); */ - emit_action_code(n, setf, tm); + emit_action_code(n, setf->code, tm); } else { Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s\n", SwigType_str(t, 0)); } diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index 53a40be9b..5835c6362 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -310,7 +310,8 @@ private: }; int SWIG_main(int, char **, Language *); -void emit_args(SwigType *, ParmList *, Wrapper *f); +void emit_parameter_variables(ParmList *l, Wrapper *f); +void emit_return_variable(Node *n, SwigType *rt, Wrapper *f); void SWIG_exit(int); /* use EXIT_{SUCCESS,FAILURE} */ void SWIG_config_file(const String_or_char *); const String *SWIG_output_directory(); @@ -322,8 +323,8 @@ int emit_num_required(ParmList *); int emit_isvarargs(ParmList *); void emit_attach_parmmaps(ParmList *, Wrapper *f); void emit_mark_varargs(ParmList *l); -void emit_action(Node *n, Wrapper *f); -int emit_action_code(Node *n, Wrapper *f, String *action); +String *emit_action(Node *n); +int emit_action_code(Node *n, String *wrappercode, String *action); void Swig_overload_check(Node *n); String *Swig_overload_dispatch(Node *n, const String_or_char *fmt, int *); String *Swig_overload_dispatch_cast(Node *n, const String_or_char *fmt, int *); @@ -337,6 +338,7 @@ String *Swig_class_name(Node *n); String *Swig_method_call(String_or_char *name, ParmList *parms); String *Swig_method_decl(SwigType *rtype, SwigType *decl, const String_or_char *id, List *args, int strip, int values); String *Swig_director_declaration(Node *n); +void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f); /* directors.cxx end */ extern "C" { diff --git a/Source/Modules/tcl8.cxx b/Source/Modules/tcl8.cxx index c2ce79b49..3ac4896e9 100644 --- a/Source/Modules/tcl8.cxx +++ b/Source/Modules/tcl8.cxx @@ -303,8 +303,8 @@ public: Printv(f->def, "SWIGINTERN int\n ", wname, "(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {", NIL); - /* Print out variables for storing arguments. */ - emit_args(type, parms, f); + // Emit all of the local variables for holding arguments. + emit_parameter_variables(parms, f); /* Attach standard typemaps */ emit_attach_parmmaps(parms, f); @@ -443,12 +443,12 @@ public: } /* Now write code to make the function call */ - emit_action(n, f); + String *actioncode = emit_action(n); /* Need to redo all of this code (eventually) */ /* Return value if necessary */ - if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) { + if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { Replaceall(tm, "$source", "result"); #ifdef SWIG_USE_RESULTOBJ Replaceall(tm, "$target", "resultobj"); @@ -466,6 +466,7 @@ public: } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), name); } + emit_return_variable(n, type, f); /* Dump output argument code */ Printv(f->code, outarg, NIL); @@ -570,7 +571,7 @@ public: Replaceall(tm, "$target", "value"); Replaceall(tm, "$result", "value"); /* Printf(getf->code, "%s\n",tm); */ - addfail = emit_action_code(n, getf, tm); + addfail = emit_action_code(n, getf->code, tm); Printf(getf->code, "if (value) {\n"); Printf(getf->code, "Tcl_SetVar2(interp,name1,name2,Tcl_GetStringFromObj(value,NULL), flags);\n"); Printf(getf->code, "Tcl_DecrRefCount(value);\n"); @@ -610,7 +611,7 @@ public: Printf(setf->code, "Tcl_DecrRefCount(name1o);\n"); Printf(setf->code, "if (!value) SWIG_fail;\n"); /* Printf(setf->code,"%s\n", tm); */ - emit_action_code(n, setf, tm); + emit_action_code(n, setf->code, tm); Printf(setf->code, "return NULL;\n"); Printf(setf->code, "fail:\n"); Printf(setf->code, "return \"%s\";\n", iname); diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index f58ebea96..2d34eabee 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -373,6 +373,7 @@ extern int ParmList_is_compactdefargs(ParmList *p); String_or_char *source, String_or_char *target, Wrapper *f); extern String *Swig_typemap_lookup_new(const String_or_char *op, Node *n, const String_or_char *lname, Wrapper *f); + extern String *Swig_typemap_lookup_out(const String_or_char *op, Node *n, const String_or_char *lname, Wrapper *f, String *actioncode); extern void Swig_typemap_attach_kwargs(Hash *tm, const String_or_char *op, Parm *p); extern void Swig_typemap_new_scope(void); extern Hash *Swig_typemap_pop_scope(void); diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index 5ad4fb485..bcce87594 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -802,10 +802,11 @@ int check_locals(ParmList *p, const char *s) { } static -void typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index) { +int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index) { char var[512]; char *varname; SwigType *ftype; + int bare_substitution_count = 0; Replaceall(s, "$typemap", "$TYPEMAP"); @@ -1086,8 +1087,9 @@ void typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType /* Replace the bare $n variable */ sprintf(var, "$%d", index); - Replace(s, var, lname, DOH_REPLACE_ANY); + bare_substitution_count = Replace(s, var, lname, DOH_REPLACE_ANY); Delete(ftype); + return bare_substitution_count; } /* ------------------------------------------------------------------------ @@ -1230,11 +1232,11 @@ String *Swig_typemap_lookup(const String_or_char *op, SwigType *type, String_or_ * Attach one or more typemaps to a node * op - typemap name, eg "out", "newfree" * node - the node to attach the typemaps to - * lname - - * f - + * lname - name of variable to substitute $1, $2 etc for + * f - wrapper code to generate into * ----------------------------------------------------------------------------- */ -String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const String_or_char *lname, Wrapper *f) { +static String *Swig_typemap_lookup_new_impl(const String_or_char *op, Node *node, const String_or_char *lname, Wrapper *f, String *actioncode) { SwigType *type; SwigType *mtype = 0; String *pname; @@ -1248,6 +1250,10 @@ String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const Stri String *cname = 0; String *clname = 0; char *cop = Char(op); + int optimal_attribute = 0; + int optimal_substitution = 0; + int num_substitutions = 0; + /* special case, we need to check for 'ref' call and set the default code 'sdef' */ if (node && Cmp(op, "newfree") == 0) { @@ -1297,6 +1303,66 @@ String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const Stri s = Copy(s); /* Make a local copy of the typemap code */ + /* Attach kwargs - ie the typemap attributes */ + kw = Getattr(tm, "kwargs"); + while (kw) { + String *value = Copy(Getattr(kw, "value")); + String *type = Getattr(kw, "type"); + char *ckwname = Char(Getattr(kw, "name")); + if (type) { + String *mangle = Swig_string_mangle(type); + Append(value, mangle); + Delete(mangle); + } + sprintf(temp, "%s:%s", cop, ckwname); + Setattr(node, tmop_name(temp), value); + if (Cmp(temp, "out:optimal") == 0) + optimal_attribute = (Cmp(value, "0") != 0) ? 1 : 0; + Delete(value); + kw = nextSibling(kw); + } + + if (optimal_attribute) { + /* Note: "out" typemap is the only typemap that will have the "optimal" attribute set. + * If f and actioncode are NULL, then the caller is just looking to attach the "out" attributes + * ie, not use the typemap code, otherwise both f and actioncode must be non null. */ + if (actioncode) { + clname = Copy(actioncode); + /* check that the code in the typemap can be used in this optimal way. + * The code should be in the form "result = ...;\n". We need to extract + * the "..." part. This may not be possible for various reasons, eg + * code added by %exception. This optimal code generation is bit of a + * hack and circumvents the normal requirement for a temporary variable + * to hold the result returned from a wrapped function call. + */ + if (Strncmp(clname, "result = ", 9) == 0) { + int numreplacements = Replace(clname, "result = ", "", DOH_REPLACE_ID_BEGIN); + if (numreplacements == 1) { + numreplacements = Replace(clname, ";\n", "", DOH_REPLACE_ID_END); + if (numreplacements == 1) { + if (Strchr(clname, ';') == 0) { + lname = clname; + actioncode = 0; + optimal_substitution = 1; + } + } + } + } + if (!optimal_substitution) { + Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(node), Getline(node), "Method %s usage of the optimal attribute in the out typemap at %s:%d ignored as the following cannot be used to generate optimal code: %s\n", Swig_name_decl(node), Getfile(s), Getline(s), clname); + Delattr(node, "tmap:out:optimal"); + } + } else { + assert(!f); + } + } + if (actioncode) { + assert(f); + Append(f->code, actioncode); + } + + /* emit local variables declared in typemap, eg emit declarations for aa and bb in: + * %typemap(in) foo (int aa, int bb) "..." */ locals = Getattr(tm, "locals"); if (locals) locals = CopyParmList(locals); @@ -1313,19 +1379,17 @@ String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const Stri } if (mtype && SwigType_isarray(mtype)) { - typemap_replace_vars(s, locals, mtype, type, pname, (char *) lname, 1); + num_substitutions = typemap_replace_vars(s, locals, mtype, type, pname, (char *) lname, 1); } else { - typemap_replace_vars(s, locals, type, type, pname, (char *) lname, 1); + num_substitutions = typemap_replace_vars(s, locals, type, type, pname, (char *) lname, 1); } + if (optimal_substitution && num_substitutions > 1) + Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(node), Getline(node), "Multiple calls to %s might be generated due to optimal attribute usage in the out typemap at %s:%d.\n", Swig_name_decl(node), Getfile(s), Getline(s)); if (locals && f) { typemap_locals(s, locals, f, -1); } replace_embedded_typemap(s); - /* { - String *tmname = Getattr(tm,"typemap"); - if (tmname) Replace(s,"$typemap",tmname, DOH_REPLACE_ANY); - } */ Replace(s, "$name", pname, DOH_REPLACE_ANY); @@ -1346,23 +1410,6 @@ String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const Stri Setattr(node, tmop_name(temp), "1"); } - /* Attach kwargs */ - kw = Getattr(tm, "kwargs"); - while (kw) { - String *value = Copy(Getattr(kw, "value")); - String *type = Getattr(kw, "type"); - char *ckwname = Char(Getattr(kw, "name")); - if (type) { - String *mangle = Swig_string_mangle(type); - Append(value, mangle); - Delete(mangle); - } - sprintf(temp, "%s:%s", cop, ckwname); - Setattr(node, tmop_name(temp), value); - Delete(value); - kw = nextSibling(kw); - } - /* Look for warnings */ { String *w; @@ -1387,21 +1434,30 @@ String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const Stri } } - if (cname) - Delete(cname); - if (clname) - Delete(clname); - if (mtype) - Delete(mtype); + Delete(cname); + Delete(clname); + Delete(mtype); if (sdef) { /* put 'ref' and 'newfree' codes together */ String *p = NewStringf("%s\n%s", sdef, s); Delete(s); Delete(sdef); s = p; } + Delete(actioncode); return s; } +String *Swig_typemap_lookup_out(const String_or_char *op, Node *node, const String_or_char *lname, Wrapper *f, String *actioncode) { + assert(actioncode); + assert(Cmp(op, "out") == 0); + return Swig_typemap_lookup_new_impl(op, node, lname, f, actioncode); +} + +String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const String_or_char *lname, Wrapper *f) { + return Swig_typemap_lookup_new_impl(op, node, lname, f, 0); +} + + /* ----------------------------------------------------------------------------- * Swig_typemap_attach_kwargs() *