Refactor the c module; initial split of wrapper/proxy

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2012-c@13164 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Leif Middelschulte 2012-06-12 00:31:09 +00:00
commit a351c3441c

View file

@ -12,6 +12,22 @@ char cvsroot_c_cxx[] = "$Id: c.cxx 11186 2009-04-11 10:46:13Z maciekd $";
#include <ctype.h> #include <ctype.h>
#include "swigmod.h" #include "swigmod.h"
#ifdef IS_SET_TO_ONE
#undef IS_SET_TO_ONE
#endif
#define IS_SET_TO_ONE(n, var) \
(Cmp(Getattr(n, var), "1") == 0)
#ifdef IS_SET
#undef IS_SET
#endif
#define IS_SET(n, var) \
(Getattr(n, var))
#ifdef IS_EQUAL
#undef IS_EQUAL
#endif
#define IS_EQUAL(val1, val2) \
(Cmp(val1, val2) == 0)
int SwigType_isbuiltin(SwigType *t) { int SwigType_isbuiltin(SwigType *t) {
const char* builtins[] = { "void", "short", "int", "long", "char", "float", "double", "bool", 0 }; const char* builtins[] = { "void", "short", "int", "long", "char", "float", "double", "bool", 0 };
int i = 0; int i = 0;
@ -401,37 +417,49 @@ ready:
return result; return result;
} }
/* ---------------------------------------------------------------------- virtual void printProxy(Node *n, SwigType *return_type, String *wname, String *name, String *proto, String *arg_names)
* functionWrapper() {
* ---------------------------------------------------------------------- */
virtual int functionWrapper(Node *n) {
String *name = Copy(Getattr(n, "sym:name"));
String *storage = Getattr(n, "storage");
String *vis_hint = NewString(""); String *vis_hint = NewString("");
// use proxy-type for return type if supplied
SwigType *proxy_type = Getattr(n, "c:stype");
if (proxy_type) {
return_type = SwigType_str(proxy_type, 0);
}
// emit proxy functions prototypes
Printv(f_proxy_code_init, return_type, " ", wname, "(", proto, ");\n", NIL);
Printv(f_proxy_code_body, return_type, " ", name, "(", proto, ") {\n", NIL);
// call to the wrapper function
Printv(f_proxy_code_body, " return ", wname, "(", arg_names, ");\n}\n", NIL);
// add function declaration to the proxy header file
// add visibility hint for the compiler (do not override this symbol)
Printv(vis_hint, "SWIGPROTECT(", return_type, " ", name, "(", proto, ");)\n\n", NIL);
Printv(f_proxy_header, vis_hint, NIL);
Delete(vis_hint);
}
virtual void functionWrapperCSpecific(Node *n)
{
// this is C function, we don't apply typemaps to it
String *name = Copy(Getattr(n, "sym:name"));
SwigType *type = Getattr(n, "type"); SwigType *type = Getattr(n, "type");
SwigType *otype = Copy(type); SwigType *return_type = NULL;
SwigType *return_type = NewString(""); String *wname = Swig_name_wrapper(name);
String *wname; String *arg_names = NULL;
String *arg_names = NewString("");
ParmList *parms = Getattr(n, "parms"); ParmList *parms = Getattr(n, "parms");
Parm *p; Parm *p;
String *tm;
String *proto = NewString(""); String *proto = NewString("");
String *over_suffix = NewString(""); int gencomma = 0;
int gencomma;
bool is_global = Cmp(Getattr(n, "c:globalfun"), "1") == 0; // possibly no longer neede
bool is_void_return = (SwigType_type(type) == T_VOID); bool is_void_return = (SwigType_type(type) == T_VOID);
bool return_object = false;
// create new function wrapper object // create new function wrapper object
Wrapper *wrapper = NewWrapper(); Wrapper *wrapper = NewWrapper();
if (!CPlusPlus) {
// this is C function, we don't apply typemaps to it
// create new wrapper name // create new wrapper name
wname = Swig_name_wrapper(name);
Setattr(n, "wrap:name", wname); Setattr(n, "wrap:name", wname);
// create function call // create function call
@ -443,8 +471,7 @@ ready:
return_type = SwigType_str(type, 0); return_type = SwigType_str(type, 0);
// emit wrapper prototype and code // emit wrapper prototype and code
gencomma = 0; for (p = parms, gencomma = 0; p; p = nextSibling(p)) {
for (p = parms; p; p = nextSibling(p)) {
Printv(proto, gencomma ? ", " : "", SwigType_str(Getattr(p, "type"), 0), " ", Getattr(p, "lname"), NIL); Printv(proto, gencomma ? ", " : "", SwigType_str(Getattr(p, "type"), 0), " ", Getattr(p, "lname"), NIL);
gencomma = 1; gencomma = 1;
} }
@ -455,6 +482,7 @@ ready:
// insert constraint checking // insert constraint checking
for (p = parms; p; ) { for (p = parms; p; ) {
String *tm;
if ((tm = Getattr(p, "tmap:check"))) { if ((tm = Getattr(p, "tmap:check"))) {
Replaceall(tm, "$target", Getattr(p, "lname")); Replaceall(tm, "$target", Getattr(p, "lname"));
Replaceall(tm, "$name", name); Replaceall(tm, "$name", name);
@ -476,75 +504,182 @@ ready:
if (!is_void_return) if (!is_void_return)
Printf(wrapper->code, "return result;\n"); Printf(wrapper->code, "return result;\n");
Printf(wrapper->code, "}"); Printf(wrapper->code, "}");
}
else {
// C++ function wrapper
// mark the first parameter as object-struct if (proxy_flag) // take care of proxy function
if (!is_global && storage && Cmp(storage, "static") != 0) { printProxy(n, return_type, wname, name, proto, arg_names);
if ((Cmp(Getattr(n, "ismember"), "1") == 0) &&
(Cmp(nodeType(n), "constructor") != 0)) { Wrapper_print(wrapper, f_wrappers);
Setattr(parms, "c:objstruct", "1");
if (!Getattr(parms, "lname")) // cleanup
Setattr(parms, "lname", "arg1"); Delete(proto);
SwigType *stype = Copy(Getattr(Swig_methodclass(n), "sym:name")); Delete(arg_names);
SwigType_add_pointer(stype); Delete(wname);
Setattr(parms, "c:stype", stype); Delete(return_type);
Delete(name);
DelWrapper(wrapper);
}
static void functionWrapperPrepareArgs(const ParmList *parms)
{
Parm *p;
int index = 1;
String *lname = 0;
for (p = (Parm*)parms, index = 1; p; (p = nextSibling(p)), index++) {
if(!(lname = Getattr(p, "lname"))) {
lname = NewStringf("arg%d", index);
Setattr(p, "lname", lname);
}
} }
} }
// mangle name if function is overloaded virtual void functionWrapperAppendOverloaded(String *name, const ParmList *parms)
if (Getattr(n, "sym:overloaded")) { {
if (!Getattr(n, "copy_constructor")) { String *over_suffix = NewString("");
for (p = parms; p; p = nextSibling(p)) { Parm *p;
if (Getattr(p, "c:objstruct")) String *mangled;
for (p = (Parm*)parms; p; p = nextSibling(p)) {
if (IS_SET(p, "c:objstruct"))
continue; continue;
String *mangled = get_mangled_type(Getattr(p, "type")); mangled = get_mangled_type(Getattr(p, "type"));
Printv(over_suffix, "_", mangled, NIL); Printv(over_suffix, "_", mangled, NIL);
} }
Append(name, over_suffix); Append(name, over_suffix);
Delete(over_suffix);
} }
static void functionWrapperAddCPPResult(Wrapper *wrapper, const SwigType *type, const String *tm)
{
SwigType *cpptype;
SwigType *tdtype = SwigType_typedef_resolve_all(tm);
if (tdtype)
cpptype = tdtype;
else
cpptype = (SwigType*)tm;
if (SwigType_ismemberpointer(type))
Wrapper_add_local(wrapper, "cppresult", SwigType_str(type, "cppresult"));
else
Wrapper_add_local(wrapper, "cppresult", SwigType_str(cpptype, "cppresult"));
} }
virtual void functionWrapperCPPSpecificProxy(Node *n, String *name)
{
// C++ function wrapper proxy code
SwigType *return_type = Getattr(n, "return_type");
String *pname = Swig_name_wrapper(name);
String *arg_names = NewString("");
ParmList *parms = Getattr(n, "parms");
Parm *p;
String *proto = NewString("");
int gencomma = 0;
// attach the standard typemaps
Swig_typemap_attach_parms("in", parms, 0);
// attach 'ctype' typemaps
Swig_typemap_attach_parms("ctype", parms, 0);
// prepare function definition
for (p = parms, gencomma = 0; p; ) {
String *tm;
while (p && checkAttribute(p, "tmap:in:numinputs", "0")) {
p = Getattr(p, "tmap:in:next");
}
if (!p) break;
SwigType *type = Getattr(p, "type");
if (SwigType_type(type) == T_VOID) {
p = nextSibling(p);
continue;
}
String *lname = Getattr(p, "lname");
String *c_parm_type = NewString("");
String *proxy_parm_type = NewString("");
String *arg_name = NewString("");
SwigType *tdtype = SwigType_typedef_resolve_all(type); SwigType *tdtype = SwigType_typedef_resolve_all(type);
if (tdtype) if (tdtype)
type = tdtype; type = tdtype;
Setattr(n, "type", type); Printf(arg_name, "c%s", lname);
// create new wrapper name // set the appropriate type for parameter
wname = Swig_name_wrapper(name); if ((tm = Getattr(p, "tmap:ctype"))) {
Setattr(n, "wrap:name", wname); Printv(c_parm_type, tm, NIL);
// set the return type
if (Cmp(Getattr(n, "c:objstruct"), "1") == 0) {
Printv(return_type, SwigType_str(type, 0), NIL);
}
else if ((tm = Swig_typemap_lookup("couttype", n, "", 0))) {
String *ctypeout = Getattr(n, "tmap:couttype:out");
if (ctypeout)
tm = ctypeout;
Printf(return_type, "%s", tm);
// template handling // template handling
Replaceall(return_type, "$tt", SwigType_lstr(type, 0)); Replaceall(c_parm_type, "$tt", SwigType_lstr(type, 0));
} }
else { else {
Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No couttype typemap defined for %s\n", SwigType_str(type, 0)); Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(type, 0));
} }
// use proxy-type for parameter if supplied
String* stype = Getattr(p, "c:stype");
if (stype) {
Printv(proxy_parm_type, SwigType_str(stype, 0), NIL);
}
else {
Printv(proxy_parm_type, c_parm_type, NIL);
}
Printv(arg_names, gencomma ? ", " : "", arg_name, NIL);
Printv(proto, gencomma ? ", " : "", proxy_parm_type, " ", arg_name, NIL);
gencomma = 1;
// apply typemaps for input parameter
if (IS_EQUAL(nodeType(n), "destructor")) {
p = Getattr(p, "tmap:in:next");
}
else if ((tm = Getattr(p, "tmap:in"))) {
Replaceall(tm, "$input", arg_name);
p = Getattr(p, "tmap:in:next");
}
else {
Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(type, 0));
p = nextSibling(p);
}
Delete(arg_name);
Delete(proxy_parm_type);
Delete(c_parm_type);
}
printProxy(n, return_type, pname, name, proto, arg_names);
// cleanup
Delete(proto);
Delete(arg_names);
Delete(pname);
}
virtual void functionWrapperCPPSpecificWrapper(Node *n, String *name)
{
// C++ function wrapper
String *storage = Getattr(n, "storage");
SwigType *type = Getattr(n, "type");
SwigType *otype = Copy(type);
SwigType *return_type = Getattr(n, "return_type");
String *wname = Swig_name_wrapper(name);
String *arg_names = NewString("");
ParmList *parms = Getattr(n, "parms");
Parm *p;
int gencomma = 0;
bool is_void_return = (SwigType_type(type) == T_VOID);
bool return_object = false;
// create new function wrapper object
Wrapper *wrapper = NewWrapper();
// create new wrapper name
Setattr(n, "wrap:name", wname);
// add variable for holding result of original function 'cppresult' // add variable for holding result of original function 'cppresult'
// WARNING: testing typemap approach // WARNING: testing typemap approach
SwigType *cpptype; if (!is_void_return && !IS_SET_TO_ONE(n, "c:objstruct")) {
if (!is_void_return && (Cmp(Getattr(n, "c:objstruct"), "1") != 0)) { String *tm;
if ((tm = Swig_typemap_lookup("cppouttype", n, "", 0))) { if ((tm = Swig_typemap_lookup("cppouttype", n, "", 0))) {
SwigType *tdtype = SwigType_typedef_resolve_all(tm); functionWrapperAddCPPResult(wrapper, type, tm);
if (tdtype)
cpptype = tdtype;
else
cpptype = tm;
if (SwigType_ismemberpointer(type))
Wrapper_add_local(wrapper, "cppresult", SwigType_str(type, "cppresult"));
Wrapper_add_local(wrapper, "cppresult", SwigType_str(cpptype, "cppresult"));
return_object = checkAttribute(n, "tmap:cppouttype:retobj", "1"); return_object = checkAttribute(n, "tmap:cppouttype:retobj", "1");
} }
else { else {
@ -552,17 +687,6 @@ ready:
} }
} }
// make sure lnames are set
int index = 1;
for (p = parms; p; p = nextSibling(p)) {
String *lname = Getattr(p, "lname");
if (!lname) {
lname = NewStringf("arg%d", index);
Setattr(p, "lname", lname);
}
index++;
}
// create wrapper function prototype // create wrapper function prototype
Printv(wrapper->def, "SWIGEXPORTC ", return_type, " ", wname, "(", NIL); Printv(wrapper->def, "SWIGEXPORTC ", return_type, " ", wname, "(", NIL);
@ -574,8 +698,8 @@ ready:
Swig_typemap_attach_parms("ctype", parms, wrapper); Swig_typemap_attach_parms("ctype", parms, wrapper);
// prepare function definition // prepare function definition
gencomma = 0; for (p = parms, gencomma = 0; p; ) {
for (p = parms; p; ) { String *tm;
while (p && checkAttribute(p, "tmap:in:numinputs", "0")) { while (p && checkAttribute(p, "tmap:in:numinputs", "0")) {
p = Getattr(p, "tmap:in:next"); p = Getattr(p, "tmap:in:next");
@ -619,11 +743,10 @@ ready:
Printv(arg_names, gencomma ? ", " : "", arg_name, NIL); Printv(arg_names, gencomma ? ", " : "", arg_name, NIL);
Printv(wrapper->def, gencomma ? ", " : "", c_parm_type, " ", arg_name, NIL); Printv(wrapper->def, gencomma ? ", " : "", c_parm_type, " ", arg_name, NIL);
Printv(proto, gencomma ? ", " : "", proxy_parm_type, " ", arg_name, NIL);
gencomma = 1; gencomma = 1;
// apply typemaps for input parameter // apply typemaps for input parameter
if (Cmp(nodeType(n), "destructor") == 0) { if (IS_EQUAL(nodeType(n), "destructor")) {
p = Getattr(p, "tmap:in:next"); p = Getattr(p, "tmap:in:next");
} }
else if ((tm = Getattr(p, "tmap:in"))) { else if ((tm = Getattr(p, "tmap:in"))) {
@ -644,7 +767,7 @@ ready:
Printf(wrapper->def, ") {"); Printf(wrapper->def, ") {");
if (Cmp(nodeType(n), "destructor") != 0) { if (!IS_EQUAL(nodeType(n), "destructor")) {
// emit variables for holding parameters // emit variables for holding parameters
emit_parameter_variables(parms, wrapper); emit_parameter_variables(parms, wrapper);
@ -654,6 +777,7 @@ ready:
// insert constraint checking // insert constraint checking
for (p = parms; p; ) { for (p = parms; p; ) {
String *tm;
if ((tm = Getattr(p, "tmap:check"))) { if ((tm = Getattr(p, "tmap:check"))) {
Replaceall(tm, "$target", Getattr(p, "lname")); Replaceall(tm, "$target", Getattr(p, "lname"));
Replaceall(tm, "$name", name); Replaceall(tm, "$name", name);
@ -677,18 +801,18 @@ ready:
} }
// handle special cases of cpp return result // handle special cases of cpp return result
if (Cmp(nodeType(n), "constructor") != 0) { if (!IS_EQUAL(nodeType(n), "constructor")) {
if (SwigType_isenum(SwigType_base(type))){ if (SwigType_isenum(SwigType_base(type))){
if (return_object) if (return_object)
Replaceall(action, "result =", "cppresult = (int)"); Replaceall(action, "result =", "cppresult = (int)");
else Replaceall(action, "result =", "cppresult = (int*)"); else Replaceall(action, "result =", "cppresult = (int*)");
} }
else if (return_object && Getattr(n, "c:retval") && !SwigType_isarray(type) else if (return_object && Getattr(n, "c:retval") && !SwigType_isarray(type)
&& Cmp(Getattr(n, "storage"), "static") != 0) { && !IS_EQUAL(storage, "static")) {
// returning object by value // returning object by value
String *str = SwigType_str(SwigType_add_reference(SwigType_base(type)), "_result_ref"); String *str = SwigType_str(SwigType_add_reference(SwigType_base(type)), "_result_ref");
String *lstr = SwigType_lstr(type, 0); String *lstr = SwigType_lstr(type, 0);
if (Cmp(Getattr(n, "kind"), "variable") == 0) { if (IS_EQUAL(Getattr(n, "kind"), "variable")) {
Delete(action); Delete(action);
action = NewStringf("{const %s = %s;", str, Swig_cmemberget_call(Getattr(n, "name"), type, 0, 0)); action = NewStringf("{const %s = %s;", str, Swig_cmemberget_call(Getattr(n, "name"), type, 0, 0));
} }
@ -711,9 +835,9 @@ ready:
// prepare action code to use, e.g. insert try-catch blocks // prepare action code to use, e.g. insert try-catch blocks
action = emit_action(n); action = emit_action(n);
Setattr(n, "type", type);
// emit output typemap if needed // emit output typemap if needed
if (!is_void_return && (Cmp(Getattr(n, "c:objstruct"), "1") != 0)) { if (!is_void_return && (Cmp(Getattr(n, "c:objstruct"), "1") != 0)) {
String *tm;
if ((tm = Swig_typemap_lookup_out("out", n, "cppresult", wrapper, action))) { if ((tm = Swig_typemap_lookup_out("out", n, "cppresult", wrapper, action))) {
Replaceall(tm, "$result", "result"); Replaceall(tm, "$result", "result");
Printf(wrapper->code, "%s", tm); Printf(wrapper->code, "%s", tm);
@ -736,6 +860,7 @@ ready:
// insert cleanup code // insert cleanup code
for (p = parms; p; ) { for (p = parms; p; ) {
String *tm;
if ((tm = Getattr(p, "tmap:freearg"))) { if ((tm = Getattr(p, "tmap:freearg"))) {
if (tm && (Len(tm) != 0)) { if (tm && (Len(tm) != 0)) {
String *input = NewStringf("c%s", Getattr(p, "lname")); String *input = NewStringf("c%s", Getattr(p, "lname"));
@ -755,42 +880,114 @@ ready:
Append(wrapper->code, "return result;\n"); Append(wrapper->code, "return result;\n");
Append(wrapper->code, "}\n"); Append(wrapper->code, "}\n");
}
// take care of proxy function
if (proxy_flag) {
// use proxy-type for return type if supplied
SwigType *proxy_type = Getattr(n, "c:stype");
if (proxy_type) {
return_type = SwigType_str(proxy_type, 0);
}
// emit proxy functions prototypes
Printv(f_proxy_code_init, return_type, " ", wname, "(", proto, ");\n", NIL);
Printv(f_proxy_code_body, return_type, " ", name, "(", proto, ") {\n", NIL);
// call to the wrapper function
Printv(f_proxy_code_body, " return ", wname, "(", arg_names, ");\n}\n", NIL);
// add function declaration to the proxy header file
// add visibility hint for the compiler (do not override this symbol)
Printv(vis_hint, "SWIGPROTECT(", return_type, " ", name, "(", proto, ");)\n\n", NIL);
Printv(f_proxy_header, vis_hint, NIL);
}
Wrapper_print(wrapper, f_wrappers); Wrapper_print(wrapper, f_wrappers);
// cleanup // cleanup
Delete(vis_hint);
Delete(over_suffix);
Delete(proto);
Delete(arg_names); Delete(arg_names);
Delete(wname); Delete(wname);
Delete(return_type); Delete(return_type);
Delete(otype); Delete(otype);
Delete(name);
DelWrapper(wrapper); DelWrapper(wrapper);
}
virtual void functionWrapperCPPSpecificMarkFirstParam(Node *n)
{
bool is_global = IS_SET_TO_ONE(n, "c:globalfun"); // possibly no longer neede
String *storage = Getattr(n, "storage");
ParmList *parms = Getattr(n, "parms");
// mark the first parameter as object-struct
if (!is_global && storage && !IS_EQUAL(storage, "static")) {
if (IS_SET_TO_ONE(n, "ismember") &&
!IS_EQUAL(nodeType(n), "constructor")) {
Setattr(parms, "c:objstruct", "1");
if (!IS_SET(parms, "lname"))
Setattr(parms, "lname", "arg1");
SwigType *stype = Copy(Getattr(Swig_methodclass(n), "sym:name"));
SwigType_add_pointer(stype);
Setattr(parms, "c:stype", stype);
}
}
}
virtual void functionWrapperCPPSpecificSetReturnType(Node *n)
{
SwigType *type = Getattr(n, "type");
SwigType *return_type = NewString("");
String *tm;
// set the return type
if (IS_SET_TO_ONE(n, "c:objstruct")) {
Printv(return_type, SwigType_str(type, 0), NIL);
}
else if ((tm = Swig_typemap_lookup("couttype", n, "", 0))) {
String *ctypeout = Getattr(n, "tmap:couttype:out");
if (ctypeout)
tm = ctypeout;
Printf(return_type, "%s", tm);
// template handling
Replaceall(return_type, "$tt", SwigType_lstr(type, 0));
}
else {
Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No couttype typemap defined for %s\n", SwigType_str(type, 0));
}
Setattr(n, "return_type", return_type);
}
/*
virtual void functionWrapperCPPSpecific(Node *n)
{
}
*/
virtual void functionWrapperCPPSpecific(Node *n)
{
ParmList *parms = Getattr(n, "parms");
String *name = Copy(Getattr(n, "sym:name"));
SwigType *type = Getattr(n, "type");
SwigType *tdtype = NULL;
functionWrapperCPPSpecificMarkFirstParam(n);
// mangle name if function is overloaded
if (IS_SET(n, "sym:overloaded")) {
if (!IS_SET(n, "copy_constructor")) {
functionWrapperAppendOverloaded(name, parms);
}
}
// resolve correct type
if((tdtype = SwigType_typedef_resolve_all(type)))
Setattr(n, "type", tdtype);
functionWrapperCPPSpecificSetReturnType(n);
// make sure lnames are set
functionWrapperPrepareArgs(parms);
// C++ function wrapper
functionWrapperCPPSpecificWrapper(n, name);
if (proxy_flag) // take care of proxy function
functionWrapperCPPSpecificProxy(n, name);
Delete(name);
}
/* ----------------------------------------------------------------------
* functionWrapper()
* ---------------------------------------------------------------------- */
virtual int functionWrapper(Node *n) {
if (CPlusPlus) {
functionWrapperCPPSpecific(n);
}
else {
functionWrapperCSpecific(n);
}
return SWIG_OK; return SWIG_OK;
} }