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
This commit is contained in:
William S Fulton 2008-05-14 22:12:31 +00:00
commit 336b50b43d
39 changed files with 726 additions and 833 deletions

View file

@ -1,6 +1,12 @@
Version 1.3.36 (in progress) 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 05/11/2008: olly
[PHP] Check for %feature("notabstract") when generating PHP5 class [PHP] Check for %feature("notabstract") when generating PHP5 class
wrapper. wrapper.

View file

@ -379,6 +379,7 @@
<li><a href="Typemaps.html#Typemaps_nn41">Implementing constraints with typemaps</a> <li><a href="Typemaps.html#Typemaps_nn41">Implementing constraints with typemaps</a>
</ul> </ul>
<li><a href="Typemaps.html#Typemaps_nn43">Typemaps for multiple languages</a> <li><a href="Typemaps.html#Typemaps_nn43">Typemaps for multiple languages</a>
<li><a href="Typemaps.html#Typemaps_optimal">Optimal code generation when returning by value</a>
<li><a href="Typemaps.html#Typemaps_nn42">Multi-argument typemaps</a> <li><a href="Typemaps.html#Typemaps_nn42">Multi-argument typemaps</a>
<li><a href="Typemaps.html#runtime_type_checker">The run-time type checker</a> <li><a href="Typemaps.html#runtime_type_checker">The run-time type checker</a>
<ul> <ul>
@ -761,7 +762,7 @@
<li><a href="Java.html#typeunsafe_enums_classes">Type unsafe enum classes</a> <li><a href="Java.html#typeunsafe_enums_classes">Type unsafe enum classes</a>
</ul> </ul>
</ul> </ul>
<li><a href="Java.html#java_directors">Cross language polymorphism using directors (experimental)</a> <li><a href="Java.html#java_directors">Cross language polymorphism using directors</a>
<ul> <ul>
<li><a href="Java.html#java_enabling_directors">Enabling directors</a> <li><a href="Java.html#java_enabling_directors">Enabling directors</a>
<li><a href="Java.html#java_directors_classes">Director classes</a> <li><a href="Java.html#java_directors_classes">Director classes</a>

View file

@ -64,6 +64,7 @@
<li><a href="#Typemaps_nn41">Implementing constraints with typemaps</a> <li><a href="#Typemaps_nn41">Implementing constraints with typemaps</a>
</ul> </ul>
<li><a href="#Typemaps_nn43">Typemaps for multiple languages</a> <li><a href="#Typemaps_nn43">Typemaps for multiple languages</a>
<li><a href="#Typemaps_optimal">Optimal code generation when returning by value</a>
<li><a href="#Typemaps_nn42">Multi-argument typemaps</a> <li><a href="#Typemaps_nn42">Multi-argument typemaps</a>
<li><a href="#runtime_type_checker">The run-time type checker</a> <li><a href="#runtime_type_checker">The run-time type checker</a>
<ul> <ul>
@ -2006,6 +2007,10 @@ $symname - Name of function/method being wrapped
</pre> </pre>
</div> </div>
<p>
The "out" typemap supports an optional attribute flag called "optimal". This is for code optimisation and is detailed in the <a href="#Typemaps_optimal">Optimal code generation when returning by value</a> section.
</p>
<H3><a name="Typemaps_nn29"></a>10.5.4 "arginit" typemap</H3> <H3><a name="Typemaps_nn29"></a>10.5.4 "arginit" typemap</H3>
@ -2619,7 +2624,194 @@ The example above also shows a common approach of issuing a warning for an as ye
<tt>%typemap(ruby,in) int "$1 = NUM2INT($input);"</tt>. <tt>%typemap(ruby,in) int "$1 = NUM2INT($input);"</tt>.
</p> </p>
<H2><a name="Typemaps_nn42"></a>10.8 Multi-argument typemaps</H2> <H2><a name="Typemaps_optimal"></a>10.8 Optimal code generation when returning by value</H2>
<p>
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.
<p>
<p>
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:
</p>
<div class="code">
<pre>
%typemap(out) SWIGTYPE %{
$result = new $1_ltype((const $1_ltype &amp;)$1);
%}
%inline %{
#include <iostream>
using namespace std;
struct XX {
XX() { cout &lt;&lt; "XX()" &lt;&lt; endl; }
XX(int i) { cout &lt;&lt; "XX(" &lt;&lt; i &lt;&lt; ")" &lt;&lt; endl; }
XX(const XX &amp;other) { cout &lt;&lt; "XX(const XX &amp;)" &lt;&lt; endl; }
XX &amp; operator =(const XX &amp;other) { cout &lt;&lt; "operator=(const XX &amp;)" &lt;&lt; endl; return *this; }
~XX() { cout &lt;&lt; "~XX()" &lt;&lt; endl; }
static XX create() {
return XX(0);
}
};
%}
</pre>
</div>
<p>
The "out" typemap shown is the default typemap for C# when returning by objects by value.
When making a call to <tt>XX::create()</tt> from C#, the output is as follows:
</p>
<div class="targetlang">
<pre>
XX()
XX(0)
operator=(const XX &amp;)
~XX()
XX(const XX &amp;)
~XX()
~XX()
</pre>
</div>
<p>
Note that three objects are being created as well as an assignment.
Wouldn't it be great if the <tt>XX::create()</tt> 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:
</p>
<div class="code">
<pre>
%typemap(out, optimal="1") SWIGTYPE %{
$result = new $1_ltype((const $1_ltype &amp;)$1);
%}
</pre>
</div>
<p>
then when the code is run again, the output is simply:
</P>
<div class="targetlang">
<pre>
XX(0)
~XX()
</pre>
</div>
<p>
How the "optimal" attribute works is best explained using the generated code.
Without "optimal", the generated code is:
</p>
<div class="code">
<pre>
SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() {
void * jresult ;
XX result;
result = XX::create();
jresult = new XX((const XX &amp;)result);
return jresult;
}
</pre>
</div>
<p>
With the "optimal" attribute, the code is:
</p>
<div class="code">
<pre>
SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() {
void * jresult ;
jresult = new XX((const XX &amp;)XX::create());
return jresult;
}
</pre>
</div>
<p>
The major difference is the <tt>result</tt> temporary variable holding the value returned from <tt>XX::create()</tt> is no longer generated and instead the copy constructor call is made directly from
the value returned by <tt>XX::create()</tt>.
With modern compiler optimisations turned on, the copy is not actually done, in fact the object is never created
on the stack in <tt>XX::create()</tt> at all, it is simply created directly on the heap.
In the first instance, the <tt>$1</tt> special variable in the typemap is expanded into <tt>result</tt>.
In the second instance, <tt>$1</tt> is expanded into <tt>XX::create()</tt> and this is essentially
what the "optimal" attribute is telling SWIG to do.
</p>
<p>
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 <a href="Customization.html#exception">%exception</a> is used.
Consider adding the following <tt>%exception</tt> to the example:
</p>
<div class="code">
<pre>
%exception XX::create() %{
try {
$action
} catch(const std::exception &amp;e) {
cout &lt;&lt; e.what() &lt;&lt; endl;
}
%}
</pre>
</div>
<p>
SWIG can detect when the "optimal" attribute cannot be used and will ignore it and in this case will issue the following warning:
</p>
<div class="targetlang">
<pre>
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 &amp;e) {
cout &lt;&lt; e.what() &lt;&lt; endl;
}
</pre>
</div>
<p>
It should be clear that the above code cannot be used as the argument to the copy constructor call, ie for the <tt>$1</tt> substitution.
<p>
<p>
Secondly, if the typemaps uses <tt>$1</tt> 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:
</p>
<div class="targetlang">
<pre>
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.
</pre>
</div>
<p>
However, it doesn't always get it right, for example when <tt>$1</tt> is within some commented out code.
</p>
<H2><a name="Typemaps_nn42"></a>10.9 Multi-argument typemaps</H2>
<p> <p>
@ -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). ordering (and perform conversions if needed).
</p> </p>
<H2><a name="runtime_type_checker"></a>10.9 The run-time type checker</H2> <H2><a name="runtime_type_checker"></a>10.10 The run-time type checker</H2>
<p> <p>
@ -2910,7 +3102,7 @@ language modules.</li>
<li>Modules can be unloaded from the type system.</li> <li>Modules can be unloaded from the type system.</li>
</ul> </ul>
<H3><a name="Typemaps_nn45"></a>10.9.1 Implementation</H3> <H3><a name="Typemaps_nn45"></a>10.10.1 Implementation</H3>
<p> <p>
@ -3096,7 +3288,7 @@ structures rather than creating new ones. These <tt>swig_module_info</tt>
structures are chained together in a circularly linked list. structures are chained together in a circularly linked list.
</p> </p>
<H3><a name="Typemaps_nn46"></a>10.9.2 Usage</H3> <H3><a name="Typemaps_nn46"></a>10.10.2 Usage</H3>
<p>This section covers how to use these functions from typemaps. To learn how to <p>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. managed.
</p> </p>
<H2><a name="Typemaps_overloading"></a>10.10 Typemaps and overloading</H2> <H2><a name="Typemaps_overloading"></a>10.11 Typemaps and overloading</H2>
<p> <p>
@ -3499,7 +3691,7 @@ Subsequent "in" typemaps would then perform more extensive type-checking.
</li> </li>
</ul> </ul>
<H2><a name="Typemaps_nn48"></a>10.11 More about <tt>%apply</tt> and <tt>%clear</tt></H2> <H2><a name="Typemaps_nn48"></a>10.12 More about <tt>%apply</tt> and <tt>%clear</tt></H2>
<p> <p>
@ -3584,7 +3776,7 @@ example:
</pre> </pre>
</div> </div>
<H2><a name="Typemaps_nn49"></a>10.12 Reducing wrapper code size</H2> <H2><a name="Typemaps_nn49"></a>10.13 Reducing wrapper code size</H2>
<p> <p>
@ -3665,7 +3857,7 @@ convert_float_array(PyObject *input, int size) {
</pre> </pre>
</div> </div>
<H2><a name="Typemaps_nn47"></a>10.13 Passing data between typemaps</H2> <H2><a name="Typemaps_nn47"></a>10.14 Passing data between typemaps</H2>
<p> <p>
@ -3702,7 +3894,7 @@ sure that the typemaps sharing information have exactly the same types and names
</p> </p>
<H2><a name="Typemaps_nn51"></a>10.14 Where to go for more information?</H2> <H2><a name="Typemaps_nn51"></a>10.15 Where to go for more information?</H2>
<p> <p>

View file

@ -482,8 +482,12 @@ example.i(4): Syntax error in input.
<li>469. No or improper directorin typemap defined for <em>type</em> <li>469. No or improper directorin typemap defined for <em>type</em>
<li>470. Thread/reentrant unsafe wrapping, consider returning by value instead. <li>470. Thread/reentrant unsafe wrapping, consider returning by value instead.
<li>471. Unable to use return type <em>type</em> in director method <li>471. Unable to use return type <em>type</em> in director method
<li>474. Method <em>method</em> usage of the optimal attribute in the out typemap at <em>file</em>:<em>line</em> ignored as the following cannot be used to generate optimal code: <em>code</em>
<li>475. Multiple calls to <em>method</em> might be generated due to optimal attribute usage in the out typemap at <em>file</em>:<em>line</em>.
</ul> </ul>
<H3><a name="Warnings_nn14"></a>14.9.5 Code generation (500-599)</H3> <H3><a name="Warnings_nn14"></a>14.9.5 Code generation (500-599)</H3>

View file

@ -137,12 +137,13 @@ SWIG_TYPECHECK_STRING_ARRAY 1140
%typemap(lispclass) double "cl:double-float"; %typemap(lispclass) double "cl:double-float";
%typemap(lispclass) char * "cl:string"; %typemap(lispclass) char * "cl:string";
%typemap(out) void "";
%typemap(out) bool "$result = (int)$1;"; %typemap(out) bool "$result = (int)$1;";
%typemap(out) char, unsigned char, signed char, %typemap(out) char, unsigned char, signed char,
short, signed short, unsigned short, short, signed short, unsigned short,
int, signed int, unsigned int, int, signed int, unsigned int,
long, signed long, unsigned long, long, signed long, unsigned long,
float, double, long double, char *, void *, void, float, double, long double, char *, void *,
enum SWIGTYPE, SWIGTYPE *, enum SWIGTYPE, SWIGTYPE *,
SWIGTYPE[ANY], SWIGTYPE & "$result = $1;"; SWIGTYPE[ANY], SWIGTYPE & "$result = $1;";
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -80,12 +80,13 @@
SWIGTYPE[ANY], SWIGTYPE & "$1 = $input;"; SWIGTYPE[ANY], SWIGTYPE & "$1 = $input;";
%typemap(in) SWIGTYPE "$1 = *$input;"; %typemap(in) SWIGTYPE "$1 = *$input;";
%typemap(out) void "";
%typemap(out) bool "$result = (int)$1;"; %typemap(out) bool "$result = (int)$1;";
%typemap(out) char, unsigned char, signed char, %typemap(out) char, unsigned char, signed char,
short, signed short, unsigned short, short, signed short, unsigned short,
int, signed int, unsigned int, int, signed int, unsigned int,
long, signed long, unsigned long, long, signed long, unsigned long,
float, double, long double, char *, void *, void, float, double, long double, char *, void *
enum SWIGTYPE, SWIGTYPE *, enum SWIGTYPE, SWIGTYPE *,
SWIGTYPE[ANY], SWIGTYPE & "$result = $1;"; SWIGTYPE[ANY], SWIGTYPE & "$result = $1;";
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -330,7 +330,7 @@ SIMPLE_TYPEMAP(double, C_c_double, C_flonum, C_swig_is_number, (double), C_SIZEO
{ {
$&1_ltype resultptr; $&1_ltype resultptr;
C_word *known_space = C_alloc(C_SIZEOF_SWIG_POINTER); 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); $result = SWIG_NewPointerObj(resultptr, $&1_descriptor, 1);
} }
#else #else
@ -348,7 +348,7 @@ SIMPLE_TYPEMAP(double, C_c_double, C_flonum, C_swig_is_number, (double), C_SIZEO
{ {
$&1_ltype resultptr; $&1_ltype resultptr;
C_word *known_space = C_alloc(C_SIZEOF_SWIG_POINTER); 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); $result = SWIG_NewPointerObj(resultptr, $&1_descriptor, 0);
} }
#else #else

View file

@ -376,7 +376,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
%typemap(out) SWIGTYPE %typemap(out) SWIGTYPE
#ifdef __cplusplus #ifdef __cplusplus
%{ $result = new $1_ltype(($1_ltype &)$1); %} %{ $result = new $1_ltype((const $1_ltype &)$1); %}
#else #else
{ {
$&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype)); $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype));

View file

@ -119,7 +119,7 @@
#ifdef __cplusplus #ifdef __cplusplus
{ {
$&1_ltype resultptr; $&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); $result = SWIG_NewPointerObj (resultptr, $&1_descriptor, 1);
} }
#else #else
@ -135,7 +135,7 @@
#ifdef __cplusplus #ifdef __cplusplus
{ {
$&1_ltype resultptr; $&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); $result = SWIG_NewPointerObj (resultptr, $&1_descriptor, 0);
} }
#else #else

View file

@ -579,7 +579,7 @@
%typemap(out) SWIGTYPE %typemap(out) SWIGTYPE
#ifdef __cplusplus #ifdef __cplusplus
%{ *($&1_ltype*)&$result = new $1_ltype(($1_ltype &)$1); %} %{ *($&1_ltype*)&$result = new $1_ltype((const $1_ltype &)$1); %}
#else #else
{ {
$&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype)); $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype));

View file

@ -189,7 +189,7 @@ $1=&temp;%}
#ifdef __cplusplus #ifdef __cplusplus
%typemap(out) SWIGTYPE %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++; SWIG_NewPointerObj(L,(void *) resultptr,$&1_descriptor,1); SWIG_arg++;
} }
#else #else

View file

@ -455,7 +455,7 @@ $1 = &temp; %}
$1 = *argp; %} $1 = *argp; %}
%typemap(out) SWIGTYPE %typemap(out) SWIGTYPE
#ifdef __cplusplus #ifdef __cplusplus
%{*($&1_ltype*)&$result = new $1_ltype(($1_ltype &)$1); %} %{*($&1_ltype*)&$result = new $1_ltype((const $1_ltype &)$1); %}
#else #else
{ {
$&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype)); $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype));

View file

@ -76,7 +76,7 @@
%typemap(out) SWIGTYPE { %typemap(out) SWIGTYPE {
/* %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"); CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr");
if( fromval ) { if( fromval ) {
$result = callback(*fromval,caml_val_ptr((void *)temp,$&1_descriptor)); $result = callback(*fromval,caml_val_ptr((void *)temp,$&1_descriptor));

View file

@ -211,7 +211,7 @@
%typemap(out) SWIGTYPE %typemap(out) SWIGTYPE
#ifdef __cplusplus #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); SWIG_SetPointerZval(return_value, (void *)resultobj, $&1_descriptor, 1);
} }
#else #else

View file

@ -136,7 +136,7 @@ extern "C" {
#ifdef __cplusplus #ifdef __cplusplus
{ {
$&1_ltype resultptr; $&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)); push_object(SWIG_NewPointerObj((void *) resultptr, $&1_descriptor, 1));
} }
#else #else

View file

@ -161,6 +161,8 @@
#define WARN_TYPEMAP_DIRECTOROUT_UNDEF 471 #define WARN_TYPEMAP_DIRECTOROUT_UNDEF 471
#define WARN_TYPEMAP_TYPECHECK_UNDEF 472 #define WARN_TYPEMAP_TYPECHECK_UNDEF 472
#define WARN_TYPEMAP_DIRECTOROUT_PTR 473 #define WARN_TYPEMAP_DIRECTOROUT_PTR 473
#define WARN_TYPEMAP_OUT_OPTIMAL_IGNORED 474
#define WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE 475
/* -- Fragments -- */ /* -- Fragments -- */
#define WARN_FRAGMENT_NOT_FOUND 490 #define WARN_FRAGMENT_NOT_FOUND 490

View file

@ -2517,7 +2517,7 @@ int ALLEGROCL::emit_defun(Node *n, File *f_cl) {
int ALLEGROCL::functionWrapper(Node *n) { int ALLEGROCL::functionWrapper(Node *n) {
ParmList *parms = CopyParmList(Getattr(n, "parms")); ParmList *parms = CopyParmList(Getattr(n, "parms"));
Wrapper *wrap = NewWrapper(); Wrapper *f = NewWrapper();
String *raw_return_type = Swig_typemap_lookup_new("ctype", n, "", 0); String *raw_return_type = Swig_typemap_lookup_new("ctype", n, "", 0);
SwigType *return_type = Swig_cparse_type(raw_return_type); SwigType *return_type = Swig_cparse_type(raw_return_type);
@ -2528,18 +2528,18 @@ int ALLEGROCL::functionWrapper(Node *n) {
if (!is_void_return) { if (!is_void_return) {
String *lresult_init = NewStringf("= (%s)0", raw_return_type); 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"), SwigType_lstr(SwigType_ltype(return_type), "lresult"),
lresult_init, NIL); lresult_init, NIL);
Delete(lresult_init); Delete(lresult_init);
} }
// Emit all of the local variables for holding arguments. // 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 // Attach the standard typemaps
Swig_typemap_attach_parms("ctype", parms, wrap); Swig_typemap_attach_parms("ctype", parms, f);
Swig_typemap_attach_parms("lin", parms, wrap); Swig_typemap_attach_parms("lin", parms, f);
emit_attach_parmmaps(parms, wrap); emit_attach_parmmaps(parms, f);
String *mangled = mangle_name(n); String *mangled = mangle_name(n);
Node *overloaded = Getattr(n, "sym:overloaded"); Node *overloaded = Getattr(n, "sym:overloaded");
@ -2562,7 +2562,7 @@ int ALLEGROCL::functionWrapper(Node *n) {
emit_buffered_defuns(n); emit_buffered_defuns(n);
emit_dispatch_defun(n); emit_dispatch_defun(n);
} }
DelWrapper(wrap); DelWrapper(f);
return SWIG_OK; return SWIG_OK;
} }
} }
@ -2609,7 +2609,7 @@ int ALLEGROCL::functionWrapper(Node *n) {
// canThrow(n, "in", p); // canThrow(n, "in", p);
Replaceall(parm_code, "$input", arg); Replaceall(parm_code, "$input", arg);
Setattr(p, "emit: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"); p = Getattr(p, "tmap:in:next");
} }
@ -2619,28 +2619,30 @@ int ALLEGROCL::functionWrapper(Node *n) {
// Emit the function definition // Emit the function definition
String *signature = SwigType_str(return_type, name_and_parms); String *signature = SwigType_str(return_type, name_and_parms);
Printf(wrap->def, "EXPORT %s {", signature); Printf(f->def, "EXPORT %s {", signature);
if (CPlusPlus) if (CPlusPlus)
Printf(wrap->code, " try {\n"); Printf(f->code, " try {\n");
emit_action(n, wrap);
if (!is_void_return) { String *actioncode = emit_action(n);
String *result_convert = Swig_typemap_lookup_new("out", n, "result", 0);
Replaceall(result_convert, "$result", "lresult"); String *result_convert = Swig_typemap_lookup_out("out", n, "result", f, actioncode);
Printf(wrap->code, "%s\n", result_convert); Replaceall(result_convert, "$result", "lresult");
Printf(wrap->code, " return lresult;\n"); Printf(f->code, "%s\n", result_convert);
Delete(result_convert); Printf(f->code, " return lresult;\n");
} Delete(result_convert);
emit_return_variable(n, Getattr(n, "type"), f);
if (CPlusPlus) { if (CPlusPlus) {
Printf(wrap->code, " } catch (...) {\n"); Printf(f->code, " } catch (...) {\n");
if (!is_void_return) if (!is_void_return)
Printf(wrap->code, " return (%s)0;\n", raw_return_type); Printf(f->code, " return (%s)0;\n", raw_return_type);
Printf(wrap->code, " }\n"); Printf(f->code, " }\n");
} }
Printf(wrap->code, "}\n"); Printf(f->code, "}\n");
/* print this when in C mode? make this a command-line arg? */ /* print this when in C mode? make this a command-line arg? */
if (Generate_Wrapper) if (Generate_Wrapper)
Wrapper_print(wrap, f_cxx); Wrapper_print(f, f_cxx);
String *f_buffer = NewString(""); String *f_buffer = NewString("");
@ -2656,7 +2658,7 @@ int ALLEGROCL::functionWrapper(Node *n) {
} }
} }
DelWrapper(wrap); DelWrapper(f);
return SWIG_OK; return SWIG_OK;
} }

View file

@ -354,7 +354,7 @@ int CFFI::functionWrapper(Node *n) {
ParmList *parms = Getattr(n, "parms"); ParmList *parms = Getattr(n, "parms");
String *iname = Getattr(n, "sym:name"); String *iname = Getattr(n, "sym:name");
Wrapper *wrap = NewWrapper(); Wrapper *f = NewWrapper();
String *raw_return_type = Swig_typemap_lookup_new("ctype", n, "", 0); String *raw_return_type = Swig_typemap_lookup_new("ctype", n, "", 0);
SwigType *return_type = Swig_cparse_type(raw_return_type); SwigType *return_type = Swig_cparse_type(raw_return_type);
@ -364,7 +364,7 @@ int CFFI::functionWrapper(Node *n) {
if (!is_void_return) { if (!is_void_return) {
String *lresult_init = NewStringf("lresult = (%s)0", raw_return_type); 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); Delete(lresult_init);
} }
@ -373,7 +373,7 @@ int CFFI::functionWrapper(Node *n) {
overname = Getattr(n, "sym:overname"); overname = Getattr(n, "sym:overname");
} else { } else {
if (!addSymbol(iname, n)) { if (!addSymbol(iname, n)) {
DelWrapper(wrap); DelWrapper(f);
return SWIG_ERROR; return SWIG_ERROR;
} }
} }
@ -385,11 +385,11 @@ int CFFI::functionWrapper(Node *n) {
Setattr(n, "wrap:name", wname); Setattr(n, "wrap:name", wname);
// Emit all of the local variables for holding arguments. // 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 // Attach the standard typemaps
Swig_typemap_attach_parms("ctype", parms, wrap); Swig_typemap_attach_parms("ctype", parms, f);
emit_attach_parmmaps(parms, wrap); emit_attach_parmmaps(parms, f);
int num_arguments = emit_num_arguments(parms); int num_arguments = emit_num_arguments(parms);
String *name_and_parms = NewStringf("%s (", wname); String *name_and_parms = NewStringf("%s (", wname);
@ -426,7 +426,7 @@ int CFFI::functionWrapper(Node *n) {
{ {
Replaceall(parm_code, "$input", arg); Replaceall(parm_code, "$input", arg);
Setattr(p, "emit: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"); p = Getattr(p, "tmap:in:next");
} }
@ -436,25 +436,26 @@ int CFFI::functionWrapper(Node *n) {
// Emit the function definition // Emit the function definition
String *signature = SwigType_str(return_type, name_and_parms); String *signature = SwigType_str(return_type, name_and_parms);
Printf(wrap->def, "EXPORT %s {", signature); Printf(f->def, "EXPORT %s {", signature);
Printf(wrap->code, " try {\n"); Printf(f->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(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) if (!is_void_return)
Printf(wrap->code, " return (%s)0;\n", raw_return_type); Printf(f->code, " return (%s)0;\n", raw_return_type);
Printf(wrap->code, " }\n"); Printf(f->code, " }\n");
Printf(wrap->code, "}\n"); Printf(f->code, "}\n");
if (CPlusPlus) if (CPlusPlus)
Wrapper_print(wrap, f_cxx); Wrapper_print(f, f_cxx);
if (CPlusPlus) { if (CPlusPlus) {
emit_defun(n, wname); emit_defun(n, wname);
@ -482,7 +483,7 @@ int CFFI::functionWrapper(Node *n) {
// } // }
Delete(wname); Delete(wname);
DelWrapper(wrap); DelWrapper(f);
return SWIG_OK; return SWIG_OK;
} }

View file

@ -368,7 +368,7 @@ int CHICKEN::functionWrapper(Node *n) {
Wrapper_add_local(f, "resultobj", "C_word resultobj"); Wrapper_add_local(f, "resultobj", "C_word resultobj");
/* Write code to extract function parameters. */ /* Write code to extract function parameters. */
emit_args(d, l, f); emit_parameter_variables(l, f);
/* Attach the standard typemaps */ /* Attach the standard typemaps */
emit_attach_parmmaps(l, f); 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 */ /* Insert argument output code */
have_argout = 0; have_argout = 0;
for (p = l; p;) { for (p = l; p;) {
@ -514,7 +509,7 @@ int CHICKEN::functionWrapper(Node *n) {
if (!have_argout) { if (!have_argout) {
have_argout = 1; have_argout = 1;
// Print initial argument output code // Print initial argument output code
Printf(f->code, "SWIG_Chicken_SetupArgout\n"); Printf(argout, "SWIG_Chicken_SetupArgout\n");
} }
Replaceall(tm, "$source", Getattr(p, "lname")); 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 */ /* 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, "$source", "result");
Replaceall(tm, "$target", "resultobj"); Replaceall(tm, "$target", "resultobj");
Replaceall(tm, "$result", "resultobj"); Replaceall(tm, "$result", "resultobj");
@ -547,6 +547,7 @@ int CHICKEN::functionWrapper(Node *n) {
} else { } 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); 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 */ /* Insert the argumetn output code */
Printv(f->code, argout, NIL); Printv(f->code, argout, NIL);
@ -731,7 +732,7 @@ int CHICKEN::variableWrapper(Node *n) {
Replaceall(tm, "$target", name); Replaceall(tm, "$target", name);
Replaceall(tm, "$input", "value"); Replaceall(tm, "$input", "value");
/* Printv(f->code, tm, "\n",NIL); */ /* Printv(f->code, tm, "\n",NIL); */
emit_action_code(n, f, tm); emit_action_code(n, f->code, tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0)); 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, "$target", "resultobj");
Replaceall(tm, "$result", "resultobj"); Replaceall(tm, "$result", "resultobj");
/* Printf(f->code, "%s\n", tm); */ /* Printf(f->code, "%s\n", tm); */
emit_action_code(n, f, tm); emit_action_code(n, f->code, tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); 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, "$target", "resultobj");
Replaceall(tm, "$result", "resultobj"); Replaceall(tm, "$result", "resultobj");
/* Printf(f->code, "%s\n", tm); */ /* Printf(f->code, "%s\n", tm); */
emit_action_code(n, f, tm); emit_action_code(n, f->code, tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
} }

View file

@ -757,7 +757,7 @@ public:
Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL); Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL);
// Emit all of the local variables for holding arguments. // Emit all of the local variables for holding arguments.
emit_args(t, l, f); emit_parameter_variables(l, f);
/* Attach the standard typemaps */ /* Attach the standard typemaps */
emit_attach_parmmaps(l, f); 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; String *null_attribute = 0;
// Now write code to make the function call
if (!native_function_flag) { 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); canThrow(n, "out", n);
Replaceall(tm, "$source", "result"); /* deprecated */ Replaceall(tm, "$source", "result"); /* deprecated */
Replaceall(tm, "$target", "jresult"); /* deprecated */ Replaceall(tm, "$target", "jresult"); /* deprecated */
@ -937,6 +938,7 @@ public:
} else { } 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")); 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 */ /* Output argument output code */
@ -3463,9 +3465,6 @@ public:
// Get any Java exception classes in the throws typemap // Get any Java exception classes in the throws typemap
ParmList *throw_parm_list = NULL; 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")) { if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
int gencomma = 0; int gencomma = 0;
@ -3507,8 +3506,7 @@ public:
if (!is_void) { if (!is_void) {
Parm *tp = NewParmFromNode(returntype, empty_str, n); Parm *tp = NewParmFromNode(returntype, empty_str, n);
tm = Swig_typemap_lookup_new("csdirectorout", tp, "", 0); if ((tm = Swig_typemap_lookup_new("csdirectorout", tp, "", 0))) {
if (tm) {
substituteClassname(returntype, tm); substituteClassname(returntype, tm);
Replaceall(tm, "$cscall", upcall); Replaceall(tm, "$cscall", upcall);

View file

@ -261,3 +261,28 @@ String *Swig_method_decl(SwigType *returntype, SwigType *decl, const String_or_c
return result; 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);
}
}

View file

@ -12,16 +12,47 @@ char cvsroot_emit_cxx[] = "$Id$";
#include "swigmod.h" #include "swigmod.h"
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* emit_args() * emit_return_variable()
* *
* Creates a list of variable declarations for both the return value * Emits a variable declaration for a function return value.
* and function parameters. * The variable name is always called result.
* * n => Node of the method being wrapped
* The return value is always called result and arguments arg0, arg1, arg2, etc... * rt => the return type
* Returns the number of parameters associated with a function. * 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; Parm *p;
String *tm; String *tm;
@ -29,24 +60,6 @@ void emit_args(SwigType *rt, ParmList *l, Wrapper *f) {
/* Emit function arguments */ /* Emit function arguments */
Swig_cargs(f, l); 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 */ /* Attach typemaps to parameters */
/* Swig_typemap_attach_parms("ignore",l,f); */ /* Swig_typemap_attach_parms("ignore",l,f); */
@ -78,7 +91,6 @@ void emit_args(SwigType *rt, ParmList *l, Wrapper *f) {
p = nextSibling(p); p = nextSibling(p);
} }
} }
return;
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
@ -332,11 +344,13 @@ static void replace_contract_args(Parm *cp, Parm *rp, String *s) {
#endif #endif
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* int emit_action() * int emit_action_code()
* *
* Emits action code for a wrapper. Adds in exception handling code (%exception). * 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")); assert(Getattr(n, "wrap:name"));
/* Look for except feature (%exception) */ /* Look for except feature (%exception) */
@ -364,16 +378,23 @@ int emit_action_code(Node *n, Wrapper *f, String *eaction) {
Delete(fulldecl); Delete(fulldecl);
} }
} }
Printv(f->code, tm, "\n", NIL); Printv(wrappercode, tm, "\n", NIL);
Delete(tm); Delete(tm);
return 1; return 1;
} else { } else {
Printv(f->code, eaction, "\n", NIL); Printv(wrappercode, eaction, "\n", NIL);
return 0; 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 *tm;
String *action; String *action;
String *wrap; String *wrap;
@ -382,11 +403,10 @@ void emit_action(Node *n, Wrapper *f) {
/* Look for fragments */ /* Look for fragments */
{ {
String *f; String *fragment = Getattr(n, "feature:fragment");
f = Getattr(n, "feature:fragment"); if (fragment) {
if (f) {
char *c, *tok; char *c, *tok;
String *t = Copy(f); String *t = Copy(fragment);
c = Char(t); c = Char(t);
tok = strtok(c, ","); tok = strtok(c, ",");
while (tok) { while (tok) {
@ -416,27 +436,7 @@ void emit_action(Node *n, Wrapper *f) {
action = Getattr(n, "wrap:action"); action = Getattr(n, "wrap:action");
assert(action != 0); 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 */ /* Get the return type */
rt = Getattr(n, "type"); rt = Getattr(n, "type");
/* Emit contract code (if any) */ /* Emit contract code (if any) */
@ -444,7 +444,7 @@ void emit_action(Node *n, Wrapper *f) {
/* Preassertion */ /* Preassertion */
tm = Getattr(n, "contract:preassert"); tm = Getattr(n, "contract:preassert");
if (Len(tm)) { if (Len(tm)) {
Printv(f->code, tm, "\n", NIL); Printv(actioncode, tm, "\n", NIL);
} }
} }
/* Exception handling code */ /* Exception handling code */
@ -495,7 +495,7 @@ void emit_action(Node *n, Wrapper *f) {
} }
/* emit the except feature code */ /* emit the except feature code */
emit_action_code(n, f, eaction); emit_action_code(n, actioncode, eaction);
Delete(eaction); Delete(eaction);
@ -504,8 +504,9 @@ void emit_action(Node *n, Wrapper *f) {
/* Postassertion */ /* Postassertion */
tm = Getattr(n, "contract:postassert"); tm = Getattr(n, "contract:postassert");
if (Len(tm)) { if (Len(tm)) {
Printv(f->code, tm, "\n", NIL); Printv(actioncode, tm, "\n", NIL);
} }
} }
return actioncode;
} }

View file

@ -687,7 +687,7 @@ public:
Replaceall(proc_name, "_", "-"); Replaceall(proc_name, "_", "-");
/* Emit locals etc. into f->code; figure out which args to ignore */ /* 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 */ /* Attach the standard typemaps */
emit_attach_parmmaps(l, f); emit_attach_parmmaps(l, f);
@ -702,25 +702,6 @@ public:
Wrapper_add_local(f, "gswig_result", "SCM gswig_result"); Wrapper_add_local(f, "gswig_result", "SCM gswig_result");
Wrapper_add_local(f, "gswig_list_p", "SWIGUNUSED int gswig_list_p = 0"); 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 */ /* Open prototype and signature */
Printv(f->def, "static SCM\n", wname, " (", NIL); Printv(f->def, "static SCM\n", wname, " (", NIL);
@ -830,6 +811,7 @@ public:
/* Pass output arguments back to the caller. */ /* Pass output arguments back to the caller. */
/* Insert argument output code */ /* Insert argument output code */
String *returns_argout = NewString("");
for (p = l; p;) { for (p = l; p;) {
if ((tm = Getattr(p, "tmap:argout"))) { if ((tm = Getattr(p, "tmap:argout"))) {
Replaceall(tm, "$source", Getattr(p, "lname")); Replaceall(tm, "$source", Getattr(p, "lname"));
@ -838,7 +820,7 @@ public:
Replaceall(tm, "$input", Getattr(p, "emit:input")); Replaceall(tm, "$input", Getattr(p, "emit:input"));
Printv(outarg, tm, "\n", NIL); Printv(outarg, tm, "\n", NIL);
if (procdoc) { 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 /* A documentation typemap that is not the empty string
indicates that a value is returned to Scheme. */ indicates that a value is returned to Scheme. */
num_results++; num_results++;
@ -881,13 +863,14 @@ public:
// Now write code to make the function call // Now write code to make the function call
if (!use_scm_interface) if (!use_scm_interface)
Printv(f->code, tab4, "gh_defer_ints();\n", NIL); Printv(f->code, tab4, "gh_defer_ints();\n", NIL);
emit_action(n, f);
String *actioncode = emit_action(n);
if (!use_scm_interface) 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. // Now have return value, figure out what to do with it.
if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
if ((tm = Getattr(n, "tmap:out"))) {
Replaceall(tm, "$result", "gswig_result"); Replaceall(tm, "$result", "gswig_result");
Replaceall(tm, "$target", "gswig_result"); Replaceall(tm, "$target", "gswig_result");
Replaceall(tm, "$source", "result"); Replaceall(tm, "$source", "result");
@ -899,6 +882,24 @@ public:
} else { } else {
throw_unhandled_guile_type_error(d); 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 // Dump the argument output code
Printv(f->code, outarg, NIL); Printv(f->code, outarg, NIL);
@ -1123,6 +1124,7 @@ public:
Delete(method_signature); Delete(method_signature);
Delete(primitive_args); Delete(primitive_args);
Delete(doc_body); Delete(doc_body);
Delete(returns_argout);
Delete(returns); Delete(returns);
Delete(tmp); Delete(tmp);
Delete(scheme_arg_names); Delete(scheme_arg_names);
@ -1182,7 +1184,7 @@ public:
Replaceall(tm, "$input", "s_0"); Replaceall(tm, "$input", "s_0");
Replaceall(tm, "$target", name); Replaceall(tm, "$target", name);
/* Printv(f->code,tm,"\n",NIL); */ /* Printv(f->code,tm,"\n",NIL); */
emit_action_code(n, f, tm); emit_action_code(n, f->code, tm);
} else { } else {
throw_unhandled_guile_type_error(t); throw_unhandled_guile_type_error(t);
} }
@ -1196,7 +1198,7 @@ public:
Replaceall(tm, "$target", "gswig_result"); Replaceall(tm, "$target", "gswig_result");
Replaceall(tm, "$result", "gswig_result"); Replaceall(tm, "$result", "gswig_result");
/* Printv(f->code,tm,"\n",NIL); */ /* Printv(f->code,tm,"\n",NIL); */
emit_action_code(n, f, tm); emit_action_code(n, f->code, tm);
} else { } else {
throw_unhandled_guile_type_error(t); throw_unhandled_guile_type_error(t);
} }

View file

@ -829,7 +829,7 @@ public:
Printv(f->code, " (void)jcls;\n", NIL); Printv(f->code, " (void)jcls;\n", NIL);
// Emit all of the local variables for holding arguments. // Emit all of the local variables for holding arguments.
emit_args(t, l, f); emit_parameter_variables(l, f);
/* Attach the standard typemaps */ /* Attach the standard typemaps */
emit_attach_parmmaps(l, f); 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) { 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 // Handle exception classes specified in the "except" feature's "throws" attribute
addThrows(n, "feature:except", n); addThrows(n, "feature:except", n);
}
if (Cmp(nodeType(n), "constant") == 0) if (Cmp(nodeType(n), "constant") == 0)
Swig_restore(n); Swig_restore(n);
/* Return value if necessary */ /* Return value if necessary */
if (!native_function_flag) { if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) {
addThrows(n, "tmap:out", n); addThrows(n, "tmap:out", n);
Replaceall(tm, "$source", "result"); /* deprecated */ Replaceall(tm, "$source", "result"); /* deprecated */
Replaceall(tm, "$target", "jresult"); /* deprecated */ Replaceall(tm, "$target", "jresult"); /* deprecated */
@ -1017,6 +1018,7 @@ public:
} else { } 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")); 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 */ /* Output argument output code */
@ -3550,6 +3552,7 @@ public:
* intermediate's upcall code */ * intermediate's upcall code */
if ((tm = Getattr(p, "tmap:jtype"))) { if ((tm = Getattr(p, "tmap:jtype"))) {
String *din = Copy(Getattr(p, "tmap:javadirectorin")); String *din = Copy(Getattr(p, "tmap:javadirectorin"));
addThrows(n, "tmap:javadirectorin", p);
if (din) { if (din) {
Replaceall(din, "$module", module_class_name); Replaceall(din, "$module", module_class_name);
@ -3629,9 +3632,6 @@ public:
// Get any Java exception classes in the throws typemap // Get any Java exception classes in the throws typemap
ParmList *throw_parm_list = NULL; 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")) { if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
int gencomma = 0; int gencomma = 0;
@ -3661,12 +3661,6 @@ public:
Append(w->def, " {"); Append(w->def, " {");
Append(declaration, ";\n"); 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 */ /* Emit the intermediate class's upcall to the actual class */
String *upcall = NewStringf("self.%s(%s)", symname, imcall_args); String *upcall = NewStringf("self.%s(%s)", symname, imcall_args);
@ -3674,14 +3668,17 @@ public:
if (!is_void) { if (!is_void) {
Parm *tp = NewParmFromNode(returntype, empty_str, n); Parm *tp = NewParmFromNode(returntype, empty_str, n);
tm = Swig_typemap_lookup_new("javadirectorout", tp, "", 0); if ((tm = Swig_typemap_lookup_new("javadirectorout", tp, "", 0))) {
if (tm) { addThrows(n, "tmap:javadirectorout", tp);
substituteClassname(returntype, tm); substituteClassname(returntype, tm);
Replaceall(tm, "$javacall", upcall); Replaceall(tm, "$javacall", upcall);
Printf(callback_code, " return %s;\n", tm); Printf(callback_code, " return %s;\n", tm);
} }
if ((tm = Swig_typemap_lookup_new("out", tp, "", 0)))
addThrows(n, "tmap:out", tp);
Delete(tm); Delete(tm);
Delete(tp); Delete(tp);
} else } else
@ -3690,6 +3687,11 @@ public:
Printf(callback_code, " }\n"); Printf(callback_code, " }\n");
Delete(upcall); Delete(upcall);
/* Finish off the inherited upcall's definition */
Putc(')', callback_def);
generateThrowsClause(n, callback_def);
Printf(callback_def, " {\n");
if (!ignored_method) { if (!ignored_method) {
/* Emit the actual upcall through */ /* Emit the actual upcall through */
String *imclass_desc = NewStringf("(%s)%s", jnidesc, jniret_desc); String *imclass_desc = NewStringf("(%s)%s", jnidesc, jniret_desc);

View file

@ -362,7 +362,7 @@ public:
we need to add a couple of local variables we need to add a couple of local variables
NEW LANGUAGE NOTE:END ************************************************/ NEW LANGUAGE NOTE:END ************************************************/
Wrapper *f = NewWrapper(); 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); String *wname = Swig_name_wrapper(iname);
@ -383,10 +383,9 @@ public:
it will print it will print
int arg1; int arg1;
int arg2; int arg2;
int result;
NEW LANGUAGE NOTE:END ************************************************/ NEW LANGUAGE NOTE:END ************************************************/
/* Write code to extract function parameters. */ /* Write code to extract function parameters. */
emit_args(d, l, f); emit_parameter_variables(l, f);
/* Attach the standard typemaps */ /* Attach the standard typemaps */
emit_attach_parmmaps(l, f); emit_attach_parmmaps(l, f);
@ -554,16 +553,15 @@ public:
Setattr(n, "wrap:name", wname); Setattr(n, "wrap:name", wname);
/* Emit the function call */ /* Emit the function call */
emit_action(n, f); String *actioncode = emit_action(n);
/* NEW LANGUAGE NOTE:*********************************************** /* NEW LANGUAGE NOTE:***********************************************
FIXME: FIXME:
returns 1 if there is a void return type returns 1 if there is a void return type
this is because there is a typemap for void this is because there is a typemap for void
NEW LANGUAGE NOTE:END ************************************************/ NEW LANGUAGE NOTE:END ************************************************/
Printv(f->code, "SWIG_arg=0;\n", NIL);
// Return value if necessary // 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 // managing the number of returning variables
// if (numoutputs=Getattr(tm,"numoutputs")){ // if (numoutputs=Getattr(tm,"numoutputs")){
// int i=GetInt(tm,"numoutputs"); // int i=GetInt(tm,"numoutputs");
@ -582,6 +580,7 @@ public:
} else { } 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); 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 */ /* Output argument output code */
Printv(f->code, outarg, NIL); Printv(f->code, outarg, NIL);

View file

@ -1304,7 +1304,7 @@ MODULA3():
Printv(f->def, " SWIGEXPORT ", c_return_type, " ", wname, "(", NIL); Printv(f->def, " SWIGEXPORT ", c_return_type, " ", wname, "(", NIL);
// Emit all of the local variables for holding arguments. // Emit all of the local variables for holding arguments.
emit_args(t, l, f); emit_parameter_variables(l, f);
/* Attach the standard typemaps */ /* Attach the standard typemaps */
emit_attach_parmmaps(l, f); emit_attach_parmmaps(l, f);
@ -1420,17 +1420,15 @@ MODULA3():
// Now write code to make the function call // Now write code to make the function call
if (!native_function_flag) { if (!native_function_flag) {
emit_action(n, f); String *actioncode = emit_action(n);
}
if (Cmp(nodeType(n), "constant") == 0) { if (Cmp(nodeType(n), "constant") == 0) {
Swig_restore(n); Swig_restore(n);
} }
/* Return value if necessary */ /* Return value if necessary */
if (!native_function_flag) { String *tm;
String *tm = getMappedTypeNew(n, "out", "result"); if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
if (tm != NIL) {
addThrows(throws_hash, "out", n); addThrows(throws_hash, "out", n);
Replaceall(tm, "$source", "result"); /* deprecated */ Replaceall(tm, "$source", "result"); /* deprecated */
Replaceall(tm, "$target", "cresult"); /* deprecated */ Replaceall(tm, "$target", "cresult"); /* deprecated */
@ -1441,6 +1439,7 @@ MODULA3():
} else { } 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); 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 */ /* Output argument output code */

View file

@ -271,12 +271,8 @@ public:
macros. */ macros. */
Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL); Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
// Declare return variable and arguments // Emit all of the local variables for holding arguments.
// number of parameters emit_parameter_variables(l, f);
// they are called arg0, arg1, ...
// the return value is called result
emit_args(d, l, f);
/* Attach the standard typemaps */ /* Attach the standard typemaps */
emit_attach_parmmaps(l, f); emit_attach_parmmaps(l, f);
@ -394,11 +390,10 @@ public:
// Now write code to make the function call // 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. // Now have return value, figure out what to do with it.
if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) {
Replaceall(tm, "$source", "result"); Replaceall(tm, "$source", "result");
Replaceall(tm, "$target", "values[0]"); Replaceall(tm, "$target", "values[0]");
Replaceall(tm, "$result", "values[0]"); Replaceall(tm, "$result", "values[0]");
@ -410,6 +405,7 @@ public:
} else { } else {
throw_unhandled_mzscheme_type_error(d); throw_unhandled_mzscheme_type_error(d);
} }
emit_return_variable(n, d, f);
// Dump the argument output code // Dump the argument output code
Printv(f->code, Char(outarg), NIL); Printv(f->code, Char(outarg), NIL);
@ -539,7 +535,7 @@ public:
Replaceall(tm, "$target", name); Replaceall(tm, "$target", name);
Replaceall(tm, "$input", "argv[0]"); Replaceall(tm, "$input", "argv[0]");
/* Printv(f->code, tm, "\n",NIL); */ /* Printv(f->code, tm, "\n",NIL); */
emit_action_code(n, f, tm); emit_action_code(n, f->code, tm);
} else { } else {
throw_unhandled_mzscheme_type_error(t); throw_unhandled_mzscheme_type_error(t);
} }
@ -553,7 +549,7 @@ public:
Replaceall(tm, "$target", "swig_result"); Replaceall(tm, "$target", "swig_result");
Replaceall(tm, "$result", "swig_result"); Replaceall(tm, "$result", "swig_result");
/* Printf (f->code, "%s\n", tm); */ /* Printf (f->code, "%s\n", tm); */
emit_action_code(n, f, tm); emit_action_code(n, f->code, tm);
} else { } else {
throw_unhandled_mzscheme_type_error(t); throw_unhandled_mzscheme_type_error(t);
} }

View file

@ -518,13 +518,8 @@ public:
"argv = (CAML_VALUE *)malloc( argc * sizeof( CAML_VALUE ) );\n" "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); "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); d = SwigType_typedef_qualified(d);
emit_args(d, l, f); emit_parameter_variables(l, f);
/* Attach the standard typemaps */ /* Attach the standard typemaps */
emit_attach_parmmaps(l, f); emit_attach_parmmaps(l, f);
@ -645,13 +640,12 @@ public:
Wrapper_add_local(f, "upcall", "bool upcall = false"); Wrapper_add_local(f, "upcall", "bool upcall = false");
Append(f->code, "upcall = (director);\n"); Append(f->code, "upcall = (director);\n");
} }
// Now write code to make the function call // Now write code to make the function call
Swig_director_emit_dynamic_cast(n, f);
String *actioncode = emit_action(n);
emit_action(n, f); if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
// Now have return value, figure out what to do with it.
if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) {
Replaceall(tm, "$source", "swig_result"); Replaceall(tm, "$source", "swig_result");
Replaceall(tm, "$target", "rv"); Replaceall(tm, "$target", "rv");
Replaceall(tm, "$result", "rv"); Replaceall(tm, "$result", "rv");
@ -660,6 +654,7 @@ public:
} else { } else {
throw_unhandled_ocaml_type_error(d, "out"); throw_unhandled_ocaml_type_error(d, "out");
} }
emit_return_variable(n, d, f);
// Dump the argument output code // Dump the argument output code
Printv(f->code, Char(outarg), NIL); Printv(f->code, Char(outarg), NIL);
@ -810,7 +805,7 @@ public:
Replaceall(tm, "$target", name); Replaceall(tm, "$target", name);
Replaceall(tm, "$input", "args"); Replaceall(tm, "$input", "args");
/* Printv(f->code, tm, "\n",NIL); */ /* 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))) { } else if ((tm = Swig_typemap_lookup_new("in", n, name, 0))) {
Replaceall(tm, "$source", "args"); Replaceall(tm, "$source", "args");
Replaceall(tm, "$target", name); Replaceall(tm, "$target", name);
@ -828,14 +823,12 @@ public:
Replaceall(tm, "$source", name); Replaceall(tm, "$source", name);
Replaceall(tm, "$target", "swig_result"); Replaceall(tm, "$target", "swig_result");
Replaceall(tm, "$result", "swig_result"); Replaceall(tm, "$result", "swig_result");
/* Printf (f->code, "%s\n", tm); */ emit_action_code(n, f->code, tm);
emit_action_code(n, f, tm);
} else if ((tm = Swig_typemap_lookup_new("out", n, name, 0))) { } else if ((tm = Swig_typemap_lookup_new("out", n, name, 0))) {
Replaceall(tm, "$source", name); Replaceall(tm, "$source", name);
Replaceall(tm, "$target", "swig_result"); Replaceall(tm, "$target", "swig_result");
Replaceall(tm, "$result", "swig_result"); Replaceall(tm, "$result", "swig_result");
Printf(f->code, "%s\n", tm); Printf(f->code, "%s\n", tm);
} else { } else {
throw_unhandled_ocaml_type_error(t, "varout/out"); throw_unhandled_ocaml_type_error(t, "varout/out");
} }

View file

@ -426,7 +426,7 @@ public:
Printv(f->def, "static octave_value_list ", overname, " (const octave_value_list& args, int nargout) {", NIL); 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); emit_attach_parmmaps(l, f);
Setattr(n, "wrap:parms", l); Setattr(n, "wrap:parms", l);
@ -569,14 +569,15 @@ public:
Setattr(n, "wrap:name", overname); 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, "_out", "octave_value_list _out");
Wrapper_add_local(f, "_outp", "octave_value_list *_outp=&_out"); Wrapper_add_local(f, "_outp", "octave_value_list *_outp=&_out");
Wrapper_add_local(f, "_outv", "octave_value _outv"); Wrapper_add_local(f, "_outv", "octave_value _outv");
// Return the function value // 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, "$source", "result");
Replaceall(tm, "$target", "_outv"); Replaceall(tm, "$target", "_outv");
Replaceall(tm, "$result", "_outv"); Replaceall(tm, "$result", "_outv");
@ -592,6 +593,7 @@ public:
} else { } 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); 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, outarg, NIL);
Printv(f->code, cleanup, NIL); Printv(f->code, cleanup, NIL);
@ -690,7 +692,7 @@ public:
if (Getattr(n, "tmap:varin:implicitconv")) { if (Getattr(n, "tmap:varin:implicitconv")) {
Replaceall(tm, "$implicitconv", get_implicitconv_flag(n)); Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
} }
emit_action_code(n, setf, tm); emit_action_code(n, setf->code, tm);
Delete(tm); Delete(tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0)); 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, "$source", name);
Replaceall(tm, "$target", "obj"); Replaceall(tm, "$target", "obj");
Replaceall(tm, "$result", "obj"); Replaceall(tm, "$result", "obj");
addfail = emit_action_code(n, getf, tm); addfail = emit_action_code(n, getf->code, tm);
Delete(tm); Delete(tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));

View file

@ -589,7 +589,7 @@ public:
Printv(f->def, "XS(", wname, ") {\n", "{\n", /* scope to destroy C++ objects before croaking */ Printv(f->def, "XS(", wname, ") {\n", "{\n", /* scope to destroy C++ objects before croaking */
NIL); NIL);
emit_args(d, l, f); emit_parameter_variables(l, f);
emit_attach_parmmaps(l, f); emit_attach_parmmaps(l, f);
Setattr(n, "wrap:parms", l); Setattr(n, "wrap:parms", l);
@ -722,9 +722,10 @@ public:
/* Now write code to make the function call */ /* 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"); SwigType *t = Getattr(n, "type");
Replaceall(tm, "$source", "result"); Replaceall(tm, "$source", "result");
Replaceall(tm, "$target", "ST(argvi)"); Replaceall(tm, "$target", "ST(argvi)");
@ -743,6 +744,7 @@ public:
} else { } 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); 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. */ /* If there were any output args, take care of them. */
@ -860,7 +862,7 @@ public:
Replaceall(tm, "$target", name); Replaceall(tm, "$target", name);
Replaceall(tm, "$input", "sv"); Replaceall(tm, "$input", "sv");
/* Printf(setf->code,"%s\n", tm); */ /* Printf(setf->code,"%s\n", tm); */
emit_action_code(n, setf, tm); emit_action_code(n, setf->code, tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0)); 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; return SWIG_NOWRAP;
@ -887,7 +889,7 @@ public:
Replaceall(tm, "$shadow", "0"); Replaceall(tm, "$shadow", "0");
} }
/* Printf(getf->code,"%s\n", tm); */ /* Printf(getf->code,"%s\n", tm); */
addfail = emit_action_code(n, getf, tm); addfail = emit_action_code(n, getf->code, tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
DelWrapper(setf); DelWrapper(setf);

View file

@ -1007,7 +1007,7 @@ public:
Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL); Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL);
} }
emit_args(d, l, f); emit_parameter_variables(l, f);
/* Attach standard typemaps */ /* Attach standard typemaps */
emit_attach_parmmaps(l, f); emit_attach_parmmaps(l, f);
@ -1175,9 +1175,9 @@ public:
Setattr(n, "wrap:name", wname); Setattr(n, "wrap:name", wname);
/* emit function call */ /* 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, "$input", "result");
Replaceall(tm, "$source", "result"); Replaceall(tm, "$source", "result");
Replaceall(tm, "$target", "return_value"); Replaceall(tm, "$target", "return_value");
@ -1205,6 +1205,7 @@ public:
} else { } 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); 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) { if (outarg) {
Printv(f->code, outarg, NIL); Printv(f->code, outarg, NIL);
@ -2679,24 +2680,23 @@ public:
int CreateZendListDestructor(Node *n) { int CreateZendListDestructor(Node *n) {
String *name = GetChar(Swig_methodclass(n), "name"); String *name = GetChar(Swig_methodclass(n), "name");
String *iname = GetChar(n, "sym:name"); String *iname = GetChar(n, "sym:name");
SwigType *d = Getattr(n, "type");
ParmList *l = Getattr(n, "parms"); ParmList *l = Getattr(n, "parms");
String *destructorname = NewStringEmpty(); String *destructorname = NewStringEmpty();
Printf(destructorname, "_%s", Swig_name_wrapper(iname)); Printf(destructorname, "_%s", Swig_name_wrapper(iname));
Setattr(classnode, "destructor", destructorname); Setattr(classnode, "destructor", destructorname);
Wrapper *df = NewWrapper(); Wrapper *f = NewWrapper();
Printf(df->def, "/* This function is designed to be called by the zend list destructors */\n"); Printf(f->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(f->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); 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(f, "value", "swig_object_wrapper *value=(swig_object_wrapper *) rsrc->ptr", NIL);
Wrapper_add_localv(df, "ptr", "void *ptr=value->ptr", NIL); Wrapper_add_localv(f, "ptr", "void *ptr=value->ptr", NIL);
Wrapper_add_localv(df, "newobject", "int newobject=value->newobject", NIL); Wrapper_add_localv(f, "newobject", "int newobject=value->newobject", NIL);
emit_args(d, l, df); emit_parameter_variables(l, f);
emit_attach_parmmaps(l, df); emit_attach_parmmaps(l, f);
// Get type of first arg, thing to be destructed // Get type of first arg, thing to be destructed
// Skip ignored arguments // Skip ignored arguments
@ -2707,18 +2707,20 @@ public:
} }
SwigType *pt = Getattr(p, "type"); SwigType *pt = Getattr(p, "type");
Printf(df->code, " efree(value);\n"); Printf(f->code, " efree(value);\n");
Printf(df->code, " if (! newobject) return; /* can't delete it! */\n"); Printf(f->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(f->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, " if (! arg1) zend_error(E_ERROR, \"%s resource already free'd\");\n", Char(name));
Setattr(n, "wrap:name", destructorname); 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; return SWIG_OK;

View file

@ -288,8 +288,8 @@ public:
Wrapper *f = NewWrapper(); Wrapper *f = NewWrapper();
/* Write code to extract function parameters. */ // Emit all of the local variables for holding arguments.
emit_args(d, l, f); emit_parameter_variables(l, f);
/* Attach the standard typemaps */ /* Attach the standard typemaps */
emit_attach_parmmaps(l, f); emit_attach_parmmaps(l, f);
@ -400,21 +400,21 @@ public:
} }
/* Emit the function call */ /* Emit the function call */
emit_action(n, f); String *actioncode = emit_action(n);
/* Clear the return stack */ /* Clear the return stack */
Printf(f->code, "pop_n_elems(args);\n"); Printf(actioncode, "pop_n_elems(args);\n");
/* Return the function value */ /* Return the function value */
if (current == CONSTRUCTOR) { if (current == CONSTRUCTOR) {
Printv(f->code, "THIS = (void *) result;\n", NIL); Printv(actioncode, "THIS = (void *) result;\n", NIL);
Printv(description, ", tVoid", NIL); Printv(description, ", tVoid", NIL);
} else if (current == DESTRUCTOR) { } else if (current == DESTRUCTOR) {
Printv(description, ", tVoid", NIL); Printv(description, ", tVoid", NIL);
} else { } else {
// Wrapper_add_local(f, "resultobj", "struct object *resultobj");
Printv(description, ", ", NIL); 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, "$source", "result");
Replaceall(tm, "$target", "resultobj"); Replaceall(tm, "$target", "resultobj");
Replaceall(tm, "$result", "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); 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 */ /* Output argument output code */
Printv(f->code, outarg, NIL); Printv(f->code, outarg, NIL);

View file

@ -1611,8 +1611,8 @@ public:
Wrapper_add_local(f, "resultobj", "PyObject *resultobj = 0"); Wrapper_add_local(f, "resultobj", "PyObject *resultobj = 0");
/* Write code to extract function parameters. */ // Emit all of the local variables for holding arguments.
emit_args(d, l, f); emit_parameter_variables(l, f);
/* Attach the standard typemaps */ /* Attach the standard typemaps */
emit_attach_parmmaps(l, f); 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 */ /* Emit the function call */
if (director_method) { if (director_method) {
Append(f->code, "try {\n"); Append(f->code, "try {\n");
@ -1939,23 +1928,24 @@ public:
Setattr(n, "wrap:name", wname); Setattr(n, "wrap:name", wname);
emit_action(n, f); Swig_director_emit_dynamic_cast(n, f);
String *actioncode = emit_action(n);
if (director_method) { if (director_method) {
Append(f->code, "} catch (Swig::DirectorException&) {\n"); Append(actioncode, "} catch (Swig::DirectorException&) {\n");
Append(f->code, " SWIG_fail;\n"); Append(actioncode, " SWIG_fail;\n");
Append(f->code, "}\n"); Append(actioncode, "}\n");
} else { } else {
if (allow_thread) { if (allow_thread) {
thread_end_allow(n, f->code); thread_end_allow(n, actioncode);
Append(f->code, "}\n"); Append(actioncode, "}\n");
} }
} }
/* This part below still needs cleanup */ /* This part below still needs cleanup */
/* Return the function value */ /* 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) { if (funpack) {
Replaceall(tm, "$self", "swig_obj[0]"); Replaceall(tm, "$self", "swig_obj[0]");
} else { } else {
@ -2013,6 +2003,7 @@ public:
} else { } 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); 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 */ /* Output argument output code */
Printv(f->code, outarg, NIL); Printv(f->code, outarg, NIL);
@ -2187,7 +2178,7 @@ public:
if (Getattr(n, "tmap:varin:implicitconv")) { if (Getattr(n, "tmap:varin:implicitconv")) {
Replaceall(tm, "$implicitconv", get_implicitconv_flag(n)); Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
} }
emit_action_code(n, setf, tm); emit_action_code(n, setf->code, tm);
Delete(tm); Delete(tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0)); 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, "$source", name);
Replaceall(tm, "$target", "pyobj"); Replaceall(tm, "$target", "pyobj");
Replaceall(tm, "$result", "pyobj"); Replaceall(tm, "$result", "pyobj");
addfail = emit_action_code(n, getf, tm); addfail = emit_action_code(n, getf->code, tm);
Delete(tm); Delete(tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));

View file

@ -354,7 +354,6 @@ protected:
int outputRegistrationRoutines(File *out); int outputRegistrationRoutines(File *out);
int outputCommandLineArguments(File *out); int outputCommandLineArguments(File *out);
int generateCopyRoutinesObsolete(Node *n);
int generateCopyRoutines(Node *n); int generateCopyRoutines(Node *n);
int DumpCode(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); 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); // emit_attach_parmmaps(parms,f);
/* Using weird name and struct to avoid potential conflicts. */ /* 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_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. 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 // whereas the type makes are reverse
Wrapper_add_local(f, "ecode", "int ecode = 0"); Wrapper_add_local(f, "ecode", "int ecode = 0");
@ -1700,7 +1700,6 @@ int R::functionWrapper(Node *n) {
ParmList *l = Getattr(n, "parms"); ParmList *l = Getattr(n, "parms");
Parm *p; Parm *p;
String *returnTM = NULL;
String *tm; String *tm;
p = l; p = l;
@ -1775,11 +1774,11 @@ int R::functionWrapper(Node *n) {
Wrapper *f = NewWrapper(); Wrapper *f = NewWrapper();
Wrapper *sfun = NewWrapper(); Wrapper *sfun = NewWrapper();
int isVoidReturnType = (Strcmp(type, "void") == 0);
int isVoidReturnType = 0; // Need to use the unresolved return type since
returnTM = Swig_typemap_lookup_new("out", n, "result",0); // typedef resolution removes the const which causes a
if(returnTM) // mismatch with the function action
isVoidReturnType = (Strcmp(type, "void") == 0); emit_return_variable(n, unresolved_return_type, f);
SwigType *rtype = Getattr(n, "type"); SwigType *rtype = Getattr(n, "type");
int addCopyParam = 0; int addCopyParam = 0;
@ -1808,10 +1807,7 @@ int R::functionWrapper(Node *n) {
Swig_typemap_attach_parms("scoerceout", l, f); Swig_typemap_attach_parms("scoerceout", l, f);
Swig_typemap_attach_parms("scheck", l, f); Swig_typemap_attach_parms("scheck", l, f);
// Need to use the unresolved return type since emit_parameter_variables(l, f);
// typedef resolution removes the const which causes a
// mismatch with the function action
emit_args(unresolved_return_type, l, f);
emit_attach_parmmaps(l,f); emit_attach_parmmaps(l,f);
Setattr(n,"wrap:parms",l); Setattr(n,"wrap:parms",l);
@ -1989,16 +1985,9 @@ int R::functionWrapper(Node *n) {
} }
} }
emit_action(n, f);
String *outargs = NewString(""); String *outargs = NewString("");
int numOutArgs = isVoidReturnType ? -1 : 0; int numOutArgs = isVoidReturnType ? -1 : 0;
for(p = l, i = 0; p; i++) { for(p = l, i = 0; p; i++) {
String *tm;
if((tm = Getattr(p, "tmap:argout"))) { if((tm = Getattr(p, "tmap:argout"))) {
// String *lname = Getattr(p, "lname"); // String *lname = Getattr(p, "lname");
numOutArgs++; numOutArgs++;
@ -2017,9 +2006,10 @@ int R::functionWrapper(Node *n) {
p = nextSibling(p); p = nextSibling(p);
} }
String *actioncode = emit_action(n);
/* Deal with the explicit return value. */ /* Deal with the explicit return value. */
if (returnTM) { if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
String *tm = returnTM;
SwigType *retType = Getattr(n, "type"); SwigType *retType = Getattr(n, "type");
//Printf(stderr, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no"); //Printf(stderr, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no");
/* if(SwigType_isarray(retType)) { /* if(SwigType_isarray(retType)) {
@ -2168,185 +2158,6 @@ int R::functionWrapper(Node *n) {
return SWIG_OK; 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, "<defineArrayAccessors> 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 Add the specified routine name to the collection of
generated routines that are called from R functions. generated routines that are called from R functions.
@ -2583,219 +2394,6 @@ int R::classDeclaration(Node *n) {
in all cases. 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) { int R::generateCopyRoutines(Node *n) {
Wrapper *copyToR = NewWrapper(); Wrapper *copyToR = NewWrapper();
Wrapper *copyToC = NewWrapper(); Wrapper *copyToC = NewWrapper();

View file

@ -1649,7 +1649,7 @@ public:
/* Emit arguments */ /* Emit arguments */
if (current != CONSTRUCTOR_ALLOCATE) { if (current != CONSTRUCTOR_ALLOCATE) {
emit_args(t, l, f); emit_parameter_variables(l, f);
} }
/* Attach standard typemaps */ /* Attach standard typemaps */
@ -1773,72 +1773,79 @@ public:
Setattr(n, "wrap:name", wname); Setattr(n, "wrap:name", wname);
emit_action(n, f); Swig_director_emit_dynamic_cast(n, f);
String *actioncode = emit_action(n);
if (director_method) { if (director_method) {
Printf(f->code, "} catch (Swig::DirectorException& e) {\n"); Printf(actioncode, "} catch (Swig::DirectorException& e) {\n");
Printf(f->code, " rb_exc_raise(e.getError());\n"); Printf(actioncode, " rb_exc_raise(e.getError());\n");
Printf(f->code, " SWIG_fail;\n"); Printf(actioncode, " SWIG_fail;\n");
Printf(f->code, "}\n"); Printf(actioncode, "}\n");
} }
}
/* Return value if necessary */ /* Return value if necessary */
if (SwigType_type(t) != T_VOID && current != CONSTRUCTOR_ALLOCATE && current != CONSTRUCTOR_INITIALIZE) { if (SwigType_type(t) != T_VOID && current != CONSTRUCTOR_INITIALIZE) {
need_result = 1; need_result = 1;
if (GetFlag(n, "feature:predicate")) { if (GetFlag(n, "feature:predicate")) {
Printv(f->code, tab4, "vresult = (result ? Qtrue : Qfalse);\n", NIL); Printv(actioncode, tab4, "vresult = (result ? Qtrue : Qfalse);\n", NIL);
} else { } else {
tm = Swig_typemap_lookup_new("out", n, "result", 0); tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode);
if (tm) { actioncode = 0;
Replaceall(tm, "$result", "vresult"); if (tm) {
Replaceall(tm, "$source", "result"); Replaceall(tm, "$result", "vresult");
Replaceall(tm, "$target", "vresult"); Replaceall(tm, "$source", "result");
Replaceall(tm, "$target", "vresult");
if (GetFlag(n, "feature:new")) if (GetFlag(n, "feature:new"))
Replaceall(tm, "$owner", "SWIG_POINTER_OWN"); Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
else else
Replaceall(tm, "$owner", "0"); Replaceall(tm, "$owner", "0");
#if 1 #if 1
// FIXME: this will not try to unwrap directors returned as non-director // FIXME: this will not try to unwrap directors returned as non-director
// base class pointers! // base class pointers!
/* New addition to unwrap director return values so that the original /* New addition to unwrap director return values so that the original
* Ruby object is returned instead. * Ruby object is returned instead.
*/ */
bool unwrap = false; bool unwrap = false;
String *decl = Getattr(n, "decl"); String *decl = Getattr(n, "decl");
int is_pointer = SwigType_ispointer_return(decl); int is_pointer = SwigType_ispointer_return(decl);
int is_reference = SwigType_isreference_return(decl); int is_reference = SwigType_isreference_return(decl);
if (is_pointer || is_reference) { if (is_pointer || is_reference) {
String *type = Getattr(n, "type"); String *type = Getattr(n, "type");
Node *parent = Swig_methodclass(n); Node *parent = Swig_methodclass(n);
Node *modname = Getattr(parent, "module"); Node *modname = Getattr(parent, "module");
Node *target = Swig_directormap(modname, type); Node *target = Swig_directormap(modname, type);
if (target) if (target)
unwrap = true; unwrap = true;
} }
if (unwrap) { if (unwrap) {
Wrapper_add_local(f, "director", "Swig::Director *director = 0"); Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "director = dynamic_cast<Swig::Director *>(result);\n"); Printf(f->code, "director = dynamic_cast<Swig::Director *>(result);\n");
Printf(f->code, "if (director) {\n"); Printf(f->code, "if (director) {\n");
Printf(f->code, " vresult = director->swig_get_self();\n"); Printf(f->code, " vresult = director->swig_get_self();\n");
Printf(f->code, "} else {\n"); Printf(f->code, "} else {\n");
Printf(f->code, "%s\n", tm); Printf(f->code, "%s\n", tm);
Printf(f->code, "}\n"); Printf(f->code, "}\n");
director_method = 0; director_method = 0;
} else { } else {
Printf(f->code, "%s\n", tm); Printf(f->code, "%s\n", tm);
} }
#else #else
Printf(f->code, "%s\n", tm); Printf(f->code, "%s\n", tm);
#endif #endif
Delete(tm); Delete(tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s.\n", SwigType_str(t, 0)); 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 */ /* Extra code needed for new and initialize methods */
@ -2108,7 +2115,7 @@ public:
Replaceall(tm, "$target", "_val"); Replaceall(tm, "$target", "_val");
Replaceall(tm, "$source", name); Replaceall(tm, "$source", name);
/* Printv(getf->code,tm, NIL); */ /* Printv(getf->code,tm, NIL); */
addfail = emit_action_code(n, getf, tm); addfail = emit_action_code(n, getf->code, tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); 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, "$source", "_val");
Replaceall(tm, "$target", name); Replaceall(tm, "$target", name);
/* Printv(setf->code,tm,"\n",NIL); */ /* Printv(setf->code,tm,"\n",NIL); */
emit_action_code(n, setf, tm); emit_action_code(n, setf->code, tm);
} else { } else {
Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s\n", SwigType_str(t, 0)); Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s\n", SwigType_str(t, 0));
} }

View file

@ -310,7 +310,8 @@ private:
}; };
int SWIG_main(int, char **, Language *); 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_exit(int); /* use EXIT_{SUCCESS,FAILURE} */
void SWIG_config_file(const String_or_char *); void SWIG_config_file(const String_or_char *);
const String *SWIG_output_directory(); const String *SWIG_output_directory();
@ -322,8 +323,8 @@ int emit_num_required(ParmList *);
int emit_isvarargs(ParmList *); int emit_isvarargs(ParmList *);
void emit_attach_parmmaps(ParmList *, Wrapper *f); void emit_attach_parmmaps(ParmList *, Wrapper *f);
void emit_mark_varargs(ParmList *l); void emit_mark_varargs(ParmList *l);
void emit_action(Node *n, Wrapper *f); String *emit_action(Node *n);
int emit_action_code(Node *n, Wrapper *f, String *action); int emit_action_code(Node *n, String *wrappercode, String *action);
void Swig_overload_check(Node *n); void Swig_overload_check(Node *n);
String *Swig_overload_dispatch(Node *n, const String_or_char *fmt, int *); 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 *); 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_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_method_decl(SwigType *rtype, SwigType *decl, const String_or_char *id, List *args, int strip, int values);
String *Swig_director_declaration(Node *n); String *Swig_director_declaration(Node *n);
void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f);
/* directors.cxx end */ /* directors.cxx end */
extern "C" { extern "C" {

View file

@ -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); 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 all of the local variables for holding arguments.
emit_args(type, parms, f); emit_parameter_variables(parms, f);
/* Attach standard typemaps */ /* Attach standard typemaps */
emit_attach_parmmaps(parms, f); emit_attach_parmmaps(parms, f);
@ -443,12 +443,12 @@ public:
} }
/* Now write code to make the function call */ /* 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) */ /* Need to redo all of this code (eventually) */
/* Return value if necessary */ /* 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"); Replaceall(tm, "$source", "result");
#ifdef SWIG_USE_RESULTOBJ #ifdef SWIG_USE_RESULTOBJ
Replaceall(tm, "$target", "resultobj"); Replaceall(tm, "$target", "resultobj");
@ -466,6 +466,7 @@ public:
} else { } 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); 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 */ /* Dump output argument code */
Printv(f->code, outarg, NIL); Printv(f->code, outarg, NIL);
@ -570,7 +571,7 @@ public:
Replaceall(tm, "$target", "value"); Replaceall(tm, "$target", "value");
Replaceall(tm, "$result", "value"); Replaceall(tm, "$result", "value");
/* Printf(getf->code, "%s\n",tm); */ /* 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, "if (value) {\n");
Printf(getf->code, "Tcl_SetVar2(interp,name1,name2,Tcl_GetStringFromObj(value,NULL), flags);\n"); Printf(getf->code, "Tcl_SetVar2(interp,name1,name2,Tcl_GetStringFromObj(value,NULL), flags);\n");
Printf(getf->code, "Tcl_DecrRefCount(value);\n"); Printf(getf->code, "Tcl_DecrRefCount(value);\n");
@ -610,7 +611,7 @@ public:
Printf(setf->code, "Tcl_DecrRefCount(name1o);\n"); Printf(setf->code, "Tcl_DecrRefCount(name1o);\n");
Printf(setf->code, "if (!value) SWIG_fail;\n"); Printf(setf->code, "if (!value) SWIG_fail;\n");
/* Printf(setf->code,"%s\n", tm); */ /* 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, "return NULL;\n");
Printf(setf->code, "fail:\n"); Printf(setf->code, "fail:\n");
Printf(setf->code, "return \"%s\";\n", iname); Printf(setf->code, "return \"%s\";\n", iname);

View file

@ -373,6 +373,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
String_or_char *source, String_or_char *target, Wrapper *f); 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_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_attach_kwargs(Hash *tm, const String_or_char *op, Parm *p);
extern void Swig_typemap_new_scope(void); extern void Swig_typemap_new_scope(void);
extern Hash *Swig_typemap_pop_scope(void); extern Hash *Swig_typemap_pop_scope(void);

View file

@ -802,10 +802,11 @@ int check_locals(ParmList *p, const char *s) {
} }
static 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 var[512];
char *varname; char *varname;
SwigType *ftype; SwigType *ftype;
int bare_substitution_count = 0;
Replaceall(s, "$typemap", "$TYPEMAP"); Replaceall(s, "$typemap", "$TYPEMAP");
@ -1086,8 +1087,9 @@ void typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType
/* Replace the bare $n variable */ /* Replace the bare $n variable */
sprintf(var, "$%d", index); sprintf(var, "$%d", index);
Replace(s, var, lname, DOH_REPLACE_ANY); bare_substitution_count = Replace(s, var, lname, DOH_REPLACE_ANY);
Delete(ftype); 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 * Attach one or more typemaps to a node
* op - typemap name, eg "out", "newfree" * op - typemap name, eg "out", "newfree"
* node - the node to attach the typemaps to * node - the node to attach the typemaps to
* lname - * lname - name of variable to substitute $1, $2 etc for
* f - * 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 *type;
SwigType *mtype = 0; SwigType *mtype = 0;
String *pname; String *pname;
@ -1248,6 +1250,10 @@ String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const Stri
String *cname = 0; String *cname = 0;
String *clname = 0; String *clname = 0;
char *cop = Char(op); 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 /* special case, we need to check for 'ref' call
and set the default code 'sdef' */ and set the default code 'sdef' */
if (node && Cmp(op, "newfree") == 0) { 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 */ 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"); locals = Getattr(tm, "locals");
if (locals) if (locals)
locals = CopyParmList(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)) { 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 { } 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) { if (locals && f) {
typemap_locals(s, locals, f, -1); typemap_locals(s, locals, f, -1);
} }
replace_embedded_typemap(s); 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); 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"); 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 */ /* Look for warnings */
{ {
String *w; String *w;
@ -1387,21 +1434,30 @@ String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const Stri
} }
} }
if (cname) Delete(cname);
Delete(cname); Delete(clname);
if (clname) Delete(mtype);
Delete(clname);
if (mtype)
Delete(mtype);
if (sdef) { /* put 'ref' and 'newfree' codes together */ if (sdef) { /* put 'ref' and 'newfree' codes together */
String *p = NewStringf("%s\n%s", sdef, s); String *p = NewStringf("%s\n%s", sdef, s);
Delete(s); Delete(s);
Delete(sdef); Delete(sdef);
s = p; s = p;
} }
Delete(actioncode);
return s; 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() * Swig_typemap_attach_kwargs()
* *