mirror of https://github.com/swig/swig
1647 lines
50 KiB
C
1647 lines
50 KiB
C
/* -----------------------------------------------------------------------------
|
|
* This file is part of SWIG, which is licensed as a whole under version 3
|
|
* (or any later version) of the GNU General Public License. Some additional
|
|
* terms also apply to certain portions of SWIG. The full details of the SWIG
|
|
* license and copyrights can be found in the LICENSE and COPYRIGHT files
|
|
* included with the SWIG source code as distributed by the SWIG developers
|
|
* and at http://www.swig.org/legal.html.
|
|
*
|
|
* cwrap.c
|
|
*
|
|
* This file defines a variety of wrapping rules for C/C++ handling including
|
|
* the naming of local variables, calling conventions, and so forth.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
#include "swig.h"
|
|
#include "cparse.h"
|
|
|
|
static const char *cresult_variable_name = "result";
|
|
|
|
static Parm *nonvoid_parms(Parm *p) {
|
|
if (p) {
|
|
SwigType *t = Getattr(p, "type");
|
|
if (SwigType_type(t) == T_VOID)
|
|
return 0;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cresult_name_set()
|
|
*
|
|
* Change the name of the variable used to hold the return value from C/C++ wrapper functions
|
|
* from the default "result".
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void Swig_cresult_name_set(const char *new_name) {
|
|
cresult_variable_name = new_name;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cresult_name()
|
|
*
|
|
* Get the name of the variable used to hold the return value from C/C++ wrapper functions
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
const char *Swig_cresult_name(void) {
|
|
return cresult_variable_name;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cparm_name()
|
|
*
|
|
* Generates a name for the ith argument in an argument list
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_cparm_name(Parm *p, int i) {
|
|
String *name = NewStringf("arg%d", i + 1);
|
|
if (p) {
|
|
Setattr(p, "lname", name);
|
|
}
|
|
|
|
return name;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_clocal()
|
|
*
|
|
* Creates a string that declares a C local variable type. Converts references
|
|
* and user defined types to pointers.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static String *Swig_clocal(SwigType *t, const_String_or_char_ptr name, const_String_or_char_ptr value) {
|
|
String *decl;
|
|
|
|
decl = NewStringEmpty();
|
|
|
|
switch (SwigType_type(t)) {
|
|
case T_REFERENCE:
|
|
if (value) {
|
|
String *lstrname = SwigType_lstr(t, name);
|
|
String *lstr = SwigType_lstr(t, 0);
|
|
Printf(decl, "%s = (%s) &%s_defvalue", lstrname, lstr, name);
|
|
Delete(lstrname);
|
|
Delete(lstr);
|
|
} else {
|
|
String *lstrname = SwigType_lstr(t, name);
|
|
Printf(decl, "%s = 0", lstrname);
|
|
Delete(lstrname);
|
|
}
|
|
break;
|
|
case T_RVALUE_REFERENCE:
|
|
if (value) {
|
|
String *lstrname = SwigType_lstr(t, name);
|
|
String *lstr = SwigType_lstr(t, 0);
|
|
Printf(decl, "%s = (%s) &%s_defrvalue", lstrname, lstr, name);
|
|
Delete(lstrname);
|
|
Delete(lstr);
|
|
} else {
|
|
String *lstrname = SwigType_lstr(t, name);
|
|
Printf(decl, "%s = 0", lstrname);
|
|
Delete(lstrname);
|
|
}
|
|
break;
|
|
case T_VOID:
|
|
break;
|
|
case T_VARARGS:
|
|
Printf(decl, "void *%s = 0", name);
|
|
break;
|
|
|
|
default:
|
|
if (value) {
|
|
String *lcaststr = SwigType_lcaststr(t, value);
|
|
String *lstr = SwigType_lstr(t, 0);
|
|
String *lstrn = SwigType_lstr(t, name);
|
|
Printf(decl, "%s = (%s) %s", lstrn, lstr, lcaststr);
|
|
Delete(lcaststr);
|
|
Delete(lstr);
|
|
Delete(lstrn);
|
|
} else {
|
|
String *lstrname = SwigType_lstr(t, name);
|
|
Append(decl, lstrname);
|
|
Delete(lstrname);
|
|
}
|
|
}
|
|
return decl;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_wrapped_var_convert()
|
|
*
|
|
* Converts a member variable for use in the get and set wrapper methods.
|
|
* This function only converts user defined types to pointers.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_wrapped_var_type(SwigType *t, int varcref) {
|
|
SwigType *ty;
|
|
|
|
if (!Strstr(t, "enum $unnamed")) {
|
|
ty = Copy(t);
|
|
} else {
|
|
/* Change the type for unnamed enum instance variables */
|
|
ty = NewString("int");
|
|
}
|
|
|
|
if (SwigType_isclass(t)) {
|
|
if (varcref) {
|
|
if (cparse_cplusplus) {
|
|
if (!SwigType_isconst(ty))
|
|
SwigType_add_qualifier(ty, "const");
|
|
SwigType_add_reference(ty);
|
|
} else {
|
|
return Copy(ty);
|
|
}
|
|
} else {
|
|
SwigType_add_pointer(ty);
|
|
}
|
|
}
|
|
return ty;
|
|
}
|
|
|
|
String *Swig_wrapped_member_var_type(SwigType *t, int varcref) {
|
|
SwigType *ty;
|
|
|
|
if (!Strstr(t, "enum $unnamed")) {
|
|
ty = Copy(t);
|
|
} else {
|
|
/* Change the type for unnamed enum instance variables */
|
|
ty = NewString("int");
|
|
}
|
|
if (SwigType_isclass(t)) {
|
|
if (varcref) {
|
|
if (cparse_cplusplus) {
|
|
if (!SwigType_isconst(ty))
|
|
SwigType_add_qualifier(ty, "const");
|
|
SwigType_add_reference(ty);
|
|
} else {
|
|
return Copy(ty);
|
|
}
|
|
} else {
|
|
SwigType_add_pointer(ty);
|
|
}
|
|
}
|
|
return ty;
|
|
}
|
|
|
|
|
|
static String *Swig_wrapped_var_deref(SwigType *t, const_String_or_char_ptr name, int varcref) {
|
|
if (SwigType_isclass(t)) {
|
|
if (varcref) {
|
|
if (cparse_cplusplus) {
|
|
return NewStringf("*%s", name);
|
|
} else {
|
|
return NewStringf("%s", name);
|
|
}
|
|
} else {
|
|
return NewStringf("*%s", name);
|
|
}
|
|
} else {
|
|
return SwigType_rcaststr(t, name);
|
|
}
|
|
}
|
|
|
|
static String *Swig_wrapped_var_assign(SwigType *t, const_String_or_char_ptr name, int varcref) {
|
|
if (SwigType_isclass(t)) {
|
|
if (varcref) {
|
|
return NewStringf("%s", name);
|
|
} else {
|
|
return NewStringf("&%s", name);
|
|
}
|
|
} else {
|
|
return SwigType_lcaststr(t, name);
|
|
}
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cargs()
|
|
*
|
|
* Emit all of the local variables for a list of parameters. Returns the
|
|
* number of parameters.
|
|
* Default values for the local variables are only emitted if the compact default
|
|
* argument behaviour is required.
|
|
* ----------------------------------------------------------------------------- */
|
|
int Swig_cargs(Wrapper *w, ParmList *p) {
|
|
int i = 0;
|
|
int compactdefargs = ParmList_is_compactdefargs(p);
|
|
|
|
while (p != 0) {
|
|
String *lname = Swig_cparm_name(p, i);
|
|
SwigType *pt = Getattr(p, "type");
|
|
if ((SwigType_type(pt) != T_VOID)) {
|
|
String *local = 0;
|
|
String *type = Getattr(p, "type");
|
|
/* default values only emitted if in compact default args mode */
|
|
String *pvalue = (compactdefargs) ? Getattr(p, "value") : 0;
|
|
|
|
/* When using compactdefaultargs, the code generated initialises a variable via a constructor call that accepts the
|
|
* default value as a parameter. The default constructor is not called and therefore SwigValueWrapper is not needed. */
|
|
SwigType *altty = pvalue ? 0 : SwigType_alttype(type, 0);
|
|
|
|
int tycode = SwigType_type(type);
|
|
if (tycode == T_REFERENCE) {
|
|
if (pvalue) {
|
|
SwigType *tvalue;
|
|
String *defname, *defvalue, *rvalue, *qvalue;
|
|
rvalue = SwigType_typedef_resolve_all(pvalue);
|
|
qvalue = SwigType_typedef_qualified(rvalue);
|
|
defname = NewStringf("%s_defvalue", lname);
|
|
tvalue = Copy(type);
|
|
SwigType_del_reference(tvalue);
|
|
tycode = SwigType_type(tvalue);
|
|
if (tycode != T_USER) {
|
|
/* plain primitive type, we copy the def value */
|
|
String *lstr = SwigType_lstr(tvalue, defname);
|
|
defvalue = NewStringf("%s = %s", lstr, qvalue);
|
|
Delete(lstr);
|
|
} else {
|
|
/* user type, we copy the reference value */
|
|
String *str = SwigType_str(type, defname);
|
|
defvalue = NewStringf("%s = %s", str, qvalue);
|
|
Delete(str);
|
|
}
|
|
Wrapper_add_localv(w, defname, defvalue, NIL);
|
|
Delete(tvalue);
|
|
Delete(rvalue);
|
|
Delete(qvalue);
|
|
Delete(defname);
|
|
Delete(defvalue);
|
|
}
|
|
} else if (tycode == T_RVALUE_REFERENCE) {
|
|
if (pvalue) {
|
|
SwigType *tvalue;
|
|
String *defname, *defvalue, *rvalue, *qvalue;
|
|
rvalue = SwigType_typedef_resolve_all(pvalue);
|
|
qvalue = SwigType_typedef_qualified(rvalue);
|
|
defname = NewStringf("%s_defrvalue", lname);
|
|
tvalue = Copy(type);
|
|
SwigType_del_rvalue_reference(tvalue);
|
|
tycode = SwigType_type(tvalue);
|
|
if (tycode != T_USER) {
|
|
/* plain primitive type, we copy the def value */
|
|
String *lstr = SwigType_lstr(tvalue, defname);
|
|
defvalue = NewStringf("%s = %s", lstr, qvalue);
|
|
Delete(lstr);
|
|
} else {
|
|
/* user type, we copy the reference value */
|
|
String *str = SwigType_str(type, defname);
|
|
defvalue = NewStringf("%s = %s", str, qvalue);
|
|
Delete(str);
|
|
}
|
|
Wrapper_add_localv(w, defname, defvalue, NIL);
|
|
Delete(tvalue);
|
|
Delete(rvalue);
|
|
Delete(qvalue);
|
|
Delete(defname);
|
|
Delete(defvalue);
|
|
}
|
|
} else if (!pvalue && ((tycode == T_POINTER) || (tycode == T_STRING) || (tycode == T_WSTRING))) {
|
|
pvalue = (String *) "0";
|
|
}
|
|
if (!altty) {
|
|
local = Swig_clocal(pt, lname, pvalue);
|
|
} else {
|
|
local = Swig_clocal(altty, lname, pvalue);
|
|
Delete(altty);
|
|
}
|
|
Wrapper_add_localv(w, lname, local, NIL);
|
|
Delete(local);
|
|
i++;
|
|
}
|
|
Delete(lname);
|
|
p = nextSibling(p);
|
|
}
|
|
return (i);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cresult()
|
|
*
|
|
* This function generates the C code needed to set the result of a C
|
|
* function call.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_cresult(SwigType *t, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
|
|
String *fcall;
|
|
|
|
fcall = NewStringEmpty();
|
|
switch (SwigType_type(t)) {
|
|
case T_VOID:
|
|
break;
|
|
case T_REFERENCE:
|
|
{
|
|
String *lstr = SwigType_lstr(t, 0);
|
|
Printf(fcall, "%s = (%s) &", name, lstr);
|
|
Delete(lstr);
|
|
}
|
|
break;
|
|
case T_RVALUE_REFERENCE:
|
|
{
|
|
String *const_lvalue_str;
|
|
String *lstr = SwigType_lstr(t, 0);
|
|
SwigType *tt = Copy(t);
|
|
SwigType_del_rvalue_reference(tt);
|
|
SwigType_add_qualifier(tt, "const");
|
|
SwigType_add_reference(tt);
|
|
const_lvalue_str = SwigType_rcaststr(tt, 0);
|
|
|
|
Printf(fcall, "%s = (%s) &%s", name, lstr, const_lvalue_str);
|
|
|
|
Delete(const_lvalue_str);
|
|
Delete(tt);
|
|
Delete(lstr);
|
|
}
|
|
break;
|
|
case T_USER:
|
|
Printf(fcall, "%s = ", name);
|
|
break;
|
|
|
|
default:
|
|
/* Normal return value */
|
|
{
|
|
String *lstr = SwigType_lstr(t, 0);
|
|
Printf(fcall, "%s = (%s)", name, lstr);
|
|
Delete(lstr);
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* Now print out function call */
|
|
Append(fcall, decl);
|
|
|
|
/* A sick hack */
|
|
{
|
|
char *c = Char(decl) + Len(decl) - 1;
|
|
if (!((*c == ';') || (*c == '}')))
|
|
Append(fcall, ";");
|
|
}
|
|
|
|
return fcall;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cfunction_call()
|
|
*
|
|
* Creates a string that calls a C function using the local variable rules
|
|
* defined above.
|
|
*
|
|
* name(arg0, arg1, arg2, ... argn)
|
|
*
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_cfunction_call(const_String_or_char_ptr name, ParmList *parms) {
|
|
String *func;
|
|
int i = 0;
|
|
int comma = 0;
|
|
Parm *p = parms;
|
|
String *nname;
|
|
|
|
func = NewStringEmpty();
|
|
nname = SwigType_namestr(name);
|
|
|
|
/*
|
|
SWIGTEMPLATEDISAMBIGUATOR is compiler dependent (swiglabels.swg),
|
|
- SUN Studio 9 requires 'template',
|
|
- gcc-3.4 forbids the use of 'template'.
|
|
the rest seems not caring very much,
|
|
*/
|
|
if (SwigType_istemplate(name)) {
|
|
String *prefix = Swig_scopename_prefix(nname);
|
|
if (!prefix || Len(prefix) == 0) {
|
|
Printf(func, "%s(", nname);
|
|
} else {
|
|
String *last = Swig_scopename_last(nname);
|
|
Printf(func, "%s::SWIGTEMPLATEDISAMBIGUATOR %s(", prefix, last);
|
|
Delete(last);
|
|
}
|
|
Delete(prefix);
|
|
} else {
|
|
Printf(func, "%s(", nname);
|
|
}
|
|
Delete(nname);
|
|
|
|
while (p) {
|
|
SwigType *pt = Getattr(p, "type");
|
|
if ((SwigType_type(pt) != T_VOID)) {
|
|
SwigType *rpt = SwigType_typedef_resolve_all(pt);
|
|
String *pname = Swig_cparm_name(p, i);
|
|
String *rcaststr = SwigType_rcaststr(rpt, pname);
|
|
|
|
if (comma) {
|
|
Printv(func, ",", rcaststr, NIL);
|
|
} else {
|
|
Append(func, rcaststr);
|
|
}
|
|
Delete(rpt);
|
|
Delete(pname);
|
|
Delete(rcaststr);
|
|
comma = 1;
|
|
i++;
|
|
}
|
|
p = nextSibling(p);
|
|
}
|
|
Append(func, ")");
|
|
return func;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cmethod_call()
|
|
*
|
|
* Generates a string that calls a C++ method from a list of parameters.
|
|
*
|
|
* arg0->name(arg1, arg2, arg3, ..., argn)
|
|
*
|
|
* self is an argument that defines how to handle the first argument. Normally,
|
|
* it should be set to "this->". With C++ proxy classes enabled, it could be
|
|
* set to "(*this)->" or some similar sequence.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static String *Swig_cmethod_call(const_String_or_char_ptr name, ParmList *parms, const_String_or_char_ptr self, String *explicit_qualifier, SwigType *director_type) {
|
|
String *func, *nname;
|
|
int i = 0;
|
|
Parm *p = parms;
|
|
SwigType *pt;
|
|
int comma = 0;
|
|
|
|
func = NewStringEmpty();
|
|
if (!p)
|
|
return func;
|
|
|
|
if (!self)
|
|
self = "(this)->";
|
|
Append(func, self);
|
|
|
|
if (SwigType_istemplate(name) && (strncmp(Char(name), "operator ", 9) == 0)) {
|
|
/* fix for template + operators and compilers like gcc 3.3.5 */
|
|
String *tprefix = SwigType_templateprefix(name);
|
|
nname = tprefix;
|
|
} else {
|
|
nname = SwigType_namestr(name);
|
|
}
|
|
|
|
if (director_type) {
|
|
const char *pname = "darg";
|
|
String *rcaststr = SwigType_rcaststr(director_type, pname);
|
|
Replaceall(func, "this", rcaststr);
|
|
Delete(rcaststr);
|
|
} else {
|
|
pt = Getattr(p, "type");
|
|
|
|
/* If the method is invoked through a dereferenced pointer, we don't add any casts
|
|
(needed for smart pointers). Otherwise, we cast to the appropriate type */
|
|
|
|
if (Strstr(func, "*this")) {
|
|
String *pname = Swig_cparm_name(p, 0);
|
|
Replaceall(func, "this", pname);
|
|
Delete(pname);
|
|
} else {
|
|
String *pname = Swig_cparm_name(p, 0);
|
|
String *rcaststr = SwigType_rcaststr(pt, pname);
|
|
Replaceall(func, "this", rcaststr);
|
|
Delete(rcaststr);
|
|
Delete(pname);
|
|
}
|
|
|
|
/*
|
|
SWIGTEMPLATEDESIMBUAGATOR is compiler dependent (swiglabels.swg),
|
|
- SUN Studio 9 requires 'template',
|
|
- gcc-3.4 forbids the use of 'template' (correctly implementing the ISO C++ standard)
|
|
the others don't seem to care,
|
|
*/
|
|
if (SwigType_istemplate(name))
|
|
Printf(func, "SWIGTEMPLATEDISAMBIGUATOR ");
|
|
|
|
if (explicit_qualifier) {
|
|
Printv(func, explicit_qualifier, "::", NIL);
|
|
}
|
|
}
|
|
|
|
Printf(func, "%s(", nname);
|
|
|
|
i++;
|
|
p = nextSibling(p);
|
|
while (p) {
|
|
pt = Getattr(p, "type");
|
|
if ((SwigType_type(pt) != T_VOID)) {
|
|
String *pname = Swig_cparm_name(p, i);
|
|
String *rcaststr = SwigType_rcaststr(pt, pname);
|
|
if (comma)
|
|
Append(func, ",");
|
|
Append(func, rcaststr);
|
|
Delete(rcaststr);
|
|
Delete(pname);
|
|
comma = 1;
|
|
i++;
|
|
}
|
|
p = nextSibling(p);
|
|
}
|
|
Append(func, ")");
|
|
Delete(nname);
|
|
return func;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cconstructor_call()
|
|
*
|
|
* Creates a string that calls a C constructor function.
|
|
*
|
|
* calloc(1,sizeof(name));
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_cconstructor_call(const_String_or_char_ptr name) {
|
|
DOH *func;
|
|
|
|
func = NewStringEmpty();
|
|
Printf(func, "calloc(1, sizeof(%s))", name);
|
|
return func;
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cppconstructor_call()
|
|
*
|
|
* Creates a string that calls a C function using the local variable rules
|
|
* defined above.
|
|
*
|
|
* name(arg0, arg1, arg2, ... argn)
|
|
*
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_cppconstructor_base_call(const_String_or_char_ptr name, ParmList *parms, int skip_self) {
|
|
String *func;
|
|
String *nname;
|
|
int i = 0;
|
|
int comma = 0;
|
|
Parm *p = parms;
|
|
SwigType *pt;
|
|
if (skip_self) {
|
|
if (p)
|
|
p = nextSibling(p);
|
|
i++;
|
|
}
|
|
nname = SwigType_namestr(name);
|
|
func = NewStringEmpty();
|
|
Printf(func, "new %s(", nname);
|
|
while (p) {
|
|
pt = Getattr(p, "type");
|
|
if ((SwigType_type(pt) != T_VOID)) {
|
|
String *rcaststr = 0;
|
|
String *pname = 0;
|
|
if (comma)
|
|
Append(func, ",");
|
|
if (!Getattr(p, "arg:byname")) {
|
|
pname = Swig_cparm_name(p, i);
|
|
i++;
|
|
} else {
|
|
pname = Getattr(p, "value");
|
|
if (pname)
|
|
pname = Copy(pname);
|
|
else
|
|
pname = Copy(Getattr(p, "name"));
|
|
}
|
|
rcaststr = SwigType_rcaststr(pt, pname);
|
|
Append(func, rcaststr);
|
|
Delete(rcaststr);
|
|
comma = 1;
|
|
Delete(pname);
|
|
}
|
|
p = nextSibling(p);
|
|
}
|
|
Append(func, ")");
|
|
Delete(nname);
|
|
return func;
|
|
}
|
|
|
|
String *Swig_cppconstructor_call(const_String_or_char_ptr name, ParmList *parms) {
|
|
return Swig_cppconstructor_base_call(name, parms, 0);
|
|
}
|
|
|
|
String *Swig_cppconstructor_nodirector_call(const_String_or_char_ptr name, ParmList *parms) {
|
|
return Swig_cppconstructor_base_call(name, parms, 1);
|
|
}
|
|
|
|
String *Swig_cppconstructor_director_call(const_String_or_char_ptr name, ParmList *parms) {
|
|
return Swig_cppconstructor_base_call(name, parms, 0);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* recursive_flag_search()
|
|
*
|
|
* This function searches for the class attribute 'attr' in the class
|
|
* 'n' or recursively in its bases.
|
|
*
|
|
* If you define SWIG_FAST_REC_SEARCH, the method will set the found
|
|
* 'attr' in the target class 'n'. If not, the method will set the
|
|
* 'noattr' one. This prevents of having to navigate the entire
|
|
* hierarchy tree every time, so, it is an O(1) method... or something
|
|
* like that. However, it populates all the parsed classes with the
|
|
* 'attr' and/or 'noattr' attributes.
|
|
*
|
|
* If you undefine the SWIG_FAST_REC_SEARCH no attribute will be set
|
|
* while searching. This could be slower for large projects with very
|
|
* large hierarchy trees... or maybe not. But it will be cleaner.
|
|
*
|
|
* Maybe later a swig option can be added to switch at runtime.
|
|
*
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
/* #define SWIG_FAST_REC_SEARCH 1 */
|
|
static String *recursive_flag_search(Node *n, const String *attr, const String *noattr) {
|
|
String *f = 0;
|
|
n = Swig_methodclass(n);
|
|
if (GetFlag(n, noattr)) {
|
|
return 0;
|
|
}
|
|
f = GetFlagAttr(n, attr);
|
|
if (f) {
|
|
return f;
|
|
} else {
|
|
List *bl = Getattr(n, "bases");
|
|
if (bl) {
|
|
Iterator bi;
|
|
for (bi = First(bl); bi.item; bi = Next(bi)) {
|
|
f = recursive_flag_search(bi.item, attr, noattr);
|
|
if (f) {
|
|
#ifdef SWIG_FAST_REC_SEARCH
|
|
SetFlagAttr(n, attr, f);
|
|
#endif
|
|
return f;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#ifdef SWIG_FAST_REC_SEARCH
|
|
SetFlag(n, noattr);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_unref_call()
|
|
*
|
|
* Find the "feature:unref" call, if any.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_unref_call(Node *n) {
|
|
String *unref = recursive_flag_search(n, "feature:unref", "feature:nounref");
|
|
if (unref) {
|
|
String *pname = Swig_cparm_name(0, 0);
|
|
unref = NewString(unref);
|
|
Replaceall(unref, "$this", pname);
|
|
Replaceall(unref, "$self", pname);
|
|
Delete(pname);
|
|
}
|
|
return unref;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_ref_call()
|
|
*
|
|
* Find the "feature:ref" call, if any.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_ref_call(Node *n, const String *lname) {
|
|
String *ref = recursive_flag_search(n, "feature:ref", "feature:noref");
|
|
if (ref) {
|
|
ref = NewString(ref);
|
|
Replaceall(ref, "$this", lname);
|
|
Replaceall(ref, "$self", lname);
|
|
}
|
|
return ref;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cdestructor_call()
|
|
*
|
|
* Creates a string that calls a C destructor function.
|
|
*
|
|
* free((char *) arg0);
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_cdestructor_call(Node *n) {
|
|
Node *cn = Swig_methodclass(n);
|
|
String *unref = Swig_unref_call(cn);
|
|
|
|
if (unref) {
|
|
return unref;
|
|
} else {
|
|
String *pname = Swig_cparm_name(0, 0);
|
|
String *call = NewStringf("free((char *) %s);", pname);
|
|
Delete(pname);
|
|
return call;
|
|
}
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cppdestructor_call()
|
|
*
|
|
* Creates a string that calls a C destructor function.
|
|
*
|
|
* delete arg1;
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_cppdestructor_call(Node *n) {
|
|
Node *cn = Swig_methodclass(n);
|
|
String *unref = Swig_unref_call(cn);
|
|
if (unref) {
|
|
return unref;
|
|
} else {
|
|
String *pname = Swig_cparm_name(0, 0);
|
|
String *call = NewStringf("delete %s;", pname);
|
|
Delete(pname);
|
|
return call;
|
|
}
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cmemberset_call()
|
|
*
|
|
* Generates a string that sets the name of a member in a C++ class or C struct.
|
|
*
|
|
* arg0->name = arg1
|
|
*
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_cmemberset_call(const_String_or_char_ptr name, SwigType *type, String *self, int varcref) {
|
|
String *func;
|
|
String *pname0 = Swig_cparm_name(0, 0);
|
|
String *pname1 = Swig_cparm_name(0, 1);
|
|
func = NewStringEmpty();
|
|
if (!self)
|
|
self = NewString("(this)->");
|
|
else
|
|
self = NewString(self);
|
|
Replaceall(self, "this", pname0);
|
|
if (SwigType_type(type) != T_ARRAY) {
|
|
if (!Strstr(type, "enum $unnamed")) {
|
|
String *dref = Swig_wrapped_var_deref(type, pname1, varcref);
|
|
int extra_cast = 0;
|
|
if (cparse_cplusplusout) {
|
|
/* Required for C nested structs compiled as C++ as a duplicate of the nested struct is put into the global namespace.
|
|
* We could improve this by adding the extra casts just for nested structs rather than all structs. */
|
|
String *base = SwigType_base(type);
|
|
extra_cast = SwigType_isclass(base);
|
|
Delete(base);
|
|
}
|
|
if (extra_cast) {
|
|
String *lstr;
|
|
SwigType *ptype = Copy(type);
|
|
SwigType_add_pointer(ptype);
|
|
lstr = SwigType_lstr(ptype, 0);
|
|
Printf(func, "if (%s) *(%s)&%s%s = %s", pname0, lstr, self, name, dref);
|
|
Delete(lstr);
|
|
Delete(ptype);
|
|
} else {
|
|
Printf(func, "if (%s) %s%s = %s", pname0, self, name, dref);
|
|
}
|
|
Delete(dref);
|
|
} else {
|
|
Printf(func, "if (%s && sizeof(int) == sizeof(%s%s)) *(int*)(void*)&(%s%s) = %s", pname0, self, name, self, name, pname1);
|
|
}
|
|
}
|
|
Delete(self);
|
|
Delete(pname0);
|
|
Delete(pname1);
|
|
return (func);
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cmemberget_call()
|
|
*
|
|
* Generates a string that sets the name of a member in a C++ class or C struct.
|
|
*
|
|
* arg0->name
|
|
*
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_cmemberget_call(const_String_or_char_ptr name, SwigType *t, String *self, int varcref) {
|
|
String *func;
|
|
String *call;
|
|
String *pname0 = Swig_cparm_name(0, 0);
|
|
if (!self)
|
|
self = NewString("(this)->");
|
|
else
|
|
self = NewString(self);
|
|
Replaceall(self, "this", pname0);
|
|
func = NewStringEmpty();
|
|
call = Swig_wrapped_var_assign(t, "", varcref);
|
|
Printf(func, "%s (%s%s)", call, self, name);
|
|
Delete(self);
|
|
Delete(call);
|
|
Delete(pname0);
|
|
return func;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_replace_special_variables()
|
|
*
|
|
* Replaces special variables with a value from the supplied node
|
|
* ----------------------------------------------------------------------------- */
|
|
void Swig_replace_special_variables(Node *n, Node *parentnode, String *code) {
|
|
Node *parentclass = parentnode;
|
|
String *overloaded = Getattr(n, "sym:overloaded");
|
|
Replaceall(code, "$name", Getattr(n, "name"));
|
|
Replaceall(code, "$symname", Getattr(n, "sym:name"));
|
|
Replaceall(code, "$wrapname", Getattr(n, "wrap:name"));
|
|
Replaceall(code, "$overname", overloaded ? Char(Getattr(n, "sym:overname")) : "");
|
|
|
|
if (Strstr(code, "$decl")) {
|
|
String *decl = Swig_name_decl(n);
|
|
Replaceall(code, "$decl", decl);
|
|
Delete(decl);
|
|
}
|
|
if (Strstr(code, "$fulldecl")) {
|
|
String *fulldecl = Swig_name_fulldecl(n);
|
|
Replaceall(code, "$fulldecl", fulldecl);
|
|
Delete(fulldecl);
|
|
}
|
|
|
|
if (parentclass && !Equal(nodeType(parentclass), "class"))
|
|
parentclass = 0;
|
|
if (Strstr(code, "$parentclasssymname")) {
|
|
String *parentclasssymname = 0;
|
|
if (parentclass)
|
|
parentclasssymname = Getattr(parentclass, "sym:name");
|
|
Replaceall(code, "$parentclasssymname", parentclasssymname ? parentclasssymname : "");
|
|
}
|
|
if (Strstr(code, "$parentclassname")) {
|
|
String *parentclassname = 0;
|
|
if (parentclass)
|
|
parentclassname = Getattr(parentclass, "name");
|
|
Replaceall(code, "$parentclassname", parentclassname ? SwigType_str(parentclassname, "") : "");
|
|
}
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* extension_code()
|
|
*
|
|
* Generates an extension function (a function defined in %extend)
|
|
*
|
|
* return_type function_name(parms) code
|
|
*
|
|
* ----------------------------------------------------------------------------- */
|
|
static String *extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self) {
|
|
String *parms_str = cplusplus ? ParmList_str_defaultargs(parms) : ParmList_str(parms);
|
|
String *sig = NewStringf("%s(%s)", function_name, (cplusplus || Len(parms_str)) ? parms_str : "void");
|
|
String *rt_sig = SwigType_str(return_type, sig);
|
|
String *body = NewStringf("SWIGINTERN %s", rt_sig);
|
|
Printv(body, code, "\n", NIL);
|
|
if (Strstr(body, "$")) {
|
|
Swig_replace_special_variables(n, parentNode(parentNode(n)), body);
|
|
if (self)
|
|
Replaceall(body, "$self", self);
|
|
}
|
|
Delete(parms_str);
|
|
Delete(sig);
|
|
Delete(rt_sig);
|
|
return body;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_add_extension_code()
|
|
*
|
|
* Generates an extension function (a function defined in %extend) and
|
|
* adds it to the "wrap:code" attribute of a node
|
|
*
|
|
* See also extension_code()
|
|
*
|
|
* ----------------------------------------------------------------------------- */
|
|
int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self) {
|
|
String *body = extension_code(n, function_name, parms, return_type, code, cplusplus, self);
|
|
Setattr(n, "wrap:code", body);
|
|
Delete(body);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_MethodToFunction(Node *n)
|
|
*
|
|
* Converts a C++ method node to a function accessor function.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int flags, SwigType *director_type, int is_director) {
|
|
String *name;
|
|
ParmList *parms;
|
|
SwigType *type;
|
|
Parm *p;
|
|
String *self = 0;
|
|
int is_smart_pointer_overload = 0;
|
|
String *qualifier = Getattr(n, "qualifier");
|
|
String *directorScope = NewString(nspace);
|
|
|
|
Replace(directorScope, NSPACE_SEPARATOR, "_", DOH_REPLACE_ANY);
|
|
|
|
/* If smart pointer without const overload or mutable method, change self dereferencing */
|
|
if (flags & CWRAP_SMART_POINTER) {
|
|
if (flags & CWRAP_SMART_POINTER_OVERLOAD) {
|
|
if (qualifier && strncmp(Char(qualifier), "q(const)", 8) == 0) {
|
|
self = NewString("(*(this))->");
|
|
is_smart_pointer_overload = 1;
|
|
}
|
|
else if (Swig_storage_isstatic(n)) {
|
|
String *cname = Getattr(n, "extendsmartclassname") ? Getattr(n, "extendsmartclassname") : classname;
|
|
String *ctname = SwigType_namestr(cname);
|
|
self = NewStringf("(*(%s const *)this)->", ctname);
|
|
is_smart_pointer_overload = 1;
|
|
Delete(ctname);
|
|
}
|
|
else {
|
|
self = NewString("(*this)->");
|
|
}
|
|
} else {
|
|
self = NewString("(*this)->");
|
|
}
|
|
}
|
|
|
|
/* If node is a member template expansion, we don't allow added code */
|
|
if (Getattr(n, "templatetype"))
|
|
flags &= ~(CWRAP_EXTEND);
|
|
|
|
name = Getattr(n, "name");
|
|
parms = CopyParmList(nonvoid_parms(Getattr(n, "parms")));
|
|
|
|
type = NewString(classname);
|
|
if (qualifier) {
|
|
SwigType_push(type, qualifier);
|
|
}
|
|
SwigType_add_pointer(type);
|
|
p = NewParm(type, "self", n);
|
|
Setattr(p, "self", "1");
|
|
Setattr(p, "hidden","1");
|
|
/*
|
|
Disable the 'this' ownership in 'self' to manage inplace
|
|
operations like:
|
|
|
|
A& A::operator+=(int i) { ...; return *this;}
|
|
|
|
Here the 'self' parameter ownership needs to be disabled since
|
|
there could be two objects sharing the same 'this' pointer: the
|
|
input and the result one. And worse, the pointer could be deleted
|
|
in one of the objects (input), leaving the other (output) with
|
|
just a seg. fault to happen.
|
|
|
|
To avoid the previous problem, use
|
|
|
|
%feature("self:disown") *::operator+=;
|
|
%feature("new") *::operator+=;
|
|
|
|
These two lines just transfer the ownership of the 'this' pointer
|
|
from the input to the output wrapping object.
|
|
|
|
This happens in python, but may also happen in other target
|
|
languages.
|
|
*/
|
|
if (GetFlag(n, "feature:self:disown")) {
|
|
Setattr(p, "wrap:disown", "1");
|
|
}
|
|
set_nextSibling(p, parms);
|
|
Delete(type);
|
|
|
|
/* Generate action code for the access */
|
|
if (!(flags & CWRAP_EXTEND)) {
|
|
String *explicit_qualifier = 0;
|
|
String *call = 0;
|
|
String *cres = 0;
|
|
String *explicitcall_name = 0;
|
|
int pure_virtual = !(Cmp(Getattr(n, "storage"), "virtual")) && !(Cmp(Getattr(n, "value"), "0"));
|
|
|
|
/* Call the explicit method rather than allow for a polymorphic call */
|
|
if ((flags & CWRAP_DIRECTOR_TWO_CALLS) || (flags & CWRAP_DIRECTOR_ONE_CALL)) {
|
|
String *access = Getattr(n, "access");
|
|
if (access && (Cmp(access, "protected") == 0)) {
|
|
/* If protected access (can only be if a director method) then call the extra public accessor method (language module must provide this) */
|
|
String *explicit_qualifier_tmp = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), "qname"));
|
|
explicitcall_name = NewStringf("%sSwigPublic", name);
|
|
if (Len(directorScope) > 0)
|
|
explicit_qualifier = NewStringf("SwigDirector_%s_%s", directorScope, explicit_qualifier_tmp);
|
|
else
|
|
explicit_qualifier = NewStringf("SwigDirector_%s", explicit_qualifier_tmp);
|
|
Delete(explicit_qualifier_tmp);
|
|
} else {
|
|
explicit_qualifier = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), "qname"));
|
|
}
|
|
}
|
|
|
|
if (!self && SwigType_isrvalue_reference(Getattr(n, "refqualifier"))) {
|
|
String *memory_header = NewString("<memory>");
|
|
Setfile(memory_header, Getfile(n));
|
|
Setline(memory_header, Getline(n));
|
|
Swig_fragment_emit(memory_header);
|
|
self = NewString("std::move(*this).");
|
|
Delete(memory_header);
|
|
}
|
|
|
|
call = Swig_cmethod_call(explicitcall_name ? explicitcall_name : name, p, self, explicit_qualifier, director_type);
|
|
cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call);
|
|
|
|
if (pure_virtual && is_director && (flags & CWRAP_DIRECTOR_TWO_CALLS)) {
|
|
String *qualifier = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), "qname"));
|
|
Delete(cres);
|
|
cres = NewStringf("Swig::DirectorPureVirtualException::raise(\"%s::%s\");", qualifier, name);
|
|
Delete(qualifier);
|
|
}
|
|
|
|
if (flags & CWRAP_DIRECTOR_TWO_CALLS) {
|
|
/* Create two method calls, one to call the explicit method, the other a normal polymorphic function call */
|
|
String *cres_both_calls = NewStringf("");
|
|
String *call_extra = Swig_cmethod_call(name, p, self, 0, director_type);
|
|
String *cres_extra = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call_extra);
|
|
Printv(cres_both_calls, "if (upcall) {\n", cres, "\n", "} else {", cres_extra, "\n}", NIL);
|
|
Setattr(n, "wrap:action", cres_both_calls);
|
|
Delete(cres_extra);
|
|
Delete(call_extra);
|
|
Delete(cres_both_calls);
|
|
} else {
|
|
Setattr(n, "wrap:action", cres);
|
|
}
|
|
|
|
Delete(explicitcall_name);
|
|
Delete(call);
|
|
Delete(cres);
|
|
Delete(explicit_qualifier);
|
|
} else {
|
|
/* Methods with default arguments are wrapped with additional methods for each default argument,
|
|
* however, only one extra %extend method is generated. */
|
|
|
|
String *defaultargs = Getattr(n, "defaultargs");
|
|
String *code = Getattr(n, "code");
|
|
String *cname = Getattr(n, "extendsmartclassname") ? Getattr(n, "extendsmartclassname") : classname;
|
|
String *membername = Swig_name_member(nspace, cname, name);
|
|
String *mangled = Swig_name_mangle(membername);
|
|
int is_smart_pointer = flags & CWRAP_SMART_POINTER;
|
|
|
|
type = Getattr(n, "type");
|
|
|
|
/* Check if the method is overloaded. If so, and it has code attached, we append an extra suffix
|
|
to avoid a name-clash in the generated wrappers. This allows overloaded methods to be defined
|
|
in C. */
|
|
if (Getattr(n, "sym:overloaded") && code) {
|
|
Append(mangled, Getattr(defaultargs ? defaultargs : n, "sym:overname"));
|
|
}
|
|
|
|
/* See if there is any code that we need to emit */
|
|
if (!defaultargs && code && !is_smart_pointer) {
|
|
Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus, "self");
|
|
}
|
|
if (is_smart_pointer) {
|
|
int i = 0;
|
|
Parm *pp = p;
|
|
String *func = NewStringf("%s(", mangled);
|
|
String *cres;
|
|
|
|
if (!Swig_storage_isstatic(n)) {
|
|
String *pname = Swig_cparm_name(pp, i);
|
|
String *ctname = SwigType_namestr(cname);
|
|
String *fadd = 0;
|
|
if (is_smart_pointer_overload) {
|
|
String *nclassname = SwigType_namestr(classname);
|
|
fadd = NewStringf("(%s const *)((%s const *)%s)->operator ->()", ctname, nclassname, pname);
|
|
Delete(nclassname);
|
|
}
|
|
else {
|
|
fadd = NewStringf("(%s*)(%s)->operator ->()", ctname, pname);
|
|
}
|
|
Append(func, fadd);
|
|
Delete(ctname);
|
|
Delete(fadd);
|
|
Delete(pname);
|
|
pp = nextSibling(pp);
|
|
if (pp)
|
|
Append(func, ",");
|
|
} else {
|
|
pp = nextSibling(pp);
|
|
}
|
|
++i;
|
|
while (pp) {
|
|
SwigType *pt = Getattr(pp, "type");
|
|
if ((SwigType_type(pt) != T_VOID)) {
|
|
String *pname = Swig_cparm_name(pp, i++);
|
|
String *rcaststr = SwigType_rcaststr(pt, pname);
|
|
Append(func, rcaststr);
|
|
Delete(rcaststr);
|
|
Delete(pname);
|
|
pp = nextSibling(pp);
|
|
if (pp)
|
|
Append(func, ",");
|
|
}
|
|
}
|
|
Append(func, ")");
|
|
cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), func);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(cres);
|
|
} else {
|
|
String *call = Swig_cfunction_call(mangled, p);
|
|
String *cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(call);
|
|
Delete(cres);
|
|
}
|
|
|
|
Delete(membername);
|
|
Delete(mangled);
|
|
}
|
|
Setattr(n, "parms", p);
|
|
Delete(p);
|
|
Delete(self);
|
|
Delete(parms);
|
|
Delete(directorScope);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_methodclass()
|
|
*
|
|
* This function returns the class node for a given method or class.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
Node *Swig_methodclass(Node *n) {
|
|
Node *nodetype = nodeType(n);
|
|
if (Cmp(nodetype, "class") == 0)
|
|
return n;
|
|
return GetFlag(n, "feature:extend") ? parentNode(parentNode(n)) : parentNode(n);
|
|
}
|
|
|
|
int Swig_directorclass(Node *n) {
|
|
Node *classNode = Swig_methodclass(n);
|
|
assert(classNode != 0);
|
|
return (Getattr(classNode, "vtable") != 0);
|
|
}
|
|
|
|
Node *Swig_directormap(Node *module, String *type) {
|
|
int is_void = !Cmp(type, "void");
|
|
if (!is_void && module) {
|
|
/* ?? follow the inheritance hierarchy? */
|
|
|
|
String *base = SwigType_base(type);
|
|
|
|
Node *directormap = Getattr(module, "wrap:directormap");
|
|
if (directormap)
|
|
return Getattr(directormap, base);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_ConstructorToFunction()
|
|
*
|
|
* This function creates a C wrapper for a C constructor function.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
int Swig_ConstructorToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, String *none_comparison, String *director_ctor, int cplus, int flags, String *directorname) {
|
|
Parm *p;
|
|
ParmList *directorparms;
|
|
SwigType *type;
|
|
int use_director = Swig_directorclass(n);
|
|
ParmList *parms = CopyParmList(nonvoid_parms(Getattr(n, "parms")));
|
|
/* Prepend the list of prefix_args (if any) */
|
|
Parm *prefix_args = Getattr(n, "director:prefix_args");
|
|
if (prefix_args != NIL) {
|
|
Parm *p2, *p3;
|
|
|
|
directorparms = CopyParmList(prefix_args);
|
|
for (p = directorparms; nextSibling(p); p = nextSibling(p));
|
|
for (p2 = parms; p2; p2 = nextSibling(p2)) {
|
|
p3 = CopyParm(p2);
|
|
set_nextSibling(p, p3);
|
|
Delete(p3);
|
|
p = p3;
|
|
}
|
|
} else
|
|
directorparms = parms;
|
|
|
|
type = NewString(classname);
|
|
SwigType_add_pointer(type);
|
|
|
|
if (flags & CWRAP_EXTEND) {
|
|
/* Constructors with default arguments are wrapped with additional constructor methods for each default argument,
|
|
* however, only one extra %extend method is generated. */
|
|
String *call;
|
|
String *cres;
|
|
String *defaultargs = Getattr(n, "defaultargs");
|
|
String *code = Getattr(n, "code");
|
|
String *membername = Swig_name_construct(nspace, classname);
|
|
String *mangled = Swig_name_mangle(membername);
|
|
|
|
/* Check if the constructor is overloaded. If so, and it has code attached, we append an extra suffix
|
|
to avoid a name-clash in the generated wrappers. This allows overloaded constructors to be defined
|
|
in C. */
|
|
if (Getattr(n, "sym:overloaded") && code) {
|
|
Append(mangled, Getattr(defaultargs ? defaultargs : n, "sym:overname"));
|
|
}
|
|
|
|
/* See if there is any code that we need to emit */
|
|
if (!defaultargs && code) {
|
|
Swig_add_extension_code(n, mangled, parms, type, code, cparse_cplusplus, "self");
|
|
}
|
|
|
|
call = Swig_cfunction_call(mangled, parms);
|
|
cres = Swig_cresult(type, Swig_cresult_name(), call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(cres);
|
|
Delete(call);
|
|
Delete(membername);
|
|
Delete(mangled);
|
|
} else {
|
|
if (cplus) {
|
|
/* if a C++ director class exists, create it rather than the original class */
|
|
if (use_director) {
|
|
Node *parent = Swig_methodclass(n);
|
|
int abstract = Getattr(parent, "abstracts") != 0;
|
|
String *action = NewStringEmpty();
|
|
String *tmp_none_comparison = Copy(none_comparison);
|
|
String *director_call;
|
|
String *nodirector_call;
|
|
|
|
Replaceall(tmp_none_comparison, "$arg", "arg1");
|
|
|
|
director_call = Swig_cppconstructor_director_call(directorname, directorparms);
|
|
nodirector_call = Swig_cppconstructor_nodirector_call(classname, parms);
|
|
|
|
if (abstract) {
|
|
/* whether or not the abstract class has been subclassed in python,
|
|
* create a director instance (there's no way to create a normal
|
|
* instance). if any of the pure virtual methods haven't been
|
|
* implemented in the target language, calls to those methods will
|
|
* generate Swig::DirectorPureVirtualException exceptions.
|
|
*/
|
|
String *cres = Swig_cresult(type, Swig_cresult_name(), director_call);
|
|
Append(action, cres);
|
|
Delete(cres);
|
|
} else {
|
|
/* (scottm): The code for creating a new director is now a string
|
|
template that gets passed in via the director_ctor argument.
|
|
|
|
$comparison : an 'if' comparison from none_comparison
|
|
$director_new: Call new for director class
|
|
$nondirector_new: Call new for non-director class
|
|
*/
|
|
String *cres;
|
|
Append(action, director_ctor);
|
|
Replaceall(action, "$comparison", tmp_none_comparison);
|
|
|
|
cres = Swig_cresult(type, Swig_cresult_name(), director_call);
|
|
Replaceall(action, "$director_new", cres);
|
|
Delete(cres);
|
|
|
|
cres = Swig_cresult(type, Swig_cresult_name(), nodirector_call);
|
|
Replaceall(action, "$nondirector_new", cres);
|
|
Delete(cres);
|
|
}
|
|
Setattr(n, "wrap:action", action);
|
|
Delete(tmp_none_comparison);
|
|
Delete(action);
|
|
} else {
|
|
String *call = Swig_cppconstructor_call(classname, parms);
|
|
String *cres = Swig_cresult(type, Swig_cresult_name(), call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(cres);
|
|
Delete(call);
|
|
}
|
|
} else {
|
|
String *call = Swig_cconstructor_call(classname);
|
|
String *cres = Swig_cresult(type, Swig_cresult_name(), call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(cres);
|
|
Delete(call);
|
|
}
|
|
}
|
|
Setattr(n, "type", type);
|
|
Setattr(n, "parms", parms);
|
|
Delete(type);
|
|
if (directorparms != parms)
|
|
Delete(directorparms);
|
|
Delete(parms);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_DestructorToFunction()
|
|
*
|
|
* This function creates a C wrapper for a destructor function.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
int Swig_DestructorToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int cplus, int flags) {
|
|
SwigType *type;
|
|
Parm *p;
|
|
|
|
type = NewString(classname);
|
|
SwigType_add_pointer(type);
|
|
p = NewParm(type, "self", n);
|
|
Setattr(p, "self", "1");
|
|
Setattr(p, "hidden", "1");
|
|
Setattr(p, "wrap:disown", "1");
|
|
Delete(type);
|
|
type = NewString("void");
|
|
|
|
if (flags & CWRAP_EXTEND) {
|
|
String *cres;
|
|
String *call;
|
|
String *membername, *mangled, *code;
|
|
membername = Swig_name_destroy(nspace, classname);
|
|
mangled = Swig_name_mangle(membername);
|
|
code = Getattr(n, "code");
|
|
if (code) {
|
|
Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus, "self");
|
|
}
|
|
call = Swig_cfunction_call(mangled, p);
|
|
cres = NewStringf("%s;", call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(membername);
|
|
Delete(mangled);
|
|
Delete(call);
|
|
Delete(cres);
|
|
} else {
|
|
if (cplus) {
|
|
String *call = Swig_cppdestructor_call(n);
|
|
String *cres = NewStringf("%s", call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(call);
|
|
Delete(cres);
|
|
} else {
|
|
String *call = Swig_cdestructor_call(n);
|
|
String *cres = NewStringf("%s", call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(call);
|
|
Delete(cres);
|
|
}
|
|
}
|
|
Setattr(n, "type", type);
|
|
Setattr(n, "parms", p);
|
|
Delete(type);
|
|
Delete(p);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_MembersetToFunction()
|
|
*
|
|
* This function creates a C wrapper for setting a structure member.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
int Swig_MembersetToFunction(Node *n, String *classname, int flags) {
|
|
String *name;
|
|
ParmList *parms;
|
|
Parm *p;
|
|
SwigType *t;
|
|
SwigType *ty;
|
|
SwigType *type;
|
|
SwigType *void_type = NewString("void");
|
|
String *self = 0;
|
|
|
|
int varcref = flags & CWRAP_NATURAL_VAR;
|
|
|
|
if (flags & CWRAP_SMART_POINTER) {
|
|
self = NewString("(*this)->");
|
|
}
|
|
if (flags & CWRAP_ALL_PROTECTED_ACCESS) {
|
|
self = NewStringf("darg->");
|
|
}
|
|
|
|
name = Getattr(n, "name");
|
|
type = Getattr(n, "type");
|
|
|
|
t = NewString(classname);
|
|
SwigType_add_pointer(t);
|
|
parms = NewParm(t, "self", n);
|
|
Setattr(parms, "self", "1");
|
|
Setattr(parms, "hidden","1");
|
|
Delete(t);
|
|
|
|
ty = Swig_wrapped_member_var_type(type, varcref);
|
|
p = NewParm(ty, name, n);
|
|
Setattr(parms, "hidden", "1");
|
|
set_nextSibling(parms, p);
|
|
|
|
/* If the type is a pointer or reference. We mark it with a special wrap:disown attribute */
|
|
if (SwigType_check_decl(type, "p.")) {
|
|
Setattr(p, "wrap:disown", "1");
|
|
}
|
|
Delete(p);
|
|
|
|
if (flags & CWRAP_EXTEND) {
|
|
String *call;
|
|
String *cres;
|
|
String *code = Getattr(n, "code");
|
|
|
|
String *sname = Swig_name_set(0, name);
|
|
String *membername = Swig_name_member(0, classname, sname);
|
|
String *mangled = Swig_name_mangle(membername);
|
|
|
|
if (code) {
|
|
/* I don't think this ever gets run - WSF */
|
|
Swig_add_extension_code(n, mangled, parms, void_type, code, cparse_cplusplus, "self");
|
|
}
|
|
call = Swig_cfunction_call(mangled, parms);
|
|
cres = NewStringf("%s;", call);
|
|
Setattr(n, "wrap:action", cres);
|
|
|
|
Delete(cres);
|
|
Delete(call);
|
|
Delete(mangled);
|
|
Delete(membername);
|
|
Delete(sname);
|
|
} else {
|
|
String *call = Swig_cmemberset_call(name, type, self, varcref);
|
|
String *cres = NewStringf("%s;", call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(call);
|
|
Delete(cres);
|
|
}
|
|
Setattr(n, "type", void_type);
|
|
Setattr(n, "parms", parms);
|
|
Delete(parms);
|
|
Delete(ty);
|
|
Delete(void_type);
|
|
Delete(self);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_MembergetToFunction()
|
|
*
|
|
* This function creates a C wrapper for getting a structure member.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
int Swig_MembergetToFunction(Node *n, String *classname, int flags) {
|
|
String *name;
|
|
ParmList *parms;
|
|
SwigType *t;
|
|
SwigType *ty;
|
|
SwigType *type;
|
|
String *self = 0;
|
|
|
|
int varcref = flags & CWRAP_NATURAL_VAR;
|
|
|
|
if (flags & CWRAP_SMART_POINTER) {
|
|
if (Swig_storage_isstatic(n)) {
|
|
Node *sn = Getattr(n, "cplus:staticbase");
|
|
String *base = Getattr(sn, "name");
|
|
self = NewStringf("%s::", base);
|
|
} else if (flags & CWRAP_SMART_POINTER_OVERLOAD) {
|
|
String *nclassname = SwigType_namestr(classname);
|
|
self = NewStringf("(*(%s const *)this)->", nclassname);
|
|
Delete(nclassname);
|
|
} else {
|
|
self = NewString("(*this)->");
|
|
}
|
|
}
|
|
if (flags & CWRAP_ALL_PROTECTED_ACCESS) {
|
|
self = NewStringf("darg->");
|
|
}
|
|
|
|
name = Getattr(n, "name");
|
|
type = Getattr(n, "type");
|
|
|
|
t = NewString(classname);
|
|
SwigType_add_pointer(t);
|
|
parms = NewParm(t, "self", n);
|
|
Setattr(parms, "self", "1");
|
|
Setattr(parms, "hidden","1");
|
|
Delete(t);
|
|
|
|
ty = Swig_wrapped_member_var_type(type, varcref);
|
|
if (flags & CWRAP_EXTEND) {
|
|
String *call;
|
|
String *cres;
|
|
String *code = Getattr(n, "code");
|
|
|
|
String *gname = Swig_name_get(0, name);
|
|
String *membername = Swig_name_member(0, classname, gname);
|
|
String *mangled = Swig_name_mangle(membername);
|
|
|
|
if (code) {
|
|
/* I don't think this ever gets run - WSF */
|
|
Swig_add_extension_code(n, mangled, parms, ty, code, cparse_cplusplus, "self");
|
|
}
|
|
call = Swig_cfunction_call(mangled, parms);
|
|
cres = Swig_cresult(ty, Swig_cresult_name(), call);
|
|
Setattr(n, "wrap:action", cres);
|
|
|
|
Delete(cres);
|
|
Delete(call);
|
|
Delete(mangled);
|
|
Delete(membername);
|
|
Delete(gname);
|
|
} else {
|
|
String *call = Swig_cmemberget_call(name, type, self, varcref);
|
|
String *cres = Swig_cresult(ty, Swig_cresult_name(), call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(call);
|
|
Delete(cres);
|
|
}
|
|
Setattr(n, "type", ty);
|
|
Setattr(n, "parms", parms);
|
|
Delete(parms);
|
|
Delete(ty);
|
|
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_VarsetToFunction()
|
|
*
|
|
* This function creates a C wrapper for setting a global variable or static member
|
|
* variable.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
int Swig_VarsetToFunction(Node *n, int flags) {
|
|
String *name, *nname;
|
|
ParmList *parms;
|
|
SwigType *type, *ty;
|
|
|
|
int varcref = flags & CWRAP_NATURAL_VAR;
|
|
|
|
name = Getattr(n, "name");
|
|
type = Getattr(n, "type");
|
|
nname = SwigType_namestr(name);
|
|
ty = Swig_wrapped_var_type(type, varcref);
|
|
parms = NewParm(ty, name, n);
|
|
|
|
if (flags & CWRAP_EXTEND) {
|
|
String *sname = Swig_name_set(0, name);
|
|
String *mangled = Swig_name_mangle(sname);
|
|
String *call = Swig_cfunction_call(mangled, parms);
|
|
String *cres = NewStringf("%s;", call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(cres);
|
|
Delete(call);
|
|
Delete(mangled);
|
|
Delete(sname);
|
|
} else {
|
|
if (!Strstr(type, "enum $unnamed")) {
|
|
String *pname = Swig_cparm_name(0, 0);
|
|
String *dref = Swig_wrapped_var_deref(type, pname, varcref);
|
|
String *call = NewStringf("%s = %s;", nname, dref);
|
|
Setattr(n, "wrap:action", call);
|
|
Delete(call);
|
|
Delete(dref);
|
|
Delete(pname);
|
|
} else {
|
|
String *pname = Swig_cparm_name(0, 0);
|
|
String *call = NewStringf("if (sizeof(int) == sizeof(%s)) *(int*)(void*)&(%s) = %s;", nname, nname, pname);
|
|
Setattr(n, "wrap:action", call);
|
|
Delete(pname);
|
|
Delete(call);
|
|
}
|
|
}
|
|
Setattr(n, "type", "void");
|
|
Setattr(n, "parms", parms);
|
|
Delete(parms);
|
|
Delete(ty);
|
|
Delete(nname);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_VargetToFunction()
|
|
*
|
|
* This function creates a C wrapper for getting a global variable or static member
|
|
* variable.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
int Swig_VargetToFunction(Node *n, int flags) {
|
|
String *cres, *call;
|
|
String *name;
|
|
SwigType *type;
|
|
SwigType *ty = 0;
|
|
|
|
int varcref = flags & CWRAP_NATURAL_VAR;
|
|
|
|
name = Getattr(n, "name");
|
|
type = Getattr(n, "type");
|
|
ty = Swig_wrapped_var_type(type, varcref);
|
|
|
|
if (flags & CWRAP_EXTEND) {
|
|
String *sname = Swig_name_get(0, name);
|
|
String *mangled = Swig_name_mangle(sname);
|
|
call = Swig_cfunction_call(mangled, 0);
|
|
cres = Swig_cresult(ty, Swig_cresult_name(), call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(mangled);
|
|
Delete(sname);
|
|
} else {
|
|
String *nname = 0;
|
|
if (Equal(nodeType(n), "constant")) {
|
|
String *rawval = Getattr(n, "rawval");
|
|
String *value = rawval ? rawval : Getattr(n, "value");
|
|
nname = NewStringf("(%s)", value);
|
|
} else {
|
|
nname = SwigType_namestr(name);
|
|
}
|
|
call = Swig_wrapped_var_assign(type, nname, varcref);
|
|
cres = Swig_cresult(ty, Swig_cresult_name(), call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Delete(nname);
|
|
}
|
|
|
|
Setattr(n, "type", ty);
|
|
Delattr(n, "parms");
|
|
Delete(cres);
|
|
Delete(call);
|
|
Delete(ty);
|
|
return SWIG_OK;
|
|
}
|