diff options
Diffstat (limited to 'Source/Modules/directors.cxx')
| -rw-r--r-- | Source/Modules/directors.cxx | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/Source/Modules/directors.cxx b/Source/Modules/directors.cxx new file mode 100644 index 0000000..158b535 --- /dev/null +++ b/Source/Modules/directors.cxx @@ -0,0 +1,288 @@ +/* ----------------------------------------------------------------------------- + * See the LICENSE file for information on copyright, usage and redistribution + * of SWIG, and the README file for authors - http://www.swig.org/release.html. + * + * directors.cxx + * + * Director support functions. + * Not all of these may be necessary, and some may duplicate existing functionality + * in SWIG. --MR + * ----------------------------------------------------------------------------- */ + +char cvsroot_directors_cxx[] = "$Id"; + +#include "swigmod.h" + +/* Swig_csuperclass_call() + * + * Generates a fully qualified method call, including the full parameter list. + * e.g. "base::method(i, j)" + * + */ + +String *Swig_csuperclass_call(String *base, String *method, ParmList *l) { + String *call = NewString(""); + int arg_idx = 0; + Parm *p; + if (base) { + Printf(call, "%s::", base); + } + Printf(call, "%s(", method); + for (p = l; p; p = nextSibling(p)) { + String *pname = Getattr(p, "name"); + if (!pname && Cmp(Getattr(p, "type"), "void")) { + pname = NewString(""); + Printf(pname, "arg%d", arg_idx++); + } + if (p != l) + Printf(call, ", "); + Printv(call, pname, NIL); + } + Printf(call, ")"); + return call; +} + +/* Swig_class_declaration() + * + * Generate the start of a class/struct declaration. + * e.g. "class myclass" + * + */ + +String *Swig_class_declaration(Node *n, String *name) { + if (!name) { + name = Getattr(n, "sym:name"); + } + String *result = NewString(""); + String *kind = Getattr(n, "kind"); + Printf(result, "%s %s", kind, name); + return result; +} + +String *Swig_class_name(Node *n) { + String *name; + name = Copy(Getattr(n, "sym:name")); + return name; +} + +/* Swig_director_declaration() + * + * Generate the full director class declaration, complete with base classes. + * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {" + * + */ + +String *Swig_director_declaration(Node *n) { + String *classname = Swig_class_name(n); + String *directorname = NewStringf("SwigDirector_%s", classname); + String *base = Getattr(n, "classtype"); + String *declaration = Swig_class_declaration(n, directorname); + Printf(declaration, " : public %s, public Swig::Director {\n", base); + Delete(classname); + Delete(directorname); + return declaration; +} + + +String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms) { + String *func; + int i = 0; + int comma = 0; + Parm *p = parms; + SwigType *pt; + String *nname; + + func = NewString(""); + nname = SwigType_namestr(name); + Printf(func, "%s(", nname); + while (p) { + String *pname; + pt = Getattr(p, "type"); + if ((SwigType_type(pt) != T_VOID)) { + if (comma) + Printf(func, ","); + pname = Getattr(p, "name"); + Printf(func, "%s", pname); + comma = 1; + i++; + } + p = nextSibling(p); + } + Printf(func, ")"); + return func; +} + +/* Swig_method_decl + * + * Misnamed and misappropriated! Taken from SWIG's type string manipulation utilities + * and modified to generate full (or partial) type qualifiers for method declarations, + * local variable declarations, and return value casting. More importantly, it merges + * parameter type information with actual parameter names to produce a complete method + * declaration that fully mirrors the original method declaration. + * + * There is almost certainly a saner way to do this. + * + * This function needs to be cleaned up and possibly split into several smaller + * functions. For instance, attaching default names to parameters should be done in a + * separate function. + * + */ + +String *Swig_method_decl(SwigType *returntype, SwigType *decl, const_String_or_char_ptr id, List *args, int strip, int values) { + String *result; + List *elements; + String *element = 0, *nextelement; + int is_const = 0; + int nelements, i; + int is_func = 0; + int arg_idx = 0; + + if (id) { + result = NewString(Char(id)); + } else { + result = NewString(""); + } + + elements = SwigType_split(decl); + nelements = Len(elements); + if (nelements > 0) { + element = Getitem(elements, 0); + } + for (i = 0; i < nelements; i++) { + if (i < (nelements - 1)) { + nextelement = Getitem(elements, i + 1); + } else { + nextelement = 0; + } + if (SwigType_isqualifier(element)) { + int skip = 0; + DOH *q = 0; + if (!strip) { + q = SwigType_parm(element); + if (!Cmp(q, "const")) { + is_const = 1; + is_func = SwigType_isfunction(nextelement); + if (is_func) + skip = 1; + skip = 1; + } + if (!skip) { + Insert(result, 0, " "); + Insert(result, 0, q); + } + Delete(q); + } + } else if (SwigType_isfunction(element)) { + Parm *parm; + String *p; + Append(result, "("); + parm = args; + while (parm != 0) { + String *type = Getattr(parm, "type"); + String *name = Getattr(parm, "name"); + if (!name && Cmp(type, "void")) { + name = NewString(""); + Printf(name, "arg%d", arg_idx++); + Setattr(parm, "name", name); + } + if (!name) { + name = NewString(""); + } + p = SwigType_str(type, name); + Append(result, p); + String *value = Getattr(parm, "value"); + if (values && (value != 0)) { + Printf(result, " = %s", value); + } + parm = nextSibling(parm); + if (parm != 0) + Append(result, ", "); + } + Append(result, ")"); + } else if (returntype) { // This check is intended for conversion operators to a pointer/reference which needs the pointer/reference ignoring in the declaration + if (SwigType_ispointer(element)) { + Insert(result, 0, "*"); + if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { + Insert(result, 0, "("); + Append(result, ")"); + } + } else if (SwigType_ismemberpointer(element)) { + String *q; + q = SwigType_parm(element); + Insert(result, 0, "::*"); + Insert(result, 0, q); + if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { + Insert(result, 0, "("); + Append(result, ")"); + } + Delete(q); + } else if (SwigType_isreference(element)) { + Insert(result, 0, "&"); + } else if (SwigType_isarray(element)) { + DOH *size; + Append(result, "["); + size = SwigType_parm(element); + Append(result, size); + Append(result, "]"); + Delete(size); + } else { + if (Strcmp(element, "v(...)") == 0) { + Insert(result, 0, "..."); + } else { + String *bs = SwigType_namestr(element); + Insert(result, 0, " "); + Insert(result, 0, bs); + Delete(bs); + } + } + } + element = nextelement; + } + + Delete(elements); + + if (is_const) { + if (is_func) { + Append(result, " "); + Append(result, "const"); + } else { + Insert(result, 0, "const "); + } + } + + Chop(result); + + if (returntype) { + Insert(result, 0, " "); + String *rtype = SwigType_str(returntype, 0); + Insert(result, 0, rtype); + Delete(rtype); + } + + 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); + } +} + |
