/* ----------------------------------------------------------------------------- * 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); } }