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.
7 * Useful functions for emitting various pieces of code.
8 * ----------------------------------------------------------------------------- */
10 char cvsroot_emit_cxx[] = "$Id: emit.cxx 11471 2009-07-29 20:52:29Z wsfulton $";
14 /* -----------------------------------------------------------------------------
15 * emit_return_variable()
17 * Emits a variable declaration for a function return value.
18 * The variable name is always called result.
19 * n => Node of the method being wrapped
20 * rt => the return type
21 * f => the wrapper to generate code into
22 * ----------------------------------------------------------------------------- */
24 void emit_return_variable(Node *n, SwigType *rt, Wrapper *f) {
26 if (!GetFlag(n, "tmap:out:optimal")) {
27 if (rt && (SwigType_type(rt) != T_VOID)) {
28 SwigType *vt = cplus_value_type(rt);
29 SwigType *tt = vt ? vt : rt;
30 SwigType *lt = SwigType_ltype(tt);
31 String *lstr = SwigType_str(lt, "result");
32 if (SwigType_ispointer(lt)) {
33 Wrapper_add_localv(f, "result", lstr, "= 0", NULL);
35 Wrapper_add_local(f, "result", lstr);
46 /* -----------------------------------------------------------------------------
47 * emit_parameter_variables()
49 * Emits a list of variable declarations for function parameters.
50 * The variable names are always called arg1, arg2, etc...
51 * l => the parameter list
52 * f => the wrapper to generate code into
53 * ----------------------------------------------------------------------------- */
55 void emit_parameter_variables(ParmList *l, Wrapper *f) {
60 /* Emit function arguments */
63 /* Attach typemaps to parameters */
64 /* Swig_typemap_attach_parms("ignore",l,f); */
66 Swig_typemap_attach_parms("default", l, f);
67 Swig_typemap_attach_parms("arginit", l, f);
69 /* Apply the arginit and default */
72 tm = Getattr(p, "tmap:arginit");
74 Replace(tm, "$target", Getattr(p, "lname"), DOH_REPLACE_ANY);
75 Printv(f->code, tm, "\n", NIL);
76 p = Getattr(p, "tmap:arginit:next");
82 /* Apply the default typemap */
85 tm = Getattr(p, "tmap:default");
87 Replace(tm, "$target", Getattr(p, "lname"), DOH_REPLACE_ANY);
88 Printv(f->code, tm, "\n", NIL);
89 p = Getattr(p, "tmap:default:next");
96 /* -----------------------------------------------------------------------------
97 * emit_attach_parmmaps()
99 * Attach the standard parameter related typemaps.
100 * ----------------------------------------------------------------------------- */
102 void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
103 Swig_typemap_attach_parms("in", l, f);
104 Swig_typemap_attach_parms("typecheck", l, 0);
105 Swig_typemap_attach_parms("argout", l, f);
106 Swig_typemap_attach_parms("check", l, f);
107 Swig_typemap_attach_parms("freearg", l, f);
110 /* This is compatibility code to deal with the deprecated "ignore" typemap */
115 tm = Getattr(p, "tmap:in");
116 if (tm && checkAttribute(p, "tmap:in:numinputs", "0")) {
117 Replaceall(tm, "$target", Getattr(p, "lname"));
118 Printv(f->code, tm, "\n", NIL);
119 np = Getattr(p, "tmap:in:next");
120 while (p && (p != np)) {
121 /* Setattr(p,"ignore","1"); Deprecate */
125 p = Getattr(p, "tmap:in:next");
132 /* Perform a sanity check on "in" and "freearg" typemaps. These
133 must exactly match to avoid chaos. If a mismatch occurs, we
134 nuke the freearg typemap */
138 Parm *npin, *npfreearg;
140 npin = Getattr(p, "tmap:in:next");
143 if (Getattr(p,"tmap:ignore")) {
144 npin = Getattr(p,"tmap:ignore:next");
145 } else if (Getattr(p,"tmap:in")) {
146 npin = Getattr(p,"tmap:in:next");
150 if (Getattr(p, "tmap:freearg")) {
151 npfreearg = Getattr(p, "tmap:freearg:next");
152 if (npin != npfreearg) {
154 Delattr(p, "tmap:freearg");
155 Delattr(p, "tmap:freearg:next");
164 /* Check for variable length arguments with no input typemap.
165 If no input is defined, we set this to ignore and print a
172 if (!checkAttribute(p, "tmap:in:numinputs", "0")) {
174 p = Getattr(p, "tmap:in:next");
177 if (SwigType_isvarargs(Getattr(p, "type"))) {
178 Swig_warning(WARN_LANG_VARARGS, input_file, line_number, "Variable length arguments discarded.\n");
179 Setattr(p, "tmap:in", "");
185 /* Check if last input argument is variable length argument */
189 if (SwigType_isvarargs(Getattr(p, "type"))) {
190 Setattr(l, "emit:varargs", lp);
199 /* -----------------------------------------------------------------------------
200 * emit_num_arguments()
202 * Calculate the total number of arguments. This function is safe for use
203 * with multi-argument typemaps which may change the number of arguments in
205 * ----------------------------------------------------------------------------- */
207 int emit_num_arguments(ParmList *parms) {
212 if (Getattr(p, "tmap:in")) {
213 nargs += GetInt(p, "tmap:in:numinputs");
214 p = Getattr(p, "tmap:in:next");
220 /* DB 04/02/2003: Not sure this is necessary with tmap:in:numinputs */
222 if (parms && (p = Getattr(parms,"emit:varargs"))) {
223 if (!nextSibling(p)) {
231 /* -----------------------------------------------------------------------------
232 * emit_num_required()
234 * Computes the number of required arguments. This function is safe for
235 * use with multi-argument typemaps and knows how to skip over everything
236 * properly. Note that parameters with default values are counted unless
237 * the compact default args option is on.
238 * ----------------------------------------------------------------------------- */
240 int emit_num_required(ParmList *parms) {
243 Parm *first_default_arg = 0;
244 int compactdefargs = ParmList_is_compactdefargs(p);
247 if (Getattr(p, "tmap:in") && checkAttribute(p, "tmap:in:numinputs", "0")) {
248 p = Getattr(p, "tmap:in:next");
250 if (Getattr(p, "tmap:default"))
252 if (Getattr(p, "value")) {
253 if (!first_default_arg)
254 first_default_arg = p;
258 nargs += GetInt(p, "tmap:in:numinputs");
259 if (Getattr(p, "tmap:in")) {
260 p = Getattr(p, "tmap:in:next");
267 /* Print error message for non-default arguments following default arguments */
268 /* The error message is printed more than once with most language modules, this ought to be fixed */
269 if (first_default_arg) {
270 p = first_default_arg;
272 if (Getattr(p, "tmap:in") && checkAttribute(p, "tmap:in:numinputs", "0")) {
273 p = Getattr(p, "tmap:in:next");
275 if (!Getattr(p, "value") && (!Getattr(p, "tmap:default"))) {
276 Swig_error(Getfile(p), Getline(p), "Non-optional argument '%s' follows an optional argument.\n", Getattr(p, "name"));
278 if (Getattr(p, "tmap:in")) {
279 p = Getattr(p, "tmap:in:next");
287 /* DB 04/02/2003: Not sure this is necessary with tmap:in:numinputs */
289 if (parms && (p = Getattr(parms,"emit:varargs"))) {
290 if (!nextSibling(p)) {
298 /* -----------------------------------------------------------------------------
301 * Checks if a function is a varargs function
302 * ----------------------------------------------------------------------------- */
304 int emit_isvarargs(ParmList *p) {
307 if (Getattr(p, "emit:varargs"))
312 /* -----------------------------------------------------------------------------
313 * void emit_mark_vararg_parms()
315 * Marks the vararg parameters which are to be ignored.
316 * Vararg parameters are marked as ignored if there is no 'in' varargs (...)
318 * ----------------------------------------------------------------------------- */
320 void emit_mark_varargs(ParmList *l) {
323 if (SwigType_isvarargs(Getattr(p, "type")))
324 if (!Getattr(p, "tmap:in"))
325 Setattr(p, "varargs:ignore", "1");
331 /* replace_contract_args. This function replaces argument names in contract
332 specifications. Used in conjunction with the %contract directive. */
334 static void replace_contract_args(Parm *cp, Parm *rp, String *s) {
336 String *n = Getattr(cp, "name");
338 Replace(s, n, Getattr(rp, "lname"), DOH_REPLACE_ID);
340 cp = nextSibling(cp);
341 rp = nextSibling(rp);
346 /* -----------------------------------------------------------------------------
347 * int emit_action_code()
349 * Emits action code for a wrapper. Adds in exception handling code (%exception).
350 * eaction -> the action code to emit
351 * wrappercode -> the emitted code (output)
352 * ----------------------------------------------------------------------------- */
353 int emit_action_code(Node *n, String *wrappercode, String *eaction) {
354 assert(Getattr(n, "wrap:name"));
356 /* Look for except feature (%exception) */
357 String *tm = GetFlagAttr(n, "feature:except");
360 if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
361 if (Strstr(tm, "$")) {
362 Replaceall(tm, "$name", Getattr(n, "name"));
363 Replaceall(tm, "$symname", Getattr(n, "sym:name"));
364 Replaceall(tm, "$function", eaction); // deprecated
365 Replaceall(tm, "$action", eaction);
366 Replaceall(tm, "$wrapname", Getattr(n, "wrap:name"));
367 String *overloaded = Getattr(n, "sym:overloaded");
368 Replaceall(tm, "$overname", overloaded ? Char(Getattr(n, "sym:overname")) : "");
370 if (Strstr(tm, "$decl")) {
371 String *decl = Swig_name_decl(n);
372 Replaceall(tm, "$decl", decl);
375 if (Strstr(tm, "$fulldecl")) {
376 String *fulldecl = Swig_name_fulldecl(n);
377 Replaceall(tm, "$fulldecl", fulldecl);
381 Printv(wrappercode, tm, "\n", NIL);
385 Printv(wrappercode, eaction, "\n", NIL);
390 /* -----------------------------------------------------------------------------
393 * Emits the call to the wrapped function.
394 * Adds in exception specification exception handling and %exception code.
395 * ----------------------------------------------------------------------------- */
396 String *emit_action(Node *n) {
397 String *actioncode = NewStringEmpty();
402 ParmList *catchlist = Getattr(n, "catchlist");
404 /* Look for fragments */
406 String *fragment = Getattr(n, "feature:fragment");
409 String *t = Copy(fragment);
411 tok = strtok(c, ",");
413 String *fname = NewString(tok);
414 Setfile(fname, Getfile(n));
415 Setline(fname, Getline(n));
416 Swig_fragment_emit(fname);
418 tok = strtok(NULL, ",");
424 /* Emit wrapper code (if any) */
425 wrap = Getattr(n, "wrap:code");
426 if (wrap && Swig_filebyname("header") != Getattr(n, "wrap:code:done")) {
427 File *f_code = Swig_filebyname("header");
429 Printv(f_code, wrap, NIL);
431 Setattr(n, "wrap:code:done", f_code);
434 action = Getattr(n, "feature:action");
436 action = Getattr(n, "wrap:action");
439 /* Get the return type */
440 rt = Getattr(n, "type");
442 /* Emit contract code (if any) */
443 if (Swig_contract_mode_get()) {
445 tm = Getattr(n, "contract:preassert");
447 Printv(actioncode, tm, "\n", NIL);
450 /* Exception handling code */
452 /* saves action -> eaction for postcatching exception */
453 String *eaction = NewString("");
455 /* If we are in C++ mode and there is an exception specification. We're going to
456 enclose the block in a try block */
458 Printf(eaction, "try {\n");
461 Printv(eaction, action, NIL);
464 int unknown_catch = 0;
465 Printf(eaction, "}\n");
466 for (Parm *ep = catchlist; ep; ep = nextSibling(ep)) {
467 String *em = Swig_typemap_lookup("throws", ep, "_e", 0);
469 SwigType *et = Getattr(ep, "type");
470 SwigType *etr = SwigType_typedef_resolve_all(et);
471 if (SwigType_isreference(etr) || SwigType_ispointer(etr) || SwigType_isarray(etr)) {
472 Printf(eaction, "catch(%s) {", SwigType_str(et, "_e"));
473 } else if (SwigType_isvarargs(etr)) {
474 Printf(eaction, "catch(...) {");
476 Printf(eaction, "catch(%s) {", SwigType_str(et, "&_e"));
478 Printv(eaction, em, "\n", NIL);
479 Printf(eaction, "}\n");
481 Swig_warning(WARN_TYPEMAP_THROW, Getfile(n), Getline(n), "No 'throws' typemap defined for exception type '%s'\n", SwigType_str(Getattr(ep, "type"), 0));
486 Printf(eaction, "catch(...) { throw; }\n");
490 /* Look for except typemap (Deprecated) */
491 tm = Swig_typemap_lookup("except", n, "result", 0);
493 Setattr(n, "feature:except", tm);
497 /* emit the except feature code */
498 emit_action_code(n, actioncode, eaction);
502 /* Emit contract code (if any) */
503 if (Swig_contract_mode_get()) {
505 tm = Getattr(n, "contract:postassert");
507 Printv(actioncode, tm, "\n", NIL);