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