123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556 |
- /* -----------------------------------------------------------------------------
- * This file is part of SWIG, which is licensed as a whole under version 3
- * (or any later version) of the GNU General Public License. Some additional
- * terms also apply to certain portions of SWIG. The full details of the SWIG
- * license and copyrights can be found in the LICENSE and COPYRIGHT files
- * included with the SWIG source code as distributed by the SWIG developers
- * and at https://www.swig.org/legal.html.
- *
- * emit.cxx
- *
- * Useful functions for emitting various pieces of code.
- * ----------------------------------------------------------------------------- */
- #include "swigmod.h"
- #include "cparse.h"
- /* -----------------------------------------------------------------------------
- * emit_return_variable()
- *
- * Emits a variable declaration for a function return value.
- * The variable name is always called result.
- * n => Node of the method being wrapped
- * rt => the return type
- * f => the wrapper to generate code into
- * ----------------------------------------------------------------------------- */
- void emit_return_variable(Node *n, SwigType *rt, Wrapper *f) {
- if (!GetFlag(n, "tmap:out:optimal")) {
- if (rt && (SwigType_type(rt) != T_VOID)) {
- SwigType *vt = cplus_value_type(rt);
- SwigType *tt = vt ? vt : rt;
- SwigType *lt = SwigType_ltype(tt);
- String *lstr = SwigType_str(lt, Swig_cresult_name());
- if (SwigType_ispointer(lt)) {
- Wrapper_add_localv(f, Swig_cresult_name(), lstr, "= 0", NULL);
- } else {
- Wrapper_add_local(f, Swig_cresult_name(), lstr);
- }
- if (vt) {
- Delete(vt);
- }
- Delete(lt);
- Delete(lstr);
- }
- }
- }
- /* -----------------------------------------------------------------------------
- * emit_parameter_variables()
- *
- * Emits a list of variable declarations for function parameters.
- * The variable names are always called arg1, arg2, etc...
- * l => the parameter list
- * f => the wrapper to generate code into
- * ----------------------------------------------------------------------------- */
- void emit_parameter_variables(ParmList *l, Wrapper *f) {
- Parm *p;
- String *tm;
- /* Emit function arguments */
- Swig_cargs(f, l);
- /* Attach typemaps to parameters */
- /* Swig_typemap_attach_parms("ignore",l,f); */
- Swig_typemap_attach_parms("default", l, f);
- Swig_typemap_attach_parms("arginit", l, f);
- /* Apply the arginit and default */
- p = l;
- while (p) {
- tm = Getattr(p, "tmap:arginit");
- if (tm) {
- Printv(f->code, tm, "\n", NIL);
- p = Getattr(p, "tmap:arginit:next");
- } else {
- p = nextSibling(p);
- }
- }
- /* Apply the default typemap */
- p = l;
- while (p) {
- tm = Getattr(p, "tmap:default");
- if (tm) {
- Printv(f->code, tm, "\n", NIL);
- p = Getattr(p, "tmap:default:next");
- } else {
- p = nextSibling(p);
- }
- }
- }
- /* -----------------------------------------------------------------------------
- * emit_attach_parmmaps()
- *
- * Attach the standard parameter related typemaps.
- * ----------------------------------------------------------------------------- */
- void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
- Swig_typemap_attach_parms("in", l, f);
- Swig_typemap_attach_parms("typecheck", l, 0);
- Swig_typemap_attach_parms("argout", l, f);
- Swig_typemap_attach_parms("check", l, f);
- Swig_typemap_attach_parms("freearg", l, f);
- {
- /* This is compatibility code to deal with the deprecated "ignore" typemap */
- Parm *p = l;
- Parm *np;
- while (p) {
- String *tm = Getattr(p, "tmap:in");
- if (tm && checkAttribute(p, "tmap:in:numinputs", "0")) {
- Printv(f->code, tm, "\n", NIL);
- np = Getattr(p, "tmap:in:next");
- while (p && (p != np)) {
- /* Setattr(p,"ignore","1"); Deprecate */
- p = nextSibling(p);
- }
- } else if (tm) {
- p = Getattr(p, "tmap:in:next");
- } else {
- p = nextSibling(p);
- }
- }
- }
- /* Perform a sanity check on "in" and "freearg" typemaps. These
- must exactly match to avoid chaos. If a mismatch occurs, we
- nuke the freearg typemap */
- {
- Parm *p = l;
- Parm *npin, *npfreearg;
- while (p) {
- npin = Getattr(p, "tmap:in:next");
- /*
- if (Getattr(p,"tmap:ignore")) {
- npin = Getattr(p,"tmap:ignore:next");
- } else if (Getattr(p,"tmap:in")) {
- npin = Getattr(p,"tmap:in:next");
- }
- */
- if (Getattr(p, "tmap:freearg")) {
- npfreearg = Getattr(p, "tmap:freearg:next");
- if (npin != npfreearg) {
- while (p != npin) {
- Delattr(p, "tmap:freearg");
- Delattr(p, "tmap:freearg:next");
- p = nextSibling(p);
- }
- }
- }
- p = npin;
- }
- }
- /* Check for variable length arguments with no input typemap.
- If no input is defined, we set this to ignore and print a
- message.
- */
- {
- Parm *p = l;
- Parm *lp = 0;
- while (p) {
- if (!checkAttribute(p, "tmap:in:numinputs", "0")) {
- lp = p;
- p = Getattr(p, "tmap:in:next");
- continue;
- }
- if (SwigType_isvarargs(Getattr(p, "type"))) {
- Swig_warning(WARN_LANG_VARARGS, input_file, line_number, "Variable length arguments discarded.\n");
- Setattr(p, "tmap:in", "");
- }
- lp = 0;
- p = nextSibling(p);
- }
- /* Check if last input argument is variable length argument */
- if (lp) {
- p = lp;
- while (p) {
- if (SwigType_isvarargs(Getattr(p, "type"))) {
- // Mark the head of the ParmList that it has varargs
- Setattr(l, "emit:varargs", lp);
- //Printf(stdout, "setting emit:varargs %s ... %s +++ %s\n", Getattr(l, "emit:varargs"), Getattr(l, "type"), Getattr(p, "type"));
- break;
- }
- p = nextSibling(p);
- }
- }
- }
- /*
- * An equivalent type can be used in the typecheck typemap for SWIG to detect the overloading of equivalent
- * target language types. This is primarily for the smartptr feature, where a pointer and a smart pointer
- * are seen as equivalent types in the target language.
- */
- {
- Parm *p = l;
- while (p) {
- String *tm = Getattr(p, "tmap:typecheck");
- if (tm) {
- String *equivalent = Getattr(p, "tmap:typecheck:equivalent");
- if (equivalent) {
- String *precedence = Getattr(p, "tmap:typecheck:precedence");
- if (precedence && Strcmp(precedence, "0") != 0)
- Swig_error(Getfile(tm), Getline(tm), "The 'typecheck' typemap for %s contains an 'equivalent' attribute for a 'precedence' that is not set to SWIG_TYPECHECK_POINTER or 0.\n", SwigType_str(Getattr(p, "type"), 0));
- SwigType *cpt = Swig_cparse_type(equivalent);
- if (cpt) {
- Setattr(p, "equivtype", cpt);
- Delete(cpt);
- } else {
- Swig_error(Getfile(tm), Getline(tm), "Invalid type (%s) in 'equivalent' attribute in 'typecheck' typemap for type %s.\n", equivalent, SwigType_str(Getattr(p, "type"), 0));
- }
- }
- p = Getattr(p, "tmap:typecheck:next");
- } else {
- p = nextSibling(p);
- }
- }
- }
- }
- /* -----------------------------------------------------------------------------
- * emit_num_arguments()
- *
- * Calculate the total number of arguments. This function is safe for use
- * with multi-argument typemaps which may change the number of arguments in
- * strange ways.
- * ----------------------------------------------------------------------------- */
- int emit_num_arguments(ParmList *parms) {
- Parm *p = parms;
- int nargs = 0;
- while (p) {
- if (Getattr(p, "tmap:in")) {
- nargs += GetInt(p, "tmap:in:numinputs");
- p = Getattr(p, "tmap:in:next");
- } else {
- p = nextSibling(p);
- }
- }
- /* DB 04/02/2003: Not sure this is necessary with tmap:in:numinputs */
- /*
- if (parms && (p = Getattr(parms,"emit:varargs"))) {
- if (!nextSibling(p)) {
- nargs--;
- }
- }
- */
- return nargs;
- }
- /* -----------------------------------------------------------------------------
- * emit_num_required()
- *
- * Computes the number of required arguments. This function is safe for
- * use with multi-argument typemaps and knows how to skip over everything
- * properly. Note that parameters with default values are counted unless
- * the compact default args option is on.
- * ----------------------------------------------------------------------------- */
- int emit_num_required(ParmList *parms) {
- Parm *p = parms;
- int nargs = 0;
- Parm *first_default_arg = 0;
- int compactdefargs = ParmList_is_compactdefargs(p);
- while (p) {
- if (Getattr(p, "tmap:in") && checkAttribute(p, "tmap:in:numinputs", "0")) {
- p = Getattr(p, "tmap:in:next");
- } else {
- if (Getattr(p, "tmap:default"))
- break;
- if (Getattr(p, "value")) {
- if (!first_default_arg)
- first_default_arg = p;
- if (compactdefargs)
- break;
- }
- nargs += GetInt(p, "tmap:in:numinputs");
- if (Getattr(p, "tmap:in")) {
- p = Getattr(p, "tmap:in:next");
- } else {
- p = nextSibling(p);
- }
- }
- }
- /* Print error message for non-default arguments following default arguments */
- /* The error message is printed more than once with most language modules, this ought to be fixed */
- if (first_default_arg) {
- p = first_default_arg;
- while (p) {
- if (Getattr(p, "tmap:in") && checkAttribute(p, "tmap:in:numinputs", "0")) {
- p = Getattr(p, "tmap:in:next");
- } else {
- if (!Getattr(p, "value") && (!Getattr(p, "tmap:default"))) {
- Swig_error(Getfile(p), Getline(p), "Non-optional argument '%s' follows an optional argument.\n", Getattr(p, "name"));
- }
- if (Getattr(p, "tmap:in")) {
- p = Getattr(p, "tmap:in:next");
- } else {
- p = nextSibling(p);
- }
- }
- }
- }
- /* DB 04/02/2003: Not sure this is necessary with tmap:in:numinputs */
- /*
- if (parms && (p = Getattr(parms,"emit:varargs"))) {
- if (!nextSibling(p)) {
- nargs--;
- }
- }
- */
- return nargs;
- }
- /* -----------------------------------------------------------------------------
- * emit_isvarargs()
- *
- * Checks if a ParmList is a parameter list containing varargs.
- * This function requires emit_attach_parmmaps to have been called beforehand.
- * ----------------------------------------------------------------------------- */
- int emit_isvarargs(ParmList *p) {
- if (!p)
- return 0;
- if (Getattr(p, "emit:varargs"))
- return 1;
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * emit_isvarargs_function()
- *
- * Checks for varargs in a function/constructor (can be overloaded)
- * ----------------------------------------------------------------------------- */
- bool emit_isvarargs_function(Node *n) {
- bool has_varargs = false;
- Node *over = Getattr(n, "sym:overloaded");
- if (over) {
- for (Node *sibling = over; sibling; sibling = Getattr(sibling, "sym:nextSibling")) {
- if (ParmList_has_varargs(Getattr(sibling, "parms"))) {
- has_varargs = true;
- break;
- }
- }
- } else {
- has_varargs = ParmList_has_varargs(Getattr(n, "parms")) ? true : false;
- }
- return has_varargs;
- }
- /* -----------------------------------------------------------------------------
- * void emit_mark_vararg_parms()
- *
- * Marks the vararg parameters which are to be ignored.
- * Vararg parameters are marked as ignored if there is no 'in' varargs (...)
- * typemap.
- * ----------------------------------------------------------------------------- */
- void emit_mark_varargs(ParmList *l) {
- Parm *p = l;
- while (p) {
- if (SwigType_isvarargs(Getattr(p, "type")))
- if (!Getattr(p, "tmap:in"))
- Setattr(p, "varargs:ignore", "1");
- p = nextSibling(p);
- }
- }
- #if 0
- /* replace_contract_args. This function replaces argument names in contract
- specifications. Used in conjunction with the %contract directive. */
- static void replace_contract_args(Parm *cp, Parm *rp, String *s) {
- while (cp && rp) {
- String *n = Getattr(cp, "name");
- if (n) {
- Replace(s, n, Getattr(rp, "lname"), DOH_REPLACE_ID);
- }
- cp = nextSibling(cp);
- rp = nextSibling(rp);
- }
- }
- #endif
- /* -----------------------------------------------------------------------------
- * int emit_action_code()
- *
- * Emits action code for a wrapper. Adds in exception handling code (%exception).
- * eaction -> the action code to emit
- * wrappercode -> the emitted code (output)
- * ----------------------------------------------------------------------------- */
- int emit_action_code(Node *n, String *wrappercode, String *eaction) {
- assert(Getattr(n, "wrap:name"));
- /* Look for except feature (%exception) */
- String *tm = GetFlagAttr(n, "feature:except");
- if (tm)
- tm = Copy(tm);
- if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
- if (Strstr(tm, "$")) {
- Swig_replace_special_variables(n, parentNode(n), tm);
- Replaceall(tm, "$function", eaction); // deprecated
- Replaceall(tm, "$action", eaction);
- }
- Printv(wrappercode, tm, "\n", NIL);
- Delete(tm);
- return 1;
- } else {
- Printv(wrappercode, eaction, "\n", NIL);
- return 0;
- }
- }
- /* -----------------------------------------------------------------------------
- * int emit_action()
- *
- * Emits the call to the wrapped function.
- * Adds in exception specification exception handling and %exception code.
- * ----------------------------------------------------------------------------- */
- String *emit_action(Node *n) {
- String *actioncode = NewStringEmpty();
- String *tm;
- String *action;
- String *wrap;
- ParmList *catchlist = Getattr(n, "catchlist");
- /* Look for fragments */
- {
- String *fragment = Getattr(n, "feature:fragment");
- if (fragment) {
- char *c, *tok;
- String *t = Copy(fragment);
- c = Char(t);
- tok = strtok(c, ",");
- while (tok) {
- String *fname = NewString(tok);
- Setfile(fname, Getfile(n));
- Setline(fname, Getline(n));
- Swig_fragment_emit(fname);
- Delete(fname);
- tok = strtok(NULL, ",");
- }
- Delete(t);
- }
- }
- /* Emit wrapper code (if any) */
- wrap = Getattr(n, "wrap:code");
- if (wrap && Swig_filebyname("header") != Getattr(n, "wrap:code:done")) {
- File *f_code = Swig_filebyname("header");
- if (f_code) {
- Printv(f_code, wrap, NIL);
- }
- Setattr(n, "wrap:code:done", f_code);
- }
- action = Getattr(n, "feature:action");
- if (!action)
- action = Getattr(n, "wrap:action");
- assert(action != 0);
- /* Emit contract code (if any) */
- if (Swig_contract_mode_get()) {
- /* Preassertion */
- tm = Getattr(n, "contract:preassert");
- if (Len(tm)) {
- Printv(actioncode, tm, "\n", NIL);
- }
- }
- /* Exception handling code */
- /* saves action -> eaction for postcatching exception */
- String *eaction = NewString("");
- /* If we are in C++ mode and there is an exception specification. We're going to
- enclose the block in a try block */
- if (catchlist) {
- Printf(eaction, "try {\n");
- }
- String *preaction = Getattr(n, "wrap:preaction");
- if (preaction)
- Printv(eaction, preaction, NIL);
- Printv(eaction, action, NIL);
- String *postaction = Getattr(n, "wrap:postaction");
- if (postaction)
- Printv(eaction, postaction, NIL);
- if (catchlist) {
- int unknown_catch = 0;
- int has_varargs = 0;
- Printf(eaction, "}");
- for (Parm *ep = catchlist; ep; ep = nextSibling(ep)) {
- String *em = Swig_typemap_lookup("throws", ep, "_e", 0);
- if (em) {
- SwigType *et = Getattr(ep, "type");
- SwigType *etr = SwigType_typedef_resolve_all(et);
- if (SwigType_isreference(etr) || SwigType_ispointer(etr) || SwigType_isarray(etr)) {
- Printf(eaction, " catch(%s) {", SwigType_str(et, "_e"));
- } else if (SwigType_isvarargs(etr)) {
- Printf(eaction, " catch(...) {");
- has_varargs = 1;
- } else {
- Printf(eaction, " catch(%s) {", SwigType_str(et, "&_e"));
- }
- Printv(eaction, em, "\n", NIL);
- Printf(eaction, "}");
- } else {
- Swig_warning(WARN_TYPEMAP_THROW, Getfile(n), Getline(n), "No 'throws' typemap defined for exception type '%s'\n", SwigType_str(Getattr(ep, "type"), 0));
- unknown_catch = 1;
- }
- }
- if (unknown_catch && !has_varargs) {
- Printf(eaction, " catch(...) {\nthrow;\n}");
- }
- }
- /* Look for except typemap (Deprecated) */
- tm = Swig_typemap_lookup("except", n, Swig_cresult_name(), 0);
- if (tm) {
- Setattr(n, "feature:except", tm);
- tm = 0;
- }
- /* emit the except feature code */
- emit_action_code(n, actioncode, eaction);
- Delete(eaction);
- /* Emit contract code (if any) */
- if (Swig_contract_mode_get()) {
- /* Postassertion */
- tm = Getattr(n, "contract:postassert");
- if (Len(tm)) {
- Printv(actioncode, tm, "\n", NIL);
- }
- }
- return actioncode;
- }
|