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
@@ -2006,6 +2007,10 @@ $symname - Name of function/method being wrapped
+
+The "out" typemap supports an optional attribute flag called "optimal". This is for code optimisation and is detailed in the Optimal code generation when returning by value section.
+
+
10.5.4 "arginit" typemap
@@ -2619,7 +2624,194 @@ The example above also shows a common approach of issuing a warning for an as ye
%typemap(ruby,in) int "$1 = NUM2INT($input);".
-10.8 Multi-argument typemaps
+10.8 Optimal code generation when returning by value
+
+
+
+The "out" typemap is the main typemap for return types.
+This typemap supports an optional attribute flag called "optimal", which is for reducing
+temporary variables and the amount of generated code.
+It only really makes a difference when returning objects by value and it cannot always be used,
+as explained later on.
+
+
+
+When a function returns an object by value, SWIG generates code that instantiates the default
+type on the stack then assigns the value returned by the function call to it.
+A copy of this object is then made on the heap and this is what is ultimately stored and
+used from the target language.
+This will be clearer considering an example.
+Consider running the following code through SWIG:
+
+
+
+
+%typemap(out) SWIGTYPE %{
+ $result = new $1_ltype((const $1_ltype &)$1);
+%}
+
+%inline %{
+#include
+using namespace std;
+
+struct XX {
+ XX() { cout << "XX()" << endl; }
+ XX(int i) { cout << "XX(" << i << ")" << endl; }
+ XX(const XX &other) { cout << "XX(const XX &)" << endl; }
+ XX & operator =(const XX &other) { cout << "operator=(const XX &)" << endl; return *this; }
+ ~XX() { cout << "~XX()" << endl; }
+ static XX create() {
+ return XX(0);
+ }
+};
+%}
+
+
+
+
+The "out" typemap shown is the default typemap for C# when returning by objects by value.
+When making a call to XX::create() from C#, the output is as follows:
+
+
+
+
+XX()
+XX(0)
+operator=(const XX &)
+~XX()
+XX(const XX &)
+~XX()
+~XX()
+
+
+
+
+Note that three objects are being created as well as an assignment.
+Wouldn't it be great if the XX::create() method was the only time a constructor was called?
+As the method returns by value, this is asking a lot and the code that SWIG generates by default
+makes it impossible for the compiler to make this type of optimisation.
+However, this is where the "optimal" attribute in the "out" typemap can help out.
+If the typemap code is kept the same and just the "optimal" attribute specified like this:
+
+
+
+
+%typemap(out, optimal="1") SWIGTYPE %{
+ $result = new $1_ltype((const $1_ltype &)$1);
+%}
+
+
+
+
+then when the code is run again, the output is simply:
+
+
+
+
+
+How the "optimal" attribute works is best explained using the generated code.
+Without "optimal", the generated code is:
+
+
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() {
+ void * jresult ;
+ XX result;
+ result = XX::create();
+ jresult = new XX((const XX &)result);
+ return jresult;
+}
+
+
+
+
+
+With the "optimal" attribute, the code is:
+
+
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() {
+ void * jresult ;
+ jresult = new XX((const XX &)XX::create());
+ return jresult;
+}
+
+
+
+
+The major difference is the result temporary variable holding the value returned from XX::create() is no longer generated and instead the copy constructor call is made directly from
+the value returned by XX::create().
+With modern compiler optimisations turned on, the copy is not actually done, in fact the object is never created
+on the stack in XX::create() at all, it is simply created directly on the heap.
+In the first instance, the $1 special variable in the typemap is expanded into result.
+In the second instance, $1 is expanded into XX::create() and this is essentially
+what the "optimal" attribute is telling SWIG to do.
+
+
+
+This kind of optimisation is not turned on by default as it has a number of restrictions.
+Firstly, some code cannot be condensed into a simple call for passing into the copy constructor.
+One common occurrence is when %exception is used.
+Consider adding the following %exception to the example:
+
+
+
+
+%exception XX::create() %{
+try {
+ $action
+} catch(const std::exception &e) {
+ cout << e.what() << endl;
+}
+%}
+
+
+
+
+SWIG can detect when the "optimal" attribute cannot be used and will ignore it and in this case will issue the following warning:
+
+
+
+
+example.i:28: Warning(474): Method XX::create() usage of the optimal attribute in the out
+typemap at example.i:14 ignored as the following cannot be used to generate optimal code:
+try {
+ result = XX::create();
+} catch(const std::exception &e) {
+ cout << e.what() << endl;
+}
+
+
+
+
+It should be clear that the above code cannot be used as the argument to the copy constructor call, ie for the $1 substitution.
+
+
+
+Secondly, if the typemaps uses $1 more than once, then multiple calls to the wrapped function
+will be made. Obviously that is not very optimal.
+In fact SWIG attempts to detect this and will issue a warning something like:
+
+
+
+
+example.i:21: Warning(475): Multiple calls to XX::create() might be generated due to
+optimal attribute usage in the out typemap at example.i:7.
+
+
+
+
+However, it doesn't always get it right, for example when $1 is within some commented out code.
+
+
+10.9 Multi-argument typemaps
@@ -2884,7 +3076,7 @@ when crossing languages you may need to worry about issues such as row-major vs.
ordering (and perform conversions if needed).
-10.9 The run-time type checker
+10.10 The run-time type checker
@@ -2910,7 +3102,7 @@ language modules.
Modules can be unloaded from the type system.
-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()
*