import source from 1.3.40
[external/swig.git] / Source / Modules / directors.cxx
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
12 char 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
23 String *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
52 String *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
62 String *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
75 String *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
87 String *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
131 String *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  * ----------------------------------------------------------------------------- */
272 void 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