1/* ----------------------------------------------------------------------------- 2 * See the LICENSE file for information on copyright, usage and redistribution 3 * of SWIG, and the README file for authors - http://www.swig.org/release.html. 4 * 5 * directors.cxx 6 * 7 * Director support functions. 8 * Not all of these may be necessary, and some may duplicate existing functionality 9 * in SWIG. --MR 10 * ----------------------------------------------------------------------------- */ 11 12char cvsroot_directors_cxx[] = "$Id"; 13 14#include "swigmod.h" 15 16/* Swig_csuperclass_call() 17 * 18 * Generates a fully qualified method call, including the full parameter list. 19 * e.g. "base::method(i, j)" 20 * 21 */ 22 23String *Swig_csuperclass_call(String *base, String *method, ParmList *l) { 24 String *call = NewString(""); 25 int arg_idx = 0; 26 Parm *p; 27 if (base) { 28 Printf(call, "%s::", base); 29 } 30 Printf(call, "%s(", method); 31 for (p = l; p; p = nextSibling(p)) { 32 String *pname = Getattr(p, "name"); 33 if (!pname && Cmp(Getattr(p, "type"), "void")) { 34 pname = NewString(""); 35 Printf(pname, "arg%d", arg_idx++); 36 } 37 if (p != l) 38 Printf(call, ", "); 39 Printv(call, pname, NIL); 40 } 41 Printf(call, ")"); 42 return call; 43} 44 45/* Swig_class_declaration() 46 * 47 * Generate the start of a class/struct declaration. 48 * e.g. "class myclass" 49 * 50 */ 51 52String *Swig_class_declaration(Node *n, String *name) { 53 if (!name) { 54 name = Getattr(n, "sym:name"); 55 } 56 String *result = NewString(""); 57 String *kind = Getattr(n, "kind"); 58 Printf(result, "%s %s", kind, name); 59 return result; 60} 61 62String *Swig_class_name(Node *n) { 63 String *name; 64 name = Copy(Getattr(n, "sym:name")); 65 return name; 66} 67 68/* Swig_director_declaration() 69 * 70 * Generate the full director class declaration, complete with base classes. 71 * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {" 72 * 73 */ 74 75String *Swig_director_declaration(Node *n) { 76 String *classname = Swig_class_name(n); 77 String *directorname = NewStringf("SwigDirector_%s", classname); 78 String *base = Getattr(n, "classtype"); 79 String *declaration = Swig_class_declaration(n, directorname); 80 Printf(declaration, " : public %s, public Swig::Director {\n", base); 81 Delete(classname); 82 Delete(directorname); 83 return declaration; 84} 85 86 87String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms) { 88 String *func; 89 int i = 0; 90 int comma = 0; 91 Parm *p = parms; 92 SwigType *pt; 93 String *nname; 94 95 func = NewString(""); 96 nname = SwigType_namestr(name); 97 Printf(func, "%s(", nname); 98 while (p) { 99 String *pname; 100 pt = Getattr(p, "type"); 101 if ((SwigType_type(pt) != T_VOID)) { 102 if (comma) 103 Printf(func, ","); 104 pname = Getattr(p, "name"); 105 Printf(func, "%s", pname); 106 comma = 1; 107 i++; 108 } 109 p = nextSibling(p); 110 } 111 Printf(func, ")"); 112 return func; 113} 114 115/* Swig_method_decl 116 * 117 * Misnamed and misappropriated! Taken from SWIG's type string manipulation utilities 118 * and modified to generate full (or partial) type qualifiers for method declarations, 119 * local variable declarations, and return value casting. More importantly, it merges 120 * parameter type information with actual parameter names to produce a complete method 121 * declaration that fully mirrors the original method declaration. 122 * 123 * There is almost certainly a saner way to do this. 124 * 125 * This function needs to be cleaned up and possibly split into several smaller 126 * functions. For instance, attaching default names to parameters should be done in a 127 * separate function. 128 * 129 */ 130 131String *Swig_method_decl(SwigType *returntype, SwigType *decl, const_String_or_char_ptr id, List *args, int strip, int values) { 132 String *result; 133 List *elements; 134 String *element = 0, *nextelement; 135 int is_const = 0; 136 int nelements, i; 137 int is_func = 0; 138 int arg_idx = 0; 139 140 if (id) { 141 result = NewString(Char(id)); 142 } else { 143 result = NewString(""); 144 } 145 146 elements = SwigType_split(decl); 147 nelements = Len(elements); 148 if (nelements > 0) { 149 element = Getitem(elements, 0); 150 } 151 for (i = 0; i < nelements; i++) { 152 if (i < (nelements - 1)) { 153 nextelement = Getitem(elements, i + 1); 154 } else { 155 nextelement = 0; 156 } 157 if (SwigType_isqualifier(element)) { 158 int skip = 0; 159 DOH *q = 0; 160 if (!strip) { 161 q = SwigType_parm(element); 162 if (!Cmp(q, "const")) { 163 is_const = 1; 164 is_func = SwigType_isfunction(nextelement); 165 if (is_func) 166 skip = 1; 167 skip = 1; 168 } 169 if (!skip) { 170 Insert(result, 0, " "); 171 Insert(result, 0, q); 172 } 173 Delete(q); 174 } 175 } else if (SwigType_isfunction(element)) { 176 Parm *parm; 177 String *p; 178 Append(result, "("); 179 parm = args; 180 while (parm != 0) { 181 String *type = Getattr(parm, "type"); 182 String *name = Getattr(parm, "name"); 183 if (!name && Cmp(type, "void")) { 184 name = NewString(""); 185 Printf(name, "arg%d", arg_idx++); 186 Setattr(parm, "name", name); 187 } 188 if (!name) { 189 name = NewString(""); 190 } 191 p = SwigType_str(type, name); 192 Append(result, p); 193 String *value = Getattr(parm, "value"); 194 if (values && (value != 0)) { 195 Printf(result, " = %s", value); 196 } 197 parm = nextSibling(parm); 198 if (parm != 0) 199 Append(result, ", "); 200 } 201 Append(result, ")"); 202 } else if (returntype) { // This check is intended for conversion operators to a pointer/reference which needs the pointer/reference ignoring in the declaration 203 if (SwigType_ispointer(element)) { 204 Insert(result, 0, "*"); 205 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { 206 Insert(result, 0, "("); 207 Append(result, ")"); 208 } 209 } else if (SwigType_ismemberpointer(element)) { 210 String *q; 211 q = SwigType_parm(element); 212 Insert(result, 0, "::*"); 213 Insert(result, 0, q); 214 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { 215 Insert(result, 0, "("); 216 Append(result, ")"); 217 } 218 Delete(q); 219 } else if (SwigType_isreference(element)) { 220 Insert(result, 0, "&"); 221 } else if (SwigType_isarray(element)) { 222 DOH *size; 223 Append(result, "["); 224 size = SwigType_parm(element); 225 Append(result, size); 226 Append(result, "]"); 227 Delete(size); 228 } else { 229 if (Strcmp(element, "v(...)") == 0) { 230 Insert(result, 0, "..."); 231 } else { 232 String *bs = SwigType_namestr(element); 233 Insert(result, 0, " "); 234 Insert(result, 0, bs); 235 Delete(bs); 236 } 237 } 238 } 239 element = nextelement; 240 } 241 242 Delete(elements); 243 244 if (is_const) { 245 if (is_func) { 246 Append(result, " "); 247 Append(result, "const"); 248 } else { 249 Insert(result, 0, "const "); 250 } 251 } 252 253 Chop(result); 254 255 if (returntype) { 256 Insert(result, 0, " "); 257 String *rtype = SwigType_str(returntype, 0); 258 Insert(result, 0, rtype); 259 Delete(rtype); 260 } 261 262 return result; 263} 264 265/* ----------------------------------------------------------------------------- 266 * Swig_director_emit_dynamic_cast() 267 * 268 * In order to call protected virtual director methods from the target language, we need 269 * to add an extra dynamic_cast to call the public C++ wrapper in the director class. 270 * Also for non-static protected members when the allprotected option is on. 271 * ----------------------------------------------------------------------------- */ 272void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f) { 273 // TODO: why is the storage element removed in staticmemberfunctionHandler ?? 274 if ((!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall"))) || 275 (is_non_virtual_protected_access(n) && !(checkAttribute(n, "staticmemberfunctionHandler:storage", "static") || 276 checkAttribute(n, "storage", "static")) 277 && !Equal(nodeType(n), "constructor"))) { 278 Node *parent = Getattr(n, "parentNode"); 279 String *symname = Getattr(parent, "sym:name"); 280 String *dirname = NewStringf("SwigDirector_%s", symname); 281 String *dirdecl = NewStringf("%s *darg = 0", dirname); 282 Wrapper_add_local(f, "darg", dirdecl); 283 Printf(f->code, "darg = dynamic_cast<%s *>(arg1);\n", dirname); 284 Delete(dirname); 285 Delete(dirdecl); 286 } 287} 288 289