PageRenderTime 69ms CodeModel.GetById 12ms app.highlight 52ms RepoModel.GetById 2ms app.codeStats 0ms

/trunk/Source/Modules/directors.cxx

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