aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/swig/Source/Swig
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@ydb.tech>2023-11-30 13:26:22 +0300
committervitalyisaev <vitalyisaev@ydb.tech>2023-11-30 15:44:45 +0300
commit0a98fece5a9b54f16afeb3a94b3eb3105e9c3962 (patch)
tree291d72dbd7e9865399f668c84d11ed86fb190bbf /contrib/tools/swig/Source/Swig
parentcb2c8d75065e5b3c47094067cb4aa407d4813298 (diff)
downloadydb-0a98fece5a9b54f16afeb3a94b3eb3105e9c3962.tar.gz
YQ Connector:Use docker-compose in integrational tests
Diffstat (limited to 'contrib/tools/swig/Source/Swig')
-rw-r--r--contrib/tools/swig/Source/Swig/cwrap.c1661
-rw-r--r--contrib/tools/swig/Source/Swig/deprecate.c107
-rw-r--r--contrib/tools/swig/Source/Swig/error.c351
-rw-r--r--contrib/tools/swig/Source/Swig/extend.c141
-rw-r--r--contrib/tools/swig/Source/Swig/fragment.c188
-rw-r--r--contrib/tools/swig/Source/Swig/getopt.c104
-rw-r--r--contrib/tools/swig/Source/Swig/include.c377
-rw-r--r--contrib/tools/swig/Source/Swig/misc.c1569
-rw-r--r--contrib/tools/swig/Source/Swig/naming.c1771
-rw-r--r--contrib/tools/swig/Source/Swig/parms.c272
-rw-r--r--contrib/tools/swig/Source/Swig/scanner.c1898
-rw-r--r--contrib/tools/swig/Source/Swig/stype.c1422
-rw-r--r--contrib/tools/swig/Source/Swig/swig.h451
-rw-r--r--contrib/tools/swig/Source/Swig/swigfile.h41
-rw-r--r--contrib/tools/swig/Source/Swig/swigopt.h18
-rw-r--r--contrib/tools/swig/Source/Swig/swigparm.h35
-rw-r--r--contrib/tools/swig/Source/Swig/swigscan.h119
-rw-r--r--contrib/tools/swig/Source/Swig/swigtree.h54
-rw-r--r--contrib/tools/swig/Source/Swig/swigwrap.h31
-rw-r--r--contrib/tools/swig/Source/Swig/symbol.c2128
-rw-r--r--contrib/tools/swig/Source/Swig/tree.c426
-rw-r--r--contrib/tools/swig/Source/Swig/typemap.c2210
-rw-r--r--contrib/tools/swig/Source/Swig/typeobj.c1367
-rw-r--r--contrib/tools/swig/Source/Swig/typesys.c2309
-rw-r--r--contrib/tools/swig/Source/Swig/wrapfunc.c520
25 files changed, 19570 insertions, 0 deletions
diff --git a/contrib/tools/swig/Source/Swig/cwrap.c b/contrib/tools/swig/Source/Swig/cwrap.c
new file mode 100644
index 0000000000..b7d01bc117
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/cwrap.c
@@ -0,0 +1,1661 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * cwrap.c
+ *
+ * This file defines a variety of wrapping rules for C/C++ handling including
+ * the naming of local variables, calling conventions, and so forth.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+
+extern int UseWrapperSuffix;
+
+static const char *cresult_variable_name = "result";
+
+static Parm *nonvoid_parms(Parm *p) {
+ if (p) {
+ SwigType *t = Getattr(p, "type");
+ if (SwigType_type(t) == T_VOID)
+ return 0;
+ }
+ return p;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cresult_name_set()
+ *
+ * Change the name of the variable used to hold the return value from C/C++ wrapper functions
+ * from the default "result".
+ * ----------------------------------------------------------------------------- */
+
+void Swig_cresult_name_set(const char *new_name) {
+ cresult_variable_name = new_name;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cresult_name()
+ *
+ * Get the name of the variable used to hold the return value from C/C++ wrapper functions
+ * ----------------------------------------------------------------------------- */
+
+const char *Swig_cresult_name(void) {
+ return cresult_variable_name;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparm_name()
+ *
+ * Generates a name for the ith argument in an argument list
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cparm_name(Parm *p, int i) {
+ String *name = NewStringf("arg%d", i + 1);
+ if (p) {
+ Setattr(p, "lname", name);
+ }
+
+ return name;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_clocal()
+ *
+ * Creates a string that declares a C local variable type. Converts references
+ * and user defined types to pointers.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_clocal(SwigType *t, const_String_or_char_ptr name, const_String_or_char_ptr value) {
+ String *decl;
+
+ decl = NewStringEmpty();
+
+ switch (SwigType_type(t)) {
+ case T_REFERENCE:
+ if (value) {
+ String *lstrname = SwigType_lstr(t, name);
+ String *lstr = SwigType_lstr(t, 0);
+ Printf(decl, "%s = (%s) &%s_defvalue", lstrname, lstr, name);
+ Delete(lstrname);
+ Delete(lstr);
+ } else {
+ String *lstrname = SwigType_lstr(t, name);
+ Printf(decl, "%s = 0", lstrname);
+ Delete(lstrname);
+ }
+ break;
+ case T_RVALUE_REFERENCE:
+ if (value) {
+ String *lstrname = SwigType_lstr(t, name);
+ String *lstr = SwigType_lstr(t, 0);
+ Printf(decl, "%s = (%s) &%s_defrvalue", lstrname, lstr, name);
+ Delete(lstrname);
+ Delete(lstr);
+ } else {
+ String *lstrname = SwigType_lstr(t, name);
+ Printf(decl, "%s = 0", lstrname);
+ Delete(lstrname);
+ }
+ break;
+ case T_VOID:
+ break;
+ case T_VARARGS:
+ Printf(decl, "void *%s = 0", name);
+ break;
+
+ default:
+ if (value) {
+ String *lcaststr = SwigType_lcaststr(t, value);
+ String *lstr = SwigType_lstr(t, 0);
+ String *lstrn = SwigType_lstr(t, name);
+ Printf(decl, "%s = (%s) %s", lstrn, lstr, lcaststr);
+ Delete(lcaststr);
+ Delete(lstr);
+ Delete(lstrn);
+ } else {
+ String *lstrname = SwigType_lstr(t, name);
+ Append(decl, lstrname);
+ Delete(lstrname);
+ }
+ }
+ return decl;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_wrapped_var_convert()
+ *
+ * Converts a member variable for use in the get and set wrapper methods.
+ * This function only converts user defined types to pointers.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_wrapped_var_type(SwigType *t, int varcref) {
+ SwigType *ty;
+
+ if (!Strstr(t, "enum $unnamed")) {
+ ty = Copy(t);
+ } else {
+ /* Change the type for unnamed enum instance variables */
+ ty = NewString("int");
+ }
+
+ if (SwigType_isclass(t)) {
+ if (varcref) {
+ if (cparse_cplusplus) {
+ if (!SwigType_isconst(ty))
+ SwigType_add_qualifier(ty, "const");
+ SwigType_add_reference(ty);
+ } else {
+ return Copy(ty);
+ }
+ } else {
+ SwigType_add_pointer(ty);
+ }
+ }
+ return ty;
+}
+
+String *Swig_wrapped_member_var_type(SwigType *t, int varcref) {
+ SwigType *ty;
+
+ if (!Strstr(t, "enum $unnamed")) {
+ ty = Copy(t);
+ } else {
+ /* Change the type for unnamed enum instance variables */
+ ty = NewString("int");
+ }
+ if (SwigType_isclass(t)) {
+ if (varcref) {
+ if (cparse_cplusplus) {
+ if (!SwigType_isconst(ty))
+ SwigType_add_qualifier(ty, "const");
+ SwigType_add_reference(ty);
+ } else {
+ return Copy(ty);
+ }
+ } else {
+ SwigType_add_pointer(ty);
+ }
+ }
+ return ty;
+}
+
+
+static String *Swig_wrapped_var_deref(SwigType *t, const_String_or_char_ptr name, int varcref) {
+ if (SwigType_isclass(t)) {
+ if (varcref) {
+ if (cparse_cplusplus) {
+ return NewStringf("*%s", name);
+ } else {
+ return NewStringf("%s", name);
+ }
+ } else {
+ return NewStringf("*%s", name);
+ }
+ } else {
+ return SwigType_rcaststr(t, name);
+ }
+}
+
+static String *Swig_wrapped_var_assign(SwigType *t, const_String_or_char_ptr name, int varcref) {
+ if (SwigType_isclass(t)) {
+ if (varcref) {
+ return NewStringf("%s", name);
+ } else {
+ return NewStringf("&%s", name);
+ }
+ } else {
+ return SwigType_lcaststr(t, name);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cargs()
+ *
+ * Emit all of the local variables for a list of parameters. Returns the
+ * number of parameters.
+ * Default values for the local variables are only emitted if the compact default
+ * argument behaviour is required.
+ * ----------------------------------------------------------------------------- */
+int Swig_cargs(Wrapper *w, ParmList *p) {
+ int i = 0;
+ int compactdefargs = ParmList_is_compactdefargs(p);
+
+ while (p != 0) {
+ String *lname = Swig_cparm_name(p, i);
+ SwigType *pt = Getattr(p, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ String *local = 0;
+ String *type = Getattr(p, "type");
+ /* default values only emitted if in compact default args mode */
+ String *pvalue = (compactdefargs) ? Getattr(p, "value") : 0;
+
+ /* When using compactdefaultargs, the code generated initialises a variable via a constructor call that accepts the
+ * default value as a parameter. The default constructor is not called and therefore SwigValueWrapper is not needed. */
+ SwigType *altty = pvalue ? 0 : SwigType_alttype(type, 0);
+
+ int tycode = SwigType_type(type);
+ if (tycode == T_REFERENCE) {
+ if (pvalue) {
+ SwigType *tvalue;
+ String *defname, *defvalue, *rvalue, *qvalue;
+ rvalue = SwigType_typedef_resolve_all(pvalue);
+ qvalue = SwigType_typedef_qualified(rvalue);
+ defname = NewStringf("%s_defvalue", lname);
+ tvalue = Copy(type);
+ SwigType_del_reference(tvalue);
+ tycode = SwigType_type(tvalue);
+ if (tycode != T_USER) {
+ /* plain primitive type, we copy the def value */
+ String *lstr = SwigType_lstr(tvalue, defname);
+ defvalue = NewStringf("%s = %s", lstr, qvalue);
+ Delete(lstr);
+ } else {
+ /* user type, we copy the reference value */
+ String *str = SwigType_str(type, defname);
+ defvalue = NewStringf("%s = %s", str, qvalue);
+ Delete(str);
+ }
+ Wrapper_add_localv(w, defname, defvalue, NIL);
+ Delete(tvalue);
+ Delete(rvalue);
+ Delete(qvalue);
+ Delete(defname);
+ Delete(defvalue);
+ }
+ } else if (tycode == T_RVALUE_REFERENCE) {
+ if (pvalue) {
+ SwigType *tvalue;
+ String *defname, *defvalue, *rvalue, *qvalue;
+ rvalue = SwigType_typedef_resolve_all(pvalue);
+ qvalue = SwigType_typedef_qualified(rvalue);
+ defname = NewStringf("%s_defrvalue", lname);
+ tvalue = Copy(type);
+ SwigType_del_rvalue_reference(tvalue);
+ tycode = SwigType_type(tvalue);
+ if (tycode != T_USER) {
+ /* plain primitive type, we copy the def value */
+ String *lstr = SwigType_lstr(tvalue, defname);
+ defvalue = NewStringf("%s = %s", lstr, qvalue);
+ Delete(lstr);
+ } else {
+ /* user type, we copy the reference value */
+ String *str = SwigType_str(type, defname);
+ defvalue = NewStringf("%s = %s", str, qvalue);
+ Delete(str);
+ }
+ Wrapper_add_localv(w, defname, defvalue, NIL);
+ Delete(tvalue);
+ Delete(rvalue);
+ Delete(qvalue);
+ Delete(defname);
+ Delete(defvalue);
+ }
+ } else if (!pvalue && ((tycode == T_POINTER) || (tycode == T_STRING) || (tycode == T_WSTRING))) {
+ pvalue = (String *) "0";
+ }
+ if (!altty) {
+ local = Swig_clocal(pt, lname, pvalue);
+ } else {
+ local = Swig_clocal(altty, lname, pvalue);
+ Delete(altty);
+ }
+ Wrapper_add_localv(w, lname, local, NIL);
+ Delete(local);
+ i++;
+ }
+ Delete(lname);
+ p = nextSibling(p);
+ }
+ return (i);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cresult()
+ *
+ * This function generates the C code needed to set the result of a C
+ * function call.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cresult(SwigType *t, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
+ String *fcall;
+
+ fcall = NewStringEmpty();
+ switch (SwigType_type(t)) {
+ case T_VOID:
+ break;
+ case T_REFERENCE:
+ {
+ String *lstr = SwigType_lstr(t, 0);
+ Printf(fcall, "%s = (%s) &", name, lstr);
+ Delete(lstr);
+ }
+ break;
+ case T_RVALUE_REFERENCE:
+ {
+ String *const_lvalue_str;
+ String *lstr = SwigType_lstr(t, 0);
+ SwigType *tt = Copy(t);
+ SwigType_del_rvalue_reference(tt);
+ SwigType_add_qualifier(tt, "const");
+ SwigType_add_reference(tt);
+ const_lvalue_str = SwigType_rcaststr(tt, 0);
+
+ Printf(fcall, "%s = (%s) &%s", name, lstr, const_lvalue_str);
+
+ Delete(const_lvalue_str);
+ Delete(tt);
+ Delete(lstr);
+ }
+ break;
+ case T_USER:
+ Printf(fcall, "%s = ", name);
+ break;
+
+ default:
+ /* Normal return value */
+ {
+ String *lstr = SwigType_lstr(t, 0);
+ Printf(fcall, "%s = (%s)", name, lstr);
+ Delete(lstr);
+ }
+ break;
+ }
+
+ /* Now print out function call */
+ Append(fcall, decl);
+
+ /* A sick hack */
+ {
+ char *c = Char(decl) + Len(decl) - 1;
+ if (!((*c == ';') || (*c == '}')))
+ Append(fcall, ";");
+ }
+
+ return fcall;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cfunction_call()
+ *
+ * Creates a string that calls a C function using the local variable rules
+ * defined above.
+ *
+ * name(arg0, arg1, arg2, ... argn)
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cfunction_call(const_String_or_char_ptr name, ParmList *parms) {
+ String *func;
+ int i = 0;
+ int comma = 0;
+ Parm *p = parms;
+ String *nname;
+
+ func = NewStringEmpty();
+ nname = SwigType_namestr(name);
+
+ /*
+ SWIGTEMPLATEDISAMBIGUATOR is compiler dependent (swiglabels.swg),
+ - SUN Studio 9 requires 'template',
+ - gcc-3.4 forbids the use of 'template'.
+ the rest seems not caring very much,
+ */
+ if (SwigType_istemplate(name)) {
+ String *prefix = Swig_scopename_prefix(nname);
+ if (!prefix || Len(prefix) == 0) {
+ Printf(func, "%s(", nname);
+ } else {
+ String *last = Swig_scopename_last(nname);
+ Printf(func, "%s::SWIGTEMPLATEDISAMBIGUATOR %s(", prefix, last);
+ Delete(last);
+ }
+ Delete(prefix);
+ } else {
+ Printf(func, "%s(", nname);
+ }
+ Delete(nname);
+
+ while (p) {
+ SwigType *pt = Getattr(p, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ SwigType *rpt = SwigType_typedef_resolve_all(pt);
+ String *pname = Swig_cparm_name(p, i);
+ String *rcaststr = SwigType_rcaststr(rpt, pname);
+
+ if (comma) {
+ Append(func, ",");
+ }
+
+ if (cparse_cplusplus && SwigType_type(rpt) == T_USER)
+ Printv(func, "SWIG_STD_MOVE(", rcaststr, ")", NIL);
+ else
+ Printv(func, rcaststr, NIL);
+
+ Delete(rpt);
+ Delete(pname);
+ Delete(rcaststr);
+ comma = 1;
+ i++;
+ }
+ p = nextSibling(p);
+ }
+ Append(func, ")");
+ return func;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cmethod_call()
+ *
+ * Generates a string that calls a C++ method from a list of parameters.
+ *
+ * arg0->name(arg1, arg2, arg3, ..., argn)
+ *
+ * self is an argument that defines how to handle the first argument. Normally,
+ * it should be set to "this->". With C++ proxy classes enabled, it could be
+ * set to "(*this)->" or some similar sequence.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_cmethod_call(const_String_or_char_ptr name, ParmList *parms, const_String_or_char_ptr self, String *explicit_qualifier, SwigType *director_type) {
+ String *func, *nname;
+ int i = 0;
+ Parm *p = parms;
+ SwigType *pt;
+ int comma = 0;
+
+ func = NewStringEmpty();
+ if (!p)
+ return func;
+
+ if (!self)
+ self = "(this)->";
+ Append(func, self);
+
+ if (SwigType_istemplate(name) && (strncmp(Char(name), "operator ", 9) == 0)) {
+ /* fix for template + operators and compilers like gcc 3.3.5 */
+ String *tprefix = SwigType_templateprefix(name);
+ nname = tprefix;
+ } else {
+ nname = SwigType_namestr(name);
+ }
+
+ if (director_type) {
+ const char *pname = "darg";
+ String *rcaststr = SwigType_rcaststr(director_type, pname);
+ Replaceall(func, "this", rcaststr);
+ Delete(rcaststr);
+ } else {
+ pt = Getattr(p, "type");
+
+ /* If the method is invoked through a dereferenced pointer, we don't add any casts
+ (needed for smart pointers). Otherwise, we cast to the appropriate type */
+
+ if (Strstr(func, "*this")) {
+ String *pname = Swig_cparm_name(p, 0);
+ Replaceall(func, "this", pname);
+ Delete(pname);
+ } else {
+ String *pname = Swig_cparm_name(p, 0);
+ String *rcaststr = SwigType_rcaststr(pt, pname);
+ Replaceall(func, "this", rcaststr);
+ Delete(rcaststr);
+ Delete(pname);
+ }
+
+ /*
+ SWIGTEMPLATEDESIMBUAGATOR is compiler dependent (swiglabels.swg),
+ - SUN Studio 9 requires 'template',
+ - gcc-3.4 forbids the use of 'template' (correctly implementing the ISO C++ standard)
+ the others don't seem to care,
+ */
+ if (SwigType_istemplate(name))
+ Printf(func, "SWIGTEMPLATEDISAMBIGUATOR ");
+
+ if (explicit_qualifier) {
+ Printv(func, explicit_qualifier, "::", NIL);
+ }
+ }
+
+ Printf(func, "%s(", nname);
+
+ i++;
+ p = nextSibling(p);
+ while (p) {
+ pt = Getattr(p, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ String *pname = Swig_cparm_name(p, i);
+ String *rcaststr = SwigType_rcaststr(pt, pname);
+ if (comma)
+ Append(func, ",");
+ Append(func, rcaststr);
+ Delete(rcaststr);
+ Delete(pname);
+ comma = 1;
+ i++;
+ }
+ p = nextSibling(p);
+ }
+ Append(func, ")");
+ Delete(nname);
+ return func;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cconstructor_call()
+ *
+ * Creates a string that calls a C constructor function.
+ *
+ * calloc(1,sizeof(name));
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cconstructor_call(const_String_or_char_ptr name) {
+ DOH *func;
+
+ func = NewStringEmpty();
+ Printf(func, "calloc(1, sizeof(%s))", name);
+ return func;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_cppconstructor_call()
+ *
+ * Creates a string that calls a C function using the local variable rules
+ * defined above.
+ *
+ * name(arg0, arg1, arg2, ... argn)
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cppconstructor_base_call(const_String_or_char_ptr name, ParmList *parms, int skip_self) {
+ String *func;
+ String *nname;
+ int i = 0;
+ int comma = 0;
+ Parm *p = parms;
+ SwigType *pt;
+ if (skip_self) {
+ if (p)
+ p = nextSibling(p);
+ i++;
+ }
+ nname = SwigType_namestr(name);
+ func = NewStringEmpty();
+ Printf(func, "new %s(", nname);
+ while (p) {
+ pt = Getattr(p, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ String *rcaststr = 0;
+ String *pname = 0;
+ if (comma)
+ Append(func, ",");
+ if (!Getattr(p, "arg:byname")) {
+ pname = Swig_cparm_name(p, i);
+ i++;
+ } else {
+ pname = Getattr(p, "value");
+ if (pname)
+ pname = Copy(pname);
+ else
+ pname = Copy(Getattr(p, "name"));
+ }
+ rcaststr = SwigType_rcaststr(pt, pname);
+ Append(func, rcaststr);
+ Delete(rcaststr);
+ comma = 1;
+ Delete(pname);
+ }
+ p = nextSibling(p);
+ }
+ Append(func, ")");
+ Delete(nname);
+ return func;
+}
+
+String *Swig_cppconstructor_call(const_String_or_char_ptr name, ParmList *parms) {
+ return Swig_cppconstructor_base_call(name, parms, 0);
+}
+
+String *Swig_cppconstructor_nodirector_call(const_String_or_char_ptr name, ParmList *parms) {
+ return Swig_cppconstructor_base_call(name, parms, 1);
+}
+
+String *Swig_cppconstructor_director_call(const_String_or_char_ptr name, ParmList *parms) {
+ return Swig_cppconstructor_base_call(name, parms, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * recursive_flag_search()
+ *
+ * This function searches for the class attribute 'attr' in the class
+ * 'n' or recursively in its bases.
+ *
+ * If you define SWIG_FAST_REC_SEARCH, the method will set the found
+ * 'attr' in the target class 'n'. If not, the method will set the
+ * 'noattr' one. This prevents of having to navigate the entire
+ * hierarchy tree every time, so, it is an O(1) method... or something
+ * like that. However, it populates all the parsed classes with the
+ * 'attr' and/or 'noattr' attributes.
+ *
+ * If you undefine the SWIG_FAST_REC_SEARCH no attribute will be set
+ * while searching. This could be slower for large projects with very
+ * large hierarchy trees... or maybe not. But it will be cleaner.
+ *
+ * Maybe later a swig option can be added to switch at runtime.
+ *
+ * ----------------------------------------------------------------------------- */
+
+/* #define SWIG_FAST_REC_SEARCH 1 */
+static String *recursive_flag_search(Node *n, const String *attr, const String *noattr) {
+ String *f = 0;
+ n = Swig_methodclass(n);
+ if (GetFlag(n, noattr)) {
+ return 0;
+ }
+ f = GetFlagAttr(n, attr);
+ if (f) {
+ return f;
+ } else {
+ List *bl = Getattr(n, "bases");
+ if (bl) {
+ Iterator bi;
+ for (bi = First(bl); bi.item; bi = Next(bi)) {
+ f = recursive_flag_search(bi.item, attr, noattr);
+ if (f) {
+#ifdef SWIG_FAST_REC_SEARCH
+ SetFlagAttr(n, attr, f);
+#endif
+ return f;
+ }
+ }
+ }
+ }
+#ifdef SWIG_FAST_REC_SEARCH
+ SetFlag(n, noattr);
+#endif
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_unref_call()
+ *
+ * Find the "feature:unref" call, if any.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_unref_call(Node *n) {
+ String *unref = recursive_flag_search(n, "feature:unref", "feature:nounref");
+ if (unref) {
+ String *pname = Swig_cparm_name(0, 0);
+ unref = NewString(unref);
+ Replaceall(unref, "$this", pname);
+ Replaceall(unref, "$self", pname);
+ Delete(pname);
+ }
+ return unref;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_ref_call()
+ *
+ * Find the "feature:ref" call, if any.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_ref_call(Node *n, const String *lname) {
+ String *ref = recursive_flag_search(n, "feature:ref", "feature:noref");
+ if (ref) {
+ ref = NewString(ref);
+ Replaceall(ref, "$this", lname);
+ Replaceall(ref, "$self", lname);
+ }
+ return ref;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cdestructor_call()
+ *
+ * Creates a string that calls a C destructor function.
+ *
+ * free((char *) arg0);
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cdestructor_call(Node *n) {
+ Node *cn = Swig_methodclass(n);
+ String *unref = Swig_unref_call(cn);
+
+ if (unref) {
+ return unref;
+ } else {
+ String *pname = Swig_cparm_name(0, 0);
+ String *call = NewStringf("free((char *) %s);", pname);
+ Delete(pname);
+ return call;
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_cppdestructor_call()
+ *
+ * Creates a string that calls a C destructor function.
+ *
+ * delete arg1;
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cppdestructor_call(Node *n) {
+ Node *cn = Swig_methodclass(n);
+ String *unref = Swig_unref_call(cn);
+ if (unref) {
+ return unref;
+ } else {
+ String *pname = Swig_cparm_name(0, 0);
+ String *call = NewStringf("delete %s;", pname);
+ Delete(pname);
+ return call;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cmemberset_call()
+ *
+ * Generates a string that sets the name of a member in a C++ class or C struct.
+ *
+ * arg0->name = arg1
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cmemberset_call(const_String_or_char_ptr name, SwigType *type, String *self, int varcref) {
+ String *func;
+ String *pname0 = Swig_cparm_name(0, 0);
+ String *pname1 = Swig_cparm_name(0, 1);
+ func = NewStringEmpty();
+ if (!self)
+ self = NewString("(this)->");
+ else
+ self = NewString(self);
+ Replaceall(self, "this", pname0);
+ if (SwigType_type(type) != T_ARRAY) {
+ if (!Strstr(type, "enum $unnamed")) {
+ String *dref = Swig_wrapped_var_deref(type, pname1, varcref);
+ int extra_cast = 0;
+ if (cparse_cplusplusout) {
+ /* Required for C nested structs compiled as C++ as a duplicate of the nested struct is put into the global namespace.
+ * We could improve this by adding the extra casts just for nested structs rather than all structs. */
+ String *base = SwigType_base(type);
+ extra_cast = SwigType_isclass(base);
+ Delete(base);
+ }
+ if (extra_cast) {
+ String *lstr;
+ SwigType *ptype = Copy(type);
+ SwigType_add_pointer(ptype);
+ lstr = SwigType_lstr(ptype, 0);
+ Printf(func, "if (%s) *(%s)&%s%s = %s", pname0, lstr, self, name, dref);
+ Delete(lstr);
+ Delete(ptype);
+ } else {
+ Printf(func, "if (%s) %s%s = %s", pname0, self, name, dref);
+ }
+ Delete(dref);
+ } else {
+ Printf(func, "if (%s && sizeof(int) == sizeof(%s%s)) *(int*)(void*)&(%s%s) = %s", pname0, self, name, self, name, pname1);
+ }
+ }
+ Delete(self);
+ Delete(pname0);
+ Delete(pname1);
+ return (func);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_cmemberget_call()
+ *
+ * Generates a string that sets the name of a member in a C++ class or C struct.
+ *
+ * arg0->name
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cmemberget_call(const_String_or_char_ptr name, SwigType *t, String *self, int varcref) {
+ String *func;
+ String *call;
+ String *pname0 = Swig_cparm_name(0, 0);
+ if (!self)
+ self = NewString("(this)->");
+ else
+ self = NewString(self);
+ Replaceall(self, "this", pname0);
+ func = NewStringEmpty();
+ call = Swig_wrapped_var_assign(t, "", varcref);
+ Printf(func, "%s (%s%s)", call, self, name);
+ Delete(self);
+ Delete(call);
+ Delete(pname0);
+ return func;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_replace_special_variables()
+ *
+ * Replaces special variables with a value from the supplied node
+ * ----------------------------------------------------------------------------- */
+void Swig_replace_special_variables(Node *n, Node *parentnode, String *code) {
+ Node *parentclass = parentnode;
+ String *overloaded = Getattr(n, "sym:overloaded");
+ Replaceall(code, "$name", Getattr(n, "name"));
+ Replaceall(code, "$symname", Getattr(n, "sym:name"));
+ Replaceall(code, "$wrapname", Getattr(n, "wrap:name"));
+ Replaceall(code, "$overname", overloaded ? Char(Getattr(n, "sym:overname")) : "");
+
+ if (Strstr(code, "$decl")) {
+ String *decl = Swig_name_decl(n);
+ Replaceall(code, "$decl", decl);
+ Delete(decl);
+ }
+ if (Strstr(code, "$fulldecl")) {
+ String *fulldecl = Swig_name_fulldecl(n);
+ Replaceall(code, "$fulldecl", fulldecl);
+ Delete(fulldecl);
+ }
+
+ if (parentclass && !Equal(nodeType(parentclass), "class"))
+ parentclass = 0;
+ if (Strstr(code, "$parentclasssymname")) {
+ String *parentclasssymname = 0;
+ if (parentclass)
+ parentclasssymname = Getattr(parentclass, "sym:name");
+ Replaceall(code, "$parentclasssymname", parentclasssymname ? parentclasssymname : "");
+ }
+ if (Strstr(code, "$parentclassname")) {
+ String *parentclassname = 0;
+ if (parentclass)
+ parentclassname = Getattr(parentclass, "name");
+ Replaceall(code, "$parentclassname", parentclassname ? SwigType_str(parentclassname, "") : "");
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * extension_code()
+ *
+ * Generates an extension function (a function defined in %extend)
+ *
+ * return_type function_name(parms) code
+ *
+ * ----------------------------------------------------------------------------- */
+static String *extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self) {
+ String *parms_str = cplusplus ? ParmList_str_defaultargs(parms) : ParmList_str(parms);
+ String *sig = NewStringf("%s(%s)", function_name, (cplusplus || Len(parms_str)) ? parms_str : "void");
+ String *rt_sig = SwigType_str(return_type, sig);
+ String *body = NewStringf("SWIGINTERN %s", rt_sig);
+ Printv(body, code, "\n", NIL);
+ if (Strstr(body, "$")) {
+ Swig_replace_special_variables(n, parentNode(parentNode(n)), body);
+ if (self)
+ Replaceall(body, "$self", self);
+ }
+ Delete(parms_str);
+ Delete(sig);
+ Delete(rt_sig);
+ return body;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_add_extension_code()
+ *
+ * Generates an extension function (a function defined in %extend) and
+ * adds it to the "wrap:code" attribute of a node
+ *
+ * See also extension_code()
+ *
+ * ----------------------------------------------------------------------------- */
+int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self) {
+ String *body = extension_code(n, function_name, parms, return_type, code, cplusplus, self);
+ Setattr(n, "wrap:code", body);
+ Delete(body);
+ return SWIG_OK;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_MethodToFunction(Node *n)
+ *
+ * Converts a C++ method node to a function accessor function.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int flags, SwigType *director_type, int is_director) {
+ String *name;
+ ParmList *parms;
+ SwigType *type;
+ Parm *p;
+ String *self = 0;
+ int is_smart_pointer_overload = 0;
+ String *qualifier = Getattr(n, "qualifier");
+ String *directorScope = NewString(nspace);
+
+ Replace(directorScope, NSPACE_SEPARATOR, "_", DOH_REPLACE_ANY);
+
+ /* If smart pointer without const overload or mutable method, change self dereferencing */
+ if (flags & CWRAP_SMART_POINTER) {
+ if (flags & CWRAP_SMART_POINTER_OVERLOAD) {
+ if (qualifier && strncmp(Char(qualifier), "q(const)", 8) == 0) {
+ self = NewString("(*(this))->");
+ is_smart_pointer_overload = 1;
+ }
+ else if (Swig_storage_isstatic(n)) {
+ String *cname = Getattr(n, "extendsmartclassname") ? Getattr(n, "extendsmartclassname") : classname;
+ String *ctname = SwigType_namestr(cname);
+ self = NewStringf("(*(%s const *)this)->", ctname);
+ is_smart_pointer_overload = 1;
+ Delete(ctname);
+ }
+ else {
+ self = NewString("(*this)->");
+ }
+ } else {
+ self = NewString("(*this)->");
+ }
+ }
+
+ /* If node is a member template expansion, we don't allow added code */
+ if (Getattr(n, "templatetype"))
+ flags &= ~(CWRAP_EXTEND);
+
+ name = Getattr(n, "name");
+ parms = CopyParmList(nonvoid_parms(Getattr(n, "parms")));
+
+ type = NewString(classname);
+ if (qualifier) {
+ SwigType_push(type, qualifier);
+ }
+ SwigType_add_pointer(type);
+ p = NewParm(type, "self", n);
+ Setattr(p, "self", "1");
+ Setattr(p, "hidden","1");
+ /*
+ Disable the 'this' ownership in 'self' to manage inplace
+ operations like:
+
+ A& A::operator+=(int i) { ...; return *this;}
+
+ Here the 'self' parameter ownership needs to be disabled since
+ there could be two objects sharing the same 'this' pointer: the
+ input and the result one. And worse, the pointer could be deleted
+ in one of the objects (input), leaving the other (output) with
+ just a seg. fault to happen.
+
+ To avoid the previous problem, use
+
+ %feature("self:disown") *::operator+=;
+ %feature("new") *::operator+=;
+
+ These two lines just transfer the ownership of the 'this' pointer
+ from the input to the output wrapping object.
+
+ This happens in python, but may also happen in other target
+ languages.
+ */
+ if (GetFlag(n, "feature:self:disown")) {
+ Setattr(p, "wrap:disown", "1");
+ }
+ set_nextSibling(p, parms);
+ Delete(type);
+
+ /* Generate action code for the access */
+ if (!(flags & CWRAP_EXTEND)) {
+ String *explicit_qualifier = 0;
+ String *call = 0;
+ String *cres = 0;
+ String *explicitcall_name = 0;
+ int pure_virtual = !(Cmp(Getattr(n, "storage"), "virtual")) && !(Cmp(Getattr(n, "value"), "0"));
+
+ /* Call the explicit method rather than allow for a polymorphic call */
+ if ((flags & CWRAP_DIRECTOR_TWO_CALLS) || (flags & CWRAP_DIRECTOR_ONE_CALL)) {
+ String *access = Getattr(n, "access");
+ if (access && (Cmp(access, "protected") == 0)) {
+ /* If protected access (can only be if a director method) then call the extra public accessor method (language module must provide this) */
+ String *explicit_qualifier_tmp = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), "qname"));
+ explicitcall_name = NewStringf("%sSwigPublic", name);
+ if (Len(directorScope) > 0)
+ explicit_qualifier = NewStringf("SwigDirector_%s_%s", directorScope, explicit_qualifier_tmp);
+ else
+ explicit_qualifier = NewStringf("SwigDirector_%s", explicit_qualifier_tmp);
+ Delete(explicit_qualifier_tmp);
+ } else {
+ explicit_qualifier = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), "qname"));
+ }
+ }
+
+ if (!self && SwigType_isrvalue_reference(Getattr(n, "refqualifier"))) {
+ String *memory_header = NewString("<memory>");
+ Setfile(memory_header, Getfile(n));
+ Setline(memory_header, Getline(n));
+ Swig_fragment_emit(memory_header);
+ self = NewString("std::move(*this).");
+ Delete(memory_header);
+ }
+
+ call = Swig_cmethod_call(explicitcall_name ? explicitcall_name : name, p, self, explicit_qualifier, director_type);
+ cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call);
+
+ if (pure_virtual && is_director && (flags & CWRAP_DIRECTOR_TWO_CALLS)) {
+ String *qualifier = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), "qname"));
+ Delete(cres);
+ cres = NewStringf("Swig::DirectorPureVirtualException::raise(\"%s::%s\");", qualifier, name);
+ Delete(qualifier);
+ }
+
+ if (flags & CWRAP_DIRECTOR_TWO_CALLS) {
+ /* Create two method calls, one to call the explicit method, the other a normal polymorphic function call */
+ String *cres_both_calls = NewStringf("");
+ String *call_extra = Swig_cmethod_call(name, p, self, 0, director_type);
+ String *cres_extra = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call_extra);
+ Printv(cres_both_calls, "if (upcall) {\n", cres, "\n", "} else {", cres_extra, "\n}", NIL);
+ Setattr(n, "wrap:action", cres_both_calls);
+ Delete(cres_extra);
+ Delete(call_extra);
+ Delete(cres_both_calls);
+ } else {
+ Setattr(n, "wrap:action", cres);
+ }
+
+ Delete(explicitcall_name);
+ Delete(call);
+ Delete(cres);
+ Delete(explicit_qualifier);
+ } else {
+ /* Methods with default arguments are wrapped with additional methods for each default argument,
+ * however, only one extra %extend method is generated. */
+
+ String *defaultargs = Getattr(n, "defaultargs");
+ String *code = Getattr(n, "code");
+ String *cname = Getattr(n, "extendsmartclassname") ? Getattr(n, "extendsmartclassname") : classname;
+ String *membername = Swig_name_member(nspace, cname, name);
+ String *mangled = Swig_name_mangle(membername);
+ int is_smart_pointer = flags & CWRAP_SMART_POINTER;
+
+ type = Getattr(n, "type");
+
+ /* Check if the method is overloaded. If so, and it has code attached, we append an extra suffix
+ to avoid a name-clash in the generated wrappers. This allows overloaded methods to be defined
+ in C.
+
+ But when not using the suffix used for overloaded functions, we still need to ensure that the
+ wrapper name doesn't conflict with any wrapper functions for some languages, so optionally make
+ it sufficiently unique by appending a suffix similar to the one used for overloaded functions to it.
+ */
+ if (code) {
+ if (Getattr(n, "sym:overloaded")) {
+ Append(mangled, Getattr(defaultargs ? defaultargs : n, "sym:overname"));
+ } else if (UseWrapperSuffix) {
+ Append(mangled, "__SWIG");
+ }
+ }
+
+ /* See if there is any code that we need to emit */
+ if (!defaultargs && code && !is_smart_pointer) {
+ Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus, "self");
+ }
+ if (is_smart_pointer) {
+ int i = 0;
+ Parm *pp = p;
+ String *func = NewStringf("%s(", mangled);
+ String *cres;
+
+ if (!Swig_storage_isstatic(n)) {
+ String *pname = Swig_cparm_name(pp, i);
+ String *ctname = SwigType_namestr(cname);
+ String *fadd = 0;
+ if (is_smart_pointer_overload) {
+ String *nclassname = SwigType_namestr(classname);
+ fadd = NewStringf("(%s const *)((%s const *)%s)->operator ->()", ctname, nclassname, pname);
+ Delete(nclassname);
+ }
+ else {
+ fadd = NewStringf("(%s*)(%s)->operator ->()", ctname, pname);
+ }
+ Append(func, fadd);
+ Delete(ctname);
+ Delete(fadd);
+ Delete(pname);
+ pp = nextSibling(pp);
+ if (pp)
+ Append(func, ",");
+ } else {
+ pp = nextSibling(pp);
+ }
+ ++i;
+ while (pp) {
+ SwigType *pt = Getattr(pp, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ String *pname = Swig_cparm_name(pp, i++);
+ String *rcaststr = SwigType_rcaststr(pt, pname);
+ Append(func, rcaststr);
+ Delete(rcaststr);
+ Delete(pname);
+ pp = nextSibling(pp);
+ if (pp)
+ Append(func, ",");
+ }
+ }
+ Append(func, ")");
+ cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), func);
+ Setattr(n, "wrap:action", cres);
+ Delete(cres);
+ } else {
+ String *call = Swig_cfunction_call(mangled, p);
+ String *cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(call);
+ Delete(cres);
+ }
+
+ Delete(membername);
+ Delete(mangled);
+ }
+ Setattr(n, "parms", p);
+ Delete(p);
+ Delete(self);
+ Delete(parms);
+ Delete(directorScope);
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_methodclass()
+ *
+ * This function returns the class node for a given method or class.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_methodclass(Node *n) {
+ Node *nodetype = nodeType(n);
+ if (Cmp(nodetype, "class") == 0)
+ return n;
+ return GetFlag(n, "feature:extend") ? parentNode(parentNode(n)) : parentNode(n);
+}
+
+int Swig_directorclass(Node *n) {
+ Node *classNode = Swig_methodclass(n);
+ assert(classNode != 0);
+ return (Getattr(classNode, "vtable") != 0);
+}
+
+Node *Swig_directormap(Node *module, String *type) {
+ int is_void = !Cmp(type, "void");
+ if (!is_void && module) {
+ /* ?? follow the inheritance hierarchy? */
+
+ String *base = SwigType_base(type);
+
+ Node *directormap = Getattr(module, "wrap:directormap");
+ if (directormap)
+ return Getattr(directormap, base);
+ }
+ return 0;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_ConstructorToFunction()
+ *
+ * This function creates a C wrapper for a C constructor function.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_ConstructorToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, String *none_comparison, String *director_ctor, int cplus, int flags, String *directorname) {
+ Parm *p;
+ ParmList *directorparms;
+ SwigType *type;
+ int use_director = Swig_directorclass(n);
+ ParmList *parms = CopyParmList(nonvoid_parms(Getattr(n, "parms")));
+ /* Prepend the list of prefix_args (if any) */
+ Parm *prefix_args = Getattr(n, "director:prefix_args");
+ if (prefix_args != NIL) {
+ Parm *p2, *p3;
+
+ directorparms = CopyParmList(prefix_args);
+ for (p = directorparms; nextSibling(p); p = nextSibling(p));
+ for (p2 = parms; p2; p2 = nextSibling(p2)) {
+ p3 = CopyParm(p2);
+ set_nextSibling(p, p3);
+ Delete(p3);
+ p = p3;
+ }
+ } else
+ directorparms = parms;
+
+ type = NewString(classname);
+ SwigType_add_pointer(type);
+
+ if (flags & CWRAP_EXTEND) {
+ /* Constructors with default arguments are wrapped with additional constructor methods for each default argument,
+ * however, only one extra %extend method is generated. */
+ String *call;
+ String *cres;
+ String *defaultargs = Getattr(n, "defaultargs");
+ String *code = Getattr(n, "code");
+ String *membername = Swig_name_construct(nspace, classname);
+ String *mangled = Swig_name_mangle(membername);
+
+ /* Check if the constructor is overloaded. If so, and it has code attached, we append an extra suffix
+ to avoid a name-clash in the generated wrappers. This allows overloaded constructors to be defined
+ in C. */
+ if (Getattr(n, "sym:overloaded") && code) {
+ Append(mangled, Getattr(defaultargs ? defaultargs : n, "sym:overname"));
+ }
+
+ /* See if there is any code that we need to emit */
+ if (!defaultargs && code) {
+ Swig_add_extension_code(n, mangled, parms, type, code, cparse_cplusplus, "self");
+ }
+
+ call = Swig_cfunction_call(mangled, parms);
+ cres = Swig_cresult(type, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(cres);
+ Delete(call);
+ Delete(membername);
+ Delete(mangled);
+ } else {
+ if (cplus) {
+ /* if a C++ director class exists, create it rather than the original class */
+ if (use_director) {
+ Node *parent = Swig_methodclass(n);
+ int abstract = Getattr(parent, "abstracts") != 0;
+ String *action = NewStringEmpty();
+ String *tmp_none_comparison = Copy(none_comparison);
+ String *director_call;
+ String *nodirector_call;
+
+ Replaceall(tmp_none_comparison, "$arg", "arg1");
+
+ director_call = Swig_cppconstructor_director_call(directorname, directorparms);
+ nodirector_call = Swig_cppconstructor_nodirector_call(classname, parms);
+
+ if (abstract) {
+ /* whether or not the abstract class has been subclassed in python,
+ * create a director instance (there's no way to create a normal
+ * instance). if any of the pure virtual methods haven't been
+ * implemented in the target language, calls to those methods will
+ * generate Swig::DirectorPureVirtualException exceptions.
+ */
+ String *cres = Swig_cresult(type, Swig_cresult_name(), director_call);
+ Append(action, cres);
+ Delete(cres);
+ } else {
+ /* (scottm): The code for creating a new director is now a string
+ template that gets passed in via the director_ctor argument.
+
+ $comparison : an 'if' comparison from none_comparison
+ $director_new: Call new for director class
+ $nondirector_new: Call new for non-director class
+ */
+ String *cres;
+ Append(action, director_ctor);
+ Replaceall(action, "$comparison", tmp_none_comparison);
+
+ cres = Swig_cresult(type, Swig_cresult_name(), director_call);
+ Replaceall(action, "$director_new", cres);
+ Delete(cres);
+
+ cres = Swig_cresult(type, Swig_cresult_name(), nodirector_call);
+ Replaceall(action, "$nondirector_new", cres);
+ Delete(cres);
+ }
+ Setattr(n, "wrap:action", action);
+ Delete(tmp_none_comparison);
+ Delete(action);
+ } else {
+ String *call = Swig_cppconstructor_call(classname, parms);
+ String *cres = Swig_cresult(type, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(cres);
+ Delete(call);
+ }
+ } else {
+ String *call = Swig_cconstructor_call(classname);
+ String *cres = Swig_cresult(type, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(cres);
+ Delete(call);
+ }
+ }
+ Setattr(n, "type", type);
+ Setattr(n, "parms", parms);
+ Delete(type);
+ if (directorparms != parms)
+ Delete(directorparms);
+ Delete(parms);
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_DestructorToFunction()
+ *
+ * This function creates a C wrapper for a destructor function.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_DestructorToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int cplus, int flags) {
+ SwigType *type;
+ Parm *p;
+
+ type = NewString(classname);
+ SwigType_add_pointer(type);
+ p = NewParm(type, "self", n);
+ Setattr(p, "self", "1");
+ Setattr(p, "hidden", "1");
+ Setattr(p, "wrap:disown", "1");
+ Delete(type);
+ type = NewString("void");
+
+ if (flags & CWRAP_EXTEND) {
+ String *cres;
+ String *call;
+ String *membername, *mangled, *code;
+ membername = Swig_name_destroy(nspace, classname);
+ mangled = Swig_name_mangle(membername);
+ code = Getattr(n, "code");
+ if (code) {
+ Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus, "self");
+ }
+ call = Swig_cfunction_call(mangled, p);
+ cres = NewStringf("%s;", call);
+ Setattr(n, "wrap:action", cres);
+ Delete(membername);
+ Delete(mangled);
+ Delete(call);
+ Delete(cres);
+ } else {
+ if (cplus) {
+ String *call = Swig_cppdestructor_call(n);
+ String *cres = NewStringf("%s", call);
+ Setattr(n, "wrap:action", cres);
+ Delete(call);
+ Delete(cres);
+ } else {
+ String *call = Swig_cdestructor_call(n);
+ String *cres = NewStringf("%s", call);
+ Setattr(n, "wrap:action", cres);
+ Delete(call);
+ Delete(cres);
+ }
+ }
+ Setattr(n, "type", type);
+ Setattr(n, "parms", p);
+ Delete(type);
+ Delete(p);
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_MembersetToFunction()
+ *
+ * This function creates a C wrapper for setting a structure member.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_MembersetToFunction(Node *n, String *classname, int flags) {
+ String *name;
+ ParmList *parms;
+ Parm *p;
+ SwigType *t;
+ SwigType *ty;
+ SwigType *type;
+ SwigType *void_type = NewString("void");
+ String *self = 0;
+
+ int varcref = flags & CWRAP_NATURAL_VAR;
+
+ if (flags & CWRAP_SMART_POINTER) {
+ self = NewString("(*this)->");
+ }
+ if (flags & CWRAP_ALL_PROTECTED_ACCESS) {
+ self = NewStringf("darg->");
+ }
+
+ name = Getattr(n, "name");
+ type = Getattr(n, "type");
+
+ t = NewString(classname);
+ SwigType_add_pointer(t);
+ parms = NewParm(t, "self", n);
+ Setattr(parms, "self", "1");
+ Setattr(parms, "hidden","1");
+ Delete(t);
+
+ ty = Swig_wrapped_member_var_type(type, varcref);
+ p = NewParm(ty, name, n);
+ Setattr(parms, "hidden", "1");
+ set_nextSibling(parms, p);
+
+ /* If the type is a pointer or reference. We mark it with a special wrap:disown attribute */
+ if (SwigType_check_decl(type, "p.")) {
+ Setattr(p, "wrap:disown", "1");
+ }
+ Delete(p);
+
+ if (flags & CWRAP_EXTEND) {
+ String *call;
+ String *cres;
+ String *code = Getattr(n, "code");
+
+ String *sname = Swig_name_set(0, name);
+ String *membername = Swig_name_member(0, classname, sname);
+ String *mangled = Swig_name_mangle(membername);
+
+ if (code) {
+ /* I don't think this ever gets run - WSF */
+ Swig_add_extension_code(n, mangled, parms, void_type, code, cparse_cplusplus, "self");
+ }
+ call = Swig_cfunction_call(mangled, parms);
+ cres = NewStringf("%s;", call);
+ Setattr(n, "wrap:action", cres);
+
+ Delete(cres);
+ Delete(call);
+ Delete(mangled);
+ Delete(membername);
+ Delete(sname);
+ } else {
+ String *call = Swig_cmemberset_call(name, type, self, varcref);
+ String *cres = NewStringf("%s;", call);
+ Setattr(n, "wrap:action", cres);
+ Delete(call);
+ Delete(cres);
+ }
+ Setattr(n, "type", void_type);
+ Setattr(n, "parms", parms);
+ Delete(parms);
+ Delete(ty);
+ Delete(void_type);
+ Delete(self);
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_MembergetToFunction()
+ *
+ * This function creates a C wrapper for getting a structure member.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_MembergetToFunction(Node *n, String *classname, int flags) {
+ String *name;
+ ParmList *parms;
+ SwigType *t;
+ SwigType *ty;
+ SwigType *type;
+ String *self = 0;
+
+ int varcref = flags & CWRAP_NATURAL_VAR;
+
+ if (flags & CWRAP_SMART_POINTER) {
+ if (Swig_storage_isstatic(n)) {
+ Node *sn = Getattr(n, "cplus:staticbase");
+ String *base = Getattr(sn, "name");
+ self = NewStringf("%s::", base);
+ } else if (flags & CWRAP_SMART_POINTER_OVERLOAD) {
+ String *nclassname = SwigType_namestr(classname);
+ self = NewStringf("(*(%s const *)this)->", nclassname);
+ Delete(nclassname);
+ } else {
+ self = NewString("(*this)->");
+ }
+ }
+ if (flags & CWRAP_ALL_PROTECTED_ACCESS) {
+ self = NewStringf("darg->");
+ }
+
+ name = Getattr(n, "name");
+ type = Getattr(n, "type");
+
+ t = NewString(classname);
+ SwigType_add_pointer(t);
+ parms = NewParm(t, "self", n);
+ Setattr(parms, "self", "1");
+ Setattr(parms, "hidden","1");
+ Delete(t);
+
+ ty = Swig_wrapped_member_var_type(type, varcref);
+ if (flags & CWRAP_EXTEND) {
+ String *call;
+ String *cres;
+ String *code = Getattr(n, "code");
+
+ String *gname = Swig_name_get(0, name);
+ String *membername = Swig_name_member(0, classname, gname);
+ String *mangled = Swig_name_mangle(membername);
+
+ if (code) {
+ /* I don't think this ever gets run - WSF */
+ Swig_add_extension_code(n, mangled, parms, ty, code, cparse_cplusplus, "self");
+ }
+ call = Swig_cfunction_call(mangled, parms);
+ cres = Swig_cresult(ty, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+
+ Delete(cres);
+ Delete(call);
+ Delete(mangled);
+ Delete(membername);
+ Delete(gname);
+ } else {
+ String *call = Swig_cmemberget_call(name, type, self, varcref);
+ String *cres = Swig_cresult(ty, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(call);
+ Delete(cres);
+ }
+ Setattr(n, "type", ty);
+ Setattr(n, "parms", parms);
+ Delete(parms);
+ Delete(ty);
+
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_VarsetToFunction()
+ *
+ * This function creates a C wrapper for setting a global variable or static member
+ * variable.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_VarsetToFunction(Node *n, int flags) {
+ String *name, *nname;
+ ParmList *parms;
+ SwigType *type, *ty;
+
+ int varcref = flags & CWRAP_NATURAL_VAR;
+
+ name = Getattr(n, "name");
+ type = Getattr(n, "type");
+ nname = SwigType_namestr(name);
+ ty = Swig_wrapped_var_type(type, varcref);
+ parms = NewParm(ty, name, n);
+
+ if (flags & CWRAP_EXTEND) {
+ String *sname = Swig_name_set(0, name);
+ String *mangled = Swig_name_mangle(sname);
+ String *call = Swig_cfunction_call(mangled, parms);
+ String *cres = NewStringf("%s;", call);
+ Setattr(n, "wrap:action", cres);
+ Delete(cres);
+ Delete(call);
+ Delete(mangled);
+ Delete(sname);
+ } else {
+ if (!Strstr(type, "enum $unnamed")) {
+ String *pname = Swig_cparm_name(0, 0);
+ String *dref = Swig_wrapped_var_deref(type, pname, varcref);
+ String *call = NewStringf("%s = %s;", nname, dref);
+ Setattr(n, "wrap:action", call);
+ Delete(call);
+ Delete(dref);
+ Delete(pname);
+ } else {
+ String *pname = Swig_cparm_name(0, 0);
+ String *call = NewStringf("if (sizeof(int) == sizeof(%s)) *(int*)(void*)&(%s) = %s;", nname, nname, pname);
+ Setattr(n, "wrap:action", call);
+ Delete(pname);
+ Delete(call);
+ }
+ }
+ Setattr(n, "type", "void");
+ Setattr(n, "parms", parms);
+ Delete(parms);
+ Delete(ty);
+ Delete(nname);
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_VargetToFunction()
+ *
+ * This function creates a C wrapper for getting a global variable or static member
+ * variable.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_VargetToFunction(Node *n, int flags) {
+ String *cres, *call;
+ String *name;
+ SwigType *type;
+ SwigType *ty = 0;
+
+ int varcref = flags & CWRAP_NATURAL_VAR;
+
+ name = Getattr(n, "name");
+ type = Getattr(n, "type");
+ ty = Swig_wrapped_var_type(type, varcref);
+
+ if (flags & CWRAP_EXTEND) {
+ String *sname = Swig_name_get(0, name);
+ String *mangled = Swig_name_mangle(sname);
+ call = Swig_cfunction_call(mangled, 0);
+ cres = Swig_cresult(ty, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(mangled);
+ Delete(sname);
+ } else {
+ String *nname = 0;
+ if (Equal(nodeType(n), "constant")) {
+ String *rawval = Getattr(n, "rawval");
+ String *value = rawval ? rawval : Getattr(n, "value");
+ nname = NewStringf("(%s)", value);
+ } else {
+ nname = SwigType_namestr(name);
+ }
+ call = Swig_wrapped_var_assign(type, nname, varcref);
+ cres = Swig_cresult(ty, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(nname);
+ }
+
+ Setattr(n, "type", ty);
+ Delattr(n, "parms");
+ Delete(cres);
+ Delete(call);
+ Delete(ty);
+ return SWIG_OK;
+}
diff --git a/contrib/tools/swig/Source/Swig/deprecate.c b/contrib/tools/swig/Source/Swig/deprecate.c
new file mode 100644
index 0000000000..5783455e59
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/deprecate.c
@@ -0,0 +1,107 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * deprecate.c
+ *
+ * The functions in this file are SWIG core functions that are deprecated
+ * or which do not fit in nicely with everything else. Generally this means
+ * that the function and/or API needs to be changed in some future release.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+
+/* ---------------------------------------------------------------------
+ * ParmList_is_compactdefargs()
+ *
+ * Returns 1 if the parameter list passed in is marked for compact argument
+ * handling (by the "compactdefargs" attribute). Otherwise returns 0.
+ * ---------------------------------------------------------------------- */
+
+/* Discussion:
+
+ "compactdefargs" is a property set by the Parser to indicate special
+ handling of default arguments. This property seems to be something that
+ is associated with functions and methods rather than low-level ParmList
+ objects. Therefore, I don't like the fact that this special purpose
+ feature is bolted onto the side of ParmList objects.
+
+ Proposed solution:
+
+ 1. "compactdefargs" should be a feature set on function/method nodes
+ instead of ParmList objects. For example, if you have a function,
+ you would check the function node to see if the parameters are
+ to be handled in this way.
+
+
+ Difficulties:
+
+ 1. This is used by functions in cwrap.c and emit.cxx, none of which
+ are passed information about the function/method node. We might
+ have to change the API of those functions to make this work correctly.
+ For example:
+
+ int emit_num_required(ParmList *parms)
+
+ might become
+
+ int emit_num_required(ParmList *parms, int compactargs)
+
+*/
+
+int ParmList_is_compactdefargs(ParmList *p) {
+ int compactdefargs = 0;
+
+ if (p) {
+ compactdefargs = Getattr(p, "compactdefargs") ? 1 : 0;
+
+ /* The "compactdefargs" attribute should only be set on the first parameter in the list.
+ * However, sometimes an extra parameter is inserted at the beginning of the parameter list,
+ * so we check the 2nd parameter too. */
+ if (!compactdefargs) {
+ Parm *nextparm = nextSibling(p);
+ compactdefargs = (nextparm && Getattr(nextparm, "compactdefargs")) ? 1 : 0;
+ }
+ }
+
+ return compactdefargs;
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_errorstr()
+ *
+ * Generate a prototype string suitable for use in error/warning messages.
+ * Similar to ParmList_protostr() but is also aware of hidden parameters.
+ * ---------------------------------------------------------------------- */
+
+/* Discussion. This function is used to generate error messages, but take
+ into account that there might be a hidden parameter. Although this involves
+ parameter lists, it really isn't a core feature of swigparm.h or parms.c.
+ This is because the "hidden" attribute of parameters is added elsewhere (cwrap.c).
+
+ For now, this function is placed here because it doesn't really seem to fit in
+ with the parms.c interface.
+
+*/
+
+String *ParmList_errorstr(ParmList *p) {
+ String *out = NewStringEmpty();
+ while (p) {
+ if (Getattr(p,"hidden")) {
+ p = nextSibling(p);
+ } else {
+ String *pstr = SwigType_str(Getattr(p, "type"), 0);
+ Append(out, pstr);
+ p = nextSibling(p);
+ if (p) {
+ Append(out, ",");
+ }
+ Delete(pstr);
+ }
+ }
+ return out;
+}
diff --git a/contrib/tools/swig/Source/Swig/error.c b/contrib/tools/swig/Source/Swig/error.c
new file mode 100644
index 0000000000..efd644f9a8
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/error.c
@@ -0,0 +1,351 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * error.c
+ *
+ * Error handling functions. These are used to issue warnings and
+ * error messages.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <stdarg.h>
+#include <ctype.h>
+
+/* -----------------------------------------------------------------------------
+ * Commentary on the warning filter.
+ *
+ * The warning filter is a string of numbers prefaced by (-) or (+) to
+ * indicate whether or not a warning message is displayed. For example:
+ *
+ * "-304-201-140+210+201"
+ *
+ * The filter string is scanned left to right and the first occurrence
+ * of a warning number is used to determine printing behavior.
+ *
+ * The same number may appear more than once in the string. For example, in the
+ * above string, "201" appears twice. This simply means that warning 201
+ * was disabled after it was previously enabled. This may only be temporary
+ * setting--the first number may be removed later in which case the warning
+ * is reenabled.
+ * ----------------------------------------------------------------------------- */
+
+#if defined(_WIN32)
+# define DEFAULT_ERROR_MSG_FORMAT EMF_MICROSOFT
+#else
+# define DEFAULT_ERROR_MSG_FORMAT EMF_STANDARD
+#endif
+static ErrorMessageFormat msg_format = DEFAULT_ERROR_MSG_FORMAT;
+static int silence = 0; /* Silent operation */
+static String *filter = 0; /* Warning filter */
+static int warnall = 0;
+static int nwarning = 0;
+static int nerrors = 0;
+
+static int init_fmt = 0;
+static char wrn_wnum_fmt[64];
+static char wrn_nnum_fmt[64];
+static char err_line_fmt[64];
+static char err_eof_fmt[64];
+static char diag_line_fmt[64];
+static char diag_eof_fmt[64];
+
+static String *format_filename(const_String_or_char_ptr filename);
+
+/* -----------------------------------------------------------------------------
+ * Swig_warning()
+ *
+ * Issue a warning message on stderr.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const char *fmt, ...) {
+ String *out;
+ char *msg;
+ int wrn = 1;
+ va_list ap;
+ if (silence)
+ return;
+ if (!init_fmt)
+ Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
+
+ va_start(ap, fmt);
+
+ out = NewStringEmpty();
+ vPrintf(out, fmt, ap);
+
+ msg = Char(out);
+ if (isdigit((unsigned char) *msg)) {
+ unsigned long result = strtoul(msg, &msg, 10);
+ if (msg != Char(out)) {
+ msg++;
+ wnum = result;
+ }
+ }
+
+ /* Check in the warning filter */
+ if (filter) {
+ char temp[32];
+ char *c;
+ char *f = Char(filter);
+ sprintf(temp, "%d", wnum);
+ while (*f != '\0' && (c = strstr(f, temp))) {
+ if (*(c - 1) == '-') {
+ wrn = 0; /* Warning disabled */
+ break;
+ }
+ if (*(c - 1) == '+') {
+ wrn = 1; /* Warning enabled */
+ break;
+ }
+ f += strlen(temp);
+ }
+ }
+ if (warnall || wrn) {
+ String *formatted_filename = format_filename(filename);
+ String *full_message = NewString("");
+ if (wnum) {
+ Printf(full_message, wrn_wnum_fmt, formatted_filename, line, wnum);
+ } else {
+ Printf(full_message, wrn_nnum_fmt, formatted_filename, line);
+ }
+ Printf(full_message, "%s", msg);
+ Printv(stderr, full_message, NIL);
+ nwarning++;
+ Delete(full_message);
+ Delete(formatted_filename);
+ }
+ Delete(out);
+ va_end(ap);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_error()
+ *
+ * Issue an error message on stderr.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, ...) {
+ va_list ap;
+ String *formatted_filename = NULL;
+ String *full_message = NULL;
+
+ if (silence)
+ return;
+ if (!init_fmt)
+ Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
+
+ va_start(ap, fmt);
+ formatted_filename = format_filename(filename);
+ full_message = NewString("");
+ if (line > 0) {
+ Printf(full_message, err_line_fmt, formatted_filename, line);
+ } else {
+ Printf(full_message, err_eof_fmt, formatted_filename);
+ }
+ vPrintf(full_message, fmt, ap);
+ Printv(stderr, full_message, NIL);
+ va_end(ap);
+ nerrors++;
+ Delete(full_message);
+ Delete(formatted_filename);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_error_count()
+ *
+ * Returns number of errors received.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_error_count(void) {
+ return nerrors;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_error_silent()
+ *
+ * Set silent flag
+ * ----------------------------------------------------------------------------- */
+
+void Swig_error_silent(int s) {
+ silence = s;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_warnfilter()
+ *
+ * Takes a comma separate list of warning numbers and puts in the filter.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_warnfilter(const_String_or_char_ptr wlist, int add) {
+ char *c;
+ char *cw;
+ String *s;
+ if (!filter)
+ filter = NewStringEmpty();
+
+ s = NewString("");
+ Clear(s);
+ cw = Char(wlist);
+ while (*cw != '\0') {
+ if (*cw != ' ') {
+ Putc(*cw, s);
+ }
+ ++cw;
+ }
+ c = Char(s);
+ c = strtok(c, ", ");
+ while (c) {
+ if (isdigit((int) *c) || (*c == '+') || (*c == '-')) {
+ /* Even if c is a digit, the rest of the string might not be, eg in the case of typemap
+ * warnings (a bit odd really), eg: %warnfilter(SWIGWARN_TYPEMAP_CHARLEAK_MSG) */
+ if (add) {
+ Insert(filter, 0, c);
+ if (isdigit((int) *c)) {
+ Insert(filter, 0, "-");
+ }
+ } else {
+ char *temp = (char *)Malloc(sizeof(char)*strlen(c) + 2);
+ if (isdigit((int) *c)) {
+ sprintf(temp, "-%s", c);
+ } else {
+ strcpy(temp, c);
+ }
+ Replace(filter, temp, "", DOH_REPLACE_FIRST);
+ Free(temp);
+ }
+ }
+ c = strtok(NULL, ", ");
+ }
+ Delete(s);
+}
+
+void Swig_warnall(void) {
+ warnall = 1;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_warn_count()
+ *
+ * Return the number of warnings
+ * ----------------------------------------------------------------------------- */
+
+int Swig_warn_count(void) {
+ return nwarning;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_error_msg_format()
+ *
+ * Set the type of error/warning message display
+ * ----------------------------------------------------------------------------- */
+
+void Swig_error_msg_format(ErrorMessageFormat format) {
+ const char *error = "Error";
+ const char *warning = "Warning";
+
+ const char *fmt_eof = 0;
+ const char *fmt_line = 0;
+
+ /* here 'format' could be directly a string instead of an enum, but
+ by now a switch is used to translated into one. */
+ switch (format) {
+ case EMF_MICROSOFT:
+ fmt_line = "%s(%d) ";
+ fmt_eof = "%s(999999) "; /* Is there a special character for EOF? Just use a large number. */
+ break;
+ case EMF_STANDARD:
+ default:
+ fmt_line = "%s:%d";
+ fmt_eof = "%s:EOF";
+ }
+
+ sprintf(wrn_wnum_fmt, "%s: %s %%d: ", fmt_line, warning);
+ sprintf(wrn_nnum_fmt, "%s: %s: ", fmt_line, warning);
+ sprintf(err_line_fmt, "%s: %s: ", fmt_line, error);
+ sprintf(err_eof_fmt, "%s: %s: ", fmt_eof, error);
+ sprintf(diag_line_fmt, "%s: ", fmt_line);
+ sprintf(diag_eof_fmt, "%s: ", fmt_eof);
+
+ msg_format = format;
+ init_fmt = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * format_filename()
+ *
+ * Remove double backslashes in Windows filename paths for display
+ * ----------------------------------------------------------------------------- */
+static String *format_filename(const_String_or_char_ptr filename) {
+ String *formatted_filename = NewString(filename);
+#if defined(_WIN32)
+ Replaceall(formatted_filename, "\\\\", "\\");
+#endif
+ return formatted_filename;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_stringify_with_location()
+ *
+ * Return a string representation of any DOH object with line and file location
+ * information in the appropriate error message format. The string representation
+ * is enclosed within [] brackets after the line and file information.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_stringify_with_location(DOH *object) {
+ String *str = NewStringEmpty();
+
+ if (!init_fmt)
+ Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
+
+ if (object) {
+ int line = Getline(object);
+ String *formatted_filename = format_filename(Getfile(object));
+ if (line > 0) {
+ Printf(str, diag_line_fmt, formatted_filename, line);
+ } else {
+ Printf(str, diag_eof_fmt, formatted_filename);
+ }
+ if (Len(object) == 0) {
+ Printf(str, "[EMPTY]");
+ } else {
+ Printf(str, "[%s]", object);
+ }
+ Delete(formatted_filename);
+ } else {
+ Printf(str, "[NULL]");
+ }
+
+ return str;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_diagnostic()
+ *
+ * Issue a diagnostic message on stdout.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_diagnostic(const_String_or_char_ptr filename, int line, const char *fmt, ...) {
+ va_list ap;
+ String *formatted_filename = NULL;
+
+ if (!init_fmt)
+ Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
+
+ va_start(ap, fmt);
+ formatted_filename = format_filename(filename);
+ if (line > 0) {
+ Printf(stdout, diag_line_fmt, formatted_filename, line);
+ } else {
+ Printf(stdout, diag_eof_fmt, formatted_filename);
+ }
+ vPrintf(stdout, fmt, ap);
+ va_end(ap);
+ Delete(formatted_filename);
+}
+
diff --git a/contrib/tools/swig/Source/Swig/extend.c b/contrib/tools/swig/Source/Swig/extend.c
new file mode 100644
index 0000000000..23660c0ad8
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/extend.c
@@ -0,0 +1,141 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * extend.c
+ *
+ * Extensions support (%extend)
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+
+static Hash *extendhash = 0; /* Hash table of added methods */
+
+/* -----------------------------------------------------------------------------
+ * Swig_extend_hash()
+ *
+ * Access the extend hash
+ * ----------------------------------------------------------------------------- */
+Hash *Swig_extend_hash(void) {
+ if (!extendhash)
+ extendhash = NewHash();
+ return extendhash;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_extend_merge()
+ *
+ * Extension merge. This function is used to handle the %extend directive
+ * when it appears before a class definition. To handle this, the %extend
+ * actually needs to take precedence. Therefore, we will selectively nuke symbols
+ * from the current symbol table, replacing them with the added methods.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_extend_merge(Node *cls, Node *am) {
+ Node *n;
+ Node *csym;
+
+ n = firstChild(am);
+ while (n) {
+ String *symname;
+ if (Strcmp(nodeType(n),"constructor") == 0) {
+ symname = Getattr(n,"sym:name");
+ if (symname) {
+ if (Strcmp(symname,Getattr(n,"name")) == 0) {
+ /* If the name and the sym:name of a constructor are the same,
+ then it hasn't been renamed. However---the name of the class
+ itself might have been renamed so we need to do a consistency
+ check here */
+ if (Getattr(cls,"sym:name")) {
+ Setattr(n,"sym:name", Getattr(cls,"sym:name"));
+ }
+ }
+ }
+ }
+
+ symname = Getattr(n,"sym:name");
+ DohIncref(symname);
+ if ((symname) && (!Getattr(n,"error"))) {
+ /* Remove node from its symbol table */
+ Swig_symbol_remove(n);
+ csym = Swig_symbol_add(symname,n);
+ if (csym != n) {
+ /* Conflict with previous definition. Nuke previous definition */
+ String *e = NewStringEmpty();
+ String *en = NewStringEmpty();
+ String *ec = NewStringEmpty();
+ Printf(ec,"Identifier '%s' redefined by %%extend (ignored),",symname);
+ Printf(en,"%%extend definition of '%s'.",symname);
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(WARN_PARSE_REDEFINED,Getfile(csym),Getline(csym),"%s\n",ec);
+ Swig_warning(WARN_PARSE_REDEFINED,Getfile(n),Getline(n),"%s\n",en);
+ SWIG_WARN_NODE_END(n);
+ Printf(e,"%s:%d:%s\n%s:%d:%s\n",Getfile(csym),Getline(csym),ec,
+ Getfile(n),Getline(n),en);
+ Setattr(csym,"error",e);
+ Delete(e);
+ Delete(en);
+ Delete(ec);
+ Swig_symbol_remove(csym); /* Remove class definition */
+ Swig_symbol_add(symname,n); /* Insert extend definition */
+ }
+ }
+ n = nextSibling(n);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_extend_append_previous()
+ * ----------------------------------------------------------------------------- */
+
+void Swig_extend_append_previous(Node *cls, Node *am) {
+ Node *n, *ne;
+ Node *pe = 0;
+ Node *ae = 0;
+
+ if (!am) return;
+
+ n = firstChild(am);
+ while (n) {
+ ne = nextSibling(n);
+ set_nextSibling(n,0);
+ /* typemaps and fragments need to be prepended */
+ if (((Cmp(nodeType(n),"typemap") == 0) || (Cmp(nodeType(n),"fragment") == 0))) {
+ if (!pe) pe = Swig_cparse_new_node("extend");
+ appendChild(pe, n);
+ } else {
+ if (!ae) ae = Swig_cparse_new_node("extend");
+ appendChild(ae, n);
+ }
+ n = ne;
+ }
+ if (pe) prependChild(cls,pe);
+ if (ae) appendChild(cls,ae);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_extend_unused_check()
+ *
+ * Check for unused %extend. Special case, don't report unused
+ * extensions for templates
+ * ----------------------------------------------------------------------------- */
+
+void Swig_extend_unused_check(void) {
+ Iterator ki;
+
+ if (!extendhash) return;
+ for (ki = First(extendhash); ki.key; ki = Next(ki)) {
+ if (!Strchr(ki.key,'<')) {
+ SWIG_WARN_NODE_BEGIN(ki.item);
+ Swig_warning(WARN_PARSE_EXTEND_UNDEF,Getfile(ki.item), Getline(ki.item), "%%extend defined for an undeclared class %s.\n", SwigType_namestr(ki.key));
+ SWIG_WARN_NODE_END(ki.item);
+ }
+ }
+}
+
diff --git a/contrib/tools/swig/Source/Swig/fragment.c b/contrib/tools/swig/Source/Swig/fragment.c
new file mode 100644
index 0000000000..03b231fa13
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/fragment.c
@@ -0,0 +1,188 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * fragment.c
+ *
+ * This file manages named code fragments. Code fragments are typically
+ * used to hold helper-code that may or may not be included in the wrapper
+ * file (depending on what features are actually used in the interface).
+ *
+ * By using fragments, it's possible to greatly reduce the amount of
+ * wrapper code and to generate cleaner wrapper files.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "swigwarn.h"
+#include "cparse.h"
+
+static Hash *fragments = 0;
+static Hash *looking_fragments = 0;
+static int debug = 0;
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_fragment_register()
+ *
+ * Add a fragment. Use the original Node*, so, if something needs to be
+ * changed, lang.cxx doesn't need to be touched again.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_fragment_register(Node *fragment) {
+ if (Getattr(fragment, "emitonly")) {
+ Swig_fragment_emit(fragment);
+ return;
+ } else {
+ String *name = Copy(Getattr(fragment, "value"));
+ String *type = Getattr(fragment, "type");
+ if (type) {
+ SwigType *rtype = SwigType_typedef_resolve_all(type);
+ String *mangle = Swig_string_mangle(type);
+ Append(name, mangle);
+ Delete(mangle);
+ Delete(rtype);
+ if (debug)
+ Printf(stdout, "register fragment %s %s\n", name, type);
+ }
+ if (!fragments) {
+ fragments = NewHash();
+ }
+ if (!Getattr(fragments, name)) {
+ String *section = Copy(Getattr(fragment, "section"));
+ String *ccode = Copy(Getattr(fragment, "code"));
+ Hash *kwargs = Getattr(fragment, "kwargs");
+ Setmeta(ccode, "section", section);
+ if (kwargs) {
+ Setmeta(ccode, "kwargs", kwargs);
+ }
+ Setfile(ccode, Getfile(fragment));
+ Setline(ccode, Getline(fragment));
+ /* Replace $descriptor() macros */
+ Swig_cparse_replace_descriptor(ccode);
+ Setattr(fragments, name, ccode);
+ if (debug)
+ Printf(stdout, "registering fragment %s %s\n", name, section);
+ Delete(section);
+ Delete(ccode);
+ }
+ Delete(name);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_fragment_emit()
+ *
+ * Emit a fragment
+ * ----------------------------------------------------------------------------- */
+
+static
+char *char_index(char *str, char c) {
+ while (*str && (c != *str))
+ ++str;
+ return (c == *str) ? str : 0;
+}
+
+void Swig_fragment_emit(Node *n) {
+ String *code;
+ char *pc, *tok;
+ String *t;
+ String *mangle = 0;
+ String *name = 0;
+ String *type = 0;
+
+ name = Getattr(n, "value");
+ if (!name) {
+ name = n;
+ }
+
+ if (!fragments) {
+ Swig_warning(WARN_FRAGMENT_NOT_FOUND, Getfile(n), Getline(n), "Fragment '%s' not found.\n", name);
+ return;
+ }
+
+ type = Getattr(n, "type");
+ if (type) {
+ mangle = Swig_string_mangle(type);
+ }
+
+ if (debug)
+ Printf(stdout, "looking fragment %s %s\n", name, type);
+ t = Copy(name);
+ tok = Char(t);
+ pc = char_index(tok, ',');
+ if (pc)
+ *pc = 0;
+ while (tok) {
+ String *name = NewString(tok);
+ if (mangle)
+ Append(name, mangle);
+ if (looking_fragments && Getattr(looking_fragments, name)) {
+ return;
+ }
+ code = Getattr(fragments, name);
+ if (debug)
+ Printf(stdout, "looking subfragment %s\n", name);
+ if (code && (Strcmp(code, "ignore") != 0)) {
+ String *section = Getmeta(code, "section");
+ Hash *nn = Getmeta(code, "kwargs");
+ if (!looking_fragments)
+ looking_fragments = NewHash();
+ Setattr(looking_fragments, name, "1");
+ while (nn) {
+ if (Equal(Getattr(nn, "name"), "fragment")) {
+ if (debug)
+ Printf(stdout, "emitting fragment %s %s\n", nn, type);
+ Setfile(nn, Getfile(n));
+ Setline(nn, Getline(n));
+ Swig_fragment_emit(nn);
+ }
+ nn = nextSibling(nn);
+ }
+ if (section) {
+ File *f = Swig_filebyname(section);
+ if (!f) {
+ Swig_error(Getfile(code), Getline(code), "Bad section '%s' in %%fragment declaration for code fragment '%s'\n", section, name);
+ } else {
+ if (debug)
+ Printf(stdout, "emitting subfragment %s %s\n", name, section);
+ if (debug)
+ Printf(f, "/* begin fragment %s */\n", name);
+ Printf(f, "%s\n", code);
+ if (debug)
+ Printf(f, "/* end fragment %s */\n\n", name);
+ Setattr(fragments, name, "ignore");
+ Delattr(looking_fragments, name);
+ }
+ }
+ } else if (!code && type) {
+ SwigType *rtype = SwigType_typedef_resolve_all(type);
+ if (!Equal(type, rtype)) {
+ String *name = Copy(Getattr(n, "value"));
+ String *mangle = Swig_string_mangle(type);
+ Append(name, mangle);
+ Setfile(name, Getfile(n));
+ Setline(name, Getline(n));
+ Swig_fragment_emit(name);
+ Delete(mangle);
+ Delete(name);
+ }
+ Delete(rtype);
+ }
+
+ if (!code) {
+ Swig_warning(WARN_FRAGMENT_NOT_FOUND, Getfile(n), Getline(n), "Fragment '%s' not found.\n", name);
+ }
+ tok = pc ? pc + 1 : 0;
+ if (tok) {
+ pc = char_index(tok, ',');
+ if (pc)
+ *pc = 0;
+ }
+ Delete(name);
+ }
+ Delete(t);
+}
diff --git a/contrib/tools/swig/Source/Swig/getopt.c b/contrib/tools/swig/Source/Swig/getopt.c
new file mode 100644
index 0000000000..7791d13f72
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/getopt.c
@@ -0,0 +1,104 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * getopt.c
+ *
+ * Handles the parsing of command line options. This is particularly nasty
+ * compared to other utilities given that command line options can potentially
+ * be read by many different modules within SWIG. Thus, in order to make sure
+ * there are no unrecognized options, each module is required to "mark"
+ * the options that it uses. Afterwards, we can make a quick scan to make
+ * sure there are no unmarked options.
+ *
+ * TODO:
+ * Should have cleaner error handling in general.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+
+static char **args;
+static int numargs;
+static int *marked;
+
+/* -----------------------------------------------------------------------------
+ * Swig_init_args()
+ *
+ * Initialize the argument list handler.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_init_args(int argc, char **argv) {
+ assert(argc > 0);
+ assert(argv);
+
+ numargs = argc;
+ args = argv;
+ marked = (int *) Calloc(numargs, sizeof(int));
+ marked[0] = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_mark_arg()
+ *
+ * Marks an argument as being parsed.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_mark_arg(int n) {
+ assert(marked);
+ assert((n >= 0) && (n < numargs));
+ marked[n] = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_check_marked()
+ *
+ * Checks to see if argument has been picked up.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_check_marked(int n) {
+ assert((n >= 0) && (n < numargs));
+ return marked[n];
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_check_options()
+ *
+ * Checkers for unprocessed command line options and errors.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_check_options(int check_input) {
+ int error = 0;
+ int i;
+ int max = check_input ? numargs - 1 : numargs;
+ assert(marked);
+ for (i = 1; i < max; i++) {
+ if (!marked[i]) {
+ Printf(stderr, "swig error : Unrecognized option %s\n", args[i]);
+ error = 1;
+ }
+ }
+ if (error) {
+ Printf(stderr, "Use 'swig -help' for available options.\n");
+ Exit(EXIT_FAILURE);
+ }
+ if (check_input && marked[numargs - 1]) {
+ Printf(stderr, "Must specify an input file. Use -help for available options.\n");
+ Exit(EXIT_FAILURE);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_arg_error()
+ *
+ * Generates a generic error message and exits.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_arg_error(void) {
+ Printf(stderr, "SWIG : Unable to parse command line options.\n");
+ Printf(stderr, "Use 'swig -help' for available options.\n");
+ Exit(EXIT_FAILURE);
+}
diff --git a/contrib/tools/swig/Source/Swig/include.c b/contrib/tools/swig/Source/Swig/include.c
new file mode 100644
index 0000000000..c153ac9b7a
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/include.c
@@ -0,0 +1,377 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * include.c
+ *
+ * The functions in this file are used to manage files in the SWIG library.
+ * General purpose functions for opening, including, and retrieving pathnames
+ * are provided.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+
+static List *directories = 0; /* List of include directories */
+static String *lastpath = 0; /* Last file that was included */
+static List *pdirectories = 0; /* List of pushed directories */
+static int dopush = 1; /* Whether to push directories */
+static int file_debug = 0;
+
+/* This functions determine whether to push/pop dirs in the preprocessor */
+void Swig_set_push_dir(int push) {
+ dopush = push;
+}
+
+int Swig_get_push_dir(void) {
+ return dopush;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_add_directory()
+ *
+ * Adds a directory to the SWIG search path.
+ * ----------------------------------------------------------------------------- */
+
+List *Swig_add_directory(const_String_or_char_ptr dirname) {
+ String *adirname;
+ if (!directories)
+ directories = NewList();
+ assert(directories);
+ if (dirname) {
+ adirname = NewString(dirname);
+ Append(directories,adirname);
+ Delete(adirname);
+ }
+ return directories;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_push_directory()
+ *
+ * Inserts a directory at the front of the SWIG search path. This is used by
+ * the preprocessor to grab files in the same directory as other included files.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_push_directory(const_String_or_char_ptr dirname) {
+ String *pdirname;
+ if (!Swig_get_push_dir())
+ return;
+ if (!pdirectories)
+ pdirectories = NewList();
+ assert(pdirectories);
+ pdirname = NewString(dirname);
+ assert(pdirname);
+ Insert(pdirectories,0,pdirname);
+ Delete(pdirname);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_pop_directory()
+ *
+ * Pops a directory off the front of the SWIG search path. This is used by
+ * the preprocessor.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_pop_directory(void) {
+ if (!Swig_get_push_dir())
+ return;
+ if (!pdirectories)
+ return;
+ Delitem(pdirectories, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_last_file()
+ *
+ * Returns the full pathname of the last file opened.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_last_file(void) {
+ assert(lastpath);
+ return lastpath;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_search_path_any()
+ *
+ * Returns a list of the current search paths.
+ * ----------------------------------------------------------------------------- */
+
+static List *Swig_search_path_any(int syspath) {
+ String *filename;
+ List *slist;
+ int i, ilen;
+
+ slist = NewList();
+ assert(slist);
+ filename = NewStringEmpty();
+ assert(filename);
+ Printf(filename, ".%s", SWIG_FILE_DELIMITER);
+ Append(slist, filename);
+ Delete(filename);
+
+ /* If there are any pushed directories. Add them first */
+ if (pdirectories) {
+ ilen = Len(pdirectories);
+ for (i = 0; i < ilen; i++) {
+ filename = NewString(Getitem(pdirectories,i));
+ Append(filename,SWIG_FILE_DELIMITER);
+ Append(slist,filename);
+ Delete(filename);
+ }
+ }
+ /* Add system directories next */
+ ilen = Len(directories);
+ for (i = 0; i < ilen; i++) {
+ filename = NewString(Getitem(directories,i));
+ Append(filename,SWIG_FILE_DELIMITER);
+ if (syspath) {
+ /* If doing a system include, put the system directories first */
+ Insert(slist,i,filename);
+ } else {
+ /* Otherwise, just put the system directories after the pushed directories (if any) */
+ Append(slist,filename);
+ }
+ Delete(filename);
+ }
+ return slist;
+}
+
+List *Swig_search_path(void) {
+ return Swig_search_path_any(0);
+}
+
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_open()
+ *
+ * open a file, optionally looking for it in the include path. Returns an open
+ * FILE * on success.
+ * ----------------------------------------------------------------------------- */
+
+static FILE *Swig_open_file(const_String_or_char_ptr name, int sysfile, int use_include_path) {
+ FILE *f;
+ String *filename;
+ List *spath = 0;
+ char *cname;
+ int i, ilen, nbytes;
+ char bom[3];
+
+ if (!directories)
+ directories = NewList();
+ assert(directories);
+
+ cname = Char(name);
+ filename = NewString(cname);
+ assert(filename);
+ if (file_debug) {
+ Printf(stdout, " Open: %s\n", filename);
+ }
+ f = fopen(Char(filename), "r");
+ if (!f && use_include_path) {
+ spath = Swig_search_path_any(sysfile);
+ ilen = Len(spath);
+ for (i = 0; i < ilen; i++) {
+ Clear(filename);
+ Printf(filename, "%s%s", Getitem(spath, i), cname);
+ f = fopen(Char(filename), "r");
+ if (f)
+ break;
+ }
+ Delete(spath);
+ }
+ if (f) {
+ Delete(lastpath);
+ lastpath = filename;
+
+ /* Skip the UTF-8 BOM if it's present */
+ nbytes = (int)fread(bom, 1, 3, f);
+ if (nbytes == 3 && bom[0] == (char)0xEF && bom[1] == (char)0xBB && bom[2] == (char)0xBF) {
+ /* skip */
+ } else {
+ fseek(f, 0, SEEK_SET);
+ }
+ }
+ return f;
+}
+
+/* Open a file - searching the include paths to find it */
+FILE *Swig_include_open(const_String_or_char_ptr name) {
+ return Swig_open_file(name, 0, 1);
+}
+
+/* Open a file - does not use include paths to find it */
+FILE *Swig_open(const_String_or_char_ptr name) {
+ return Swig_open_file(name, 0, 0);
+}
+
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_read_file()
+ *
+ * Reads data from an open FILE * and returns it as a string.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_read_file(FILE *f) {
+ int len;
+ char buffer[4096];
+ String *str = NewStringEmpty();
+
+ assert(str);
+ while (fgets(buffer, 4095, f)) {
+ Append(str, buffer);
+ }
+ len = Len(str);
+ /* Add a newline if not present on last line -- the preprocessor seems to
+ * rely on \n and not EOF terminating lines */
+ if (len) {
+ char *cstr = Char(str);
+ if (cstr[len - 1] != '\n') {
+ Append(str, "\n");
+ }
+ }
+ return str;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_include()
+ *
+ * Opens a file and returns it as a string.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_include_any(const_String_or_char_ptr name, int sysfile) {
+ FILE *f;
+ String *str;
+ String *file;
+
+ f = Swig_open_file(name, sysfile, 1);
+ if (!f)
+ return 0;
+ str = Swig_read_file(f);
+ fclose(f);
+ Seek(str, 0, SEEK_SET);
+ file = Copy(Swig_last_file());
+ Setfile(str, file);
+ Delete(file);
+ Setline(str, 1);
+ return str;
+}
+
+String *Swig_include(const_String_or_char_ptr name) {
+ return Swig_include_any(name, 0);
+}
+
+String *Swig_include_sys(const_String_or_char_ptr name) {
+ return Swig_include_any(name, 1);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_insert_file()
+ *
+ * Copies the contents of a file into another file
+ * ----------------------------------------------------------------------------- */
+
+int Swig_insert_file(const_String_or_char_ptr filename, File *outfile) {
+ char buffer[4096];
+ int nbytes;
+ FILE *f = Swig_include_open(filename);
+
+ if (!f)
+ return -1;
+ while ((nbytes = Read(f, buffer, 4096)) > 0) {
+ Write(outfile, buffer, nbytes);
+ }
+ fclose(f);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_register_filebyname()
+ *
+ * Register a "named" file with the core. Named files can become targets
+ * for %insert directives and other SWIG operations. This function takes
+ * the place of the f_header, f_wrapper, f_init, and other global variables
+ * in SWIG1.1
+ * ----------------------------------------------------------------------------- */
+
+static Hash *named_files = 0;
+
+void Swig_register_filebyname(const_String_or_char_ptr filename, File *outfile) {
+ if (!named_files)
+ named_files = NewHash();
+ Setattr(named_files, filename, outfile);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_filebyname()
+ *
+ * Get a named file
+ * ----------------------------------------------------------------------------- */
+
+File *Swig_filebyname(const_String_or_char_ptr filename) {
+ if (!named_files)
+ return 0;
+ return Getattr(named_files, filename);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_file_extension()
+ *
+ * Returns the extension of a file
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_file_extension(const_String_or_char_ptr filename) {
+ String *name = Swig_file_filename(filename);
+ const char *c = strrchr(Char(name), '.');
+ String *extension = c ? NewString(c) : NewString("");
+ Delete(name);
+ return extension;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_file_basename()
+ *
+ * Returns the filename with the extension removed.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_file_basename(const_String_or_char_ptr filename) {
+ String *extension = Swig_file_extension(filename);
+ String *basename = NewStringWithSize(filename, Len(filename) - Len(extension));
+ Delete(extension);
+ return basename;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_file_filename()
+ *
+ * Return the file name with any leading path stripped off
+ * ----------------------------------------------------------------------------- */
+String *Swig_file_filename(const_String_or_char_ptr filename) {
+ const char *delim = SWIG_FILE_DELIMITER;
+ const char *c = strrchr(Char(filename), *delim);
+ return c ? NewString(c + 1) : NewString(filename);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_file_dirname()
+ *
+ * Return the name of the directory associated with a file
+ * ----------------------------------------------------------------------------- */
+String *Swig_file_dirname(const_String_or_char_ptr filename) {
+ const char *delim = SWIG_FILE_DELIMITER;
+ const char *c = strrchr(Char(filename), *delim);
+ return c ? NewStringWithSize(filename, (int)(c - Char(filename) + 1)) : NewString("");
+}
+
+/*
+ * Swig_file_debug()
+ */
+void Swig_file_debug_set(void) {
+ file_debug = 1;
+}
diff --git a/contrib/tools/swig/Source/Swig/misc.c b/contrib/tools/swig/Source/Swig/misc.c
new file mode 100644
index 0000000000..7d1119c5e2
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/misc.c
@@ -0,0 +1,1569 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * misc.c
+ *
+ * Miscellaneous functions that don't really fit anywhere else.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <errno.h>
+#include <ctype.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#ifndef S_ISDIR
+#define S_ISDIR(mode) (((mode) & S_IFDIR) == S_IFDIR)
+#endif
+#endif
+
+static char *fake_version = 0;
+
+/* -----------------------------------------------------------------------------
+ * Swig_copy_string()
+ *
+ * Duplicate a NULL-terminate string given as a char *.
+ * ----------------------------------------------------------------------------- */
+
+char *Swig_copy_string(const char *s) {
+ char *c = 0;
+ if (s) {
+ c = (char *) Malloc(strlen(s) + 1);
+ strcpy(c, s);
+ }
+ return c;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_set_fakeversion()
+ *
+ * Version string override
+ * ----------------------------------------------------------------------------- */
+
+void Swig_set_fakeversion(const char *version) {
+ fake_version = Swig_copy_string(version);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_package_version()
+ *
+ * Return the package string containing the version number
+ * ----------------------------------------------------------------------------- */
+
+const char *Swig_package_version(void) {
+ return fake_version ? fake_version : PACKAGE_VERSION;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_package_version_hex()
+ *
+ * Return the package version in hex format "0xAABBCC" such as "0x040200" for 4.2.0
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_package_version_hex(void) {
+ String *package_version = NewString(Swig_package_version());
+ char *token = strtok(Char(package_version), ".");
+ String *vers = NewString("SWIG_VERSION 0x");
+ int count = 0;
+ while (token) {
+ int len = (int)strlen(token);
+ assert(len == 1 || len == 2);
+ Printf(vers, "%s%s", (len == 1) ? "0" : "", token);
+ token = strtok(NULL, ".");
+ count++;
+ }
+ Delete(package_version);
+ assert(count == 3); /* Check version format is correct */
+ return vers;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_obligatory_macros()
+ *
+ * Generates the SWIG_VERSION and SWIGXXX macros where XXX is the target language
+ * name (must be provided uppercase).
+ * ----------------------------------------------------------------------------- */
+
+void Swig_obligatory_macros(String *f_runtime, const char *language) {
+ String *version_hex = Swig_package_version_hex();
+ Printf(f_runtime, "\n\n");
+ Printf(f_runtime, "#define %s\n", version_hex);
+ Printf(f_runtime, "#define SWIG%s\n", language);
+ Delete(version_hex);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_banner()
+ *
+ * Emits the SWIG identifying banner for the C/C++ wrapper file.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_banner(File *f) {
+ Printf(f, "/* ----------------------------------------------------------------------------\n");
+ Swig_banner_target_lang(f, " *");
+ Printf(f, " * ----------------------------------------------------------------------------- */\n");
+
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_banner_target_lang()
+ *
+ * Emits a SWIG identifying banner in the target language
+ * ----------------------------------------------------------------------------- */
+
+void Swig_banner_target_lang(File *f, const_String_or_char_ptr commentchar) {
+ Printf(f, "%s This file was automatically generated by SWIG (https://www.swig.org).\n", commentchar);
+ Printf(f, "%s Version %s\n", commentchar, Swig_package_version());
+ Printf(f, "%s\n", commentchar);
+ Printf(f, "%s Do not make changes to this file unless you know what you are doing - modify\n", commentchar);
+ Printf(f, "%s the SWIG interface file instead.\n", commentchar);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_strip_c_comments()
+ *
+ * Return a new string with C comments stripped from the input string. NULL is
+ * returned if there aren't any comments.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_strip_c_comments(const String *s) {
+ const char *c = Char(s);
+ const char *comment_begin = 0;
+ const char *comment_end = 0;
+ String *stripped = 0;
+
+ while (*c) {
+ if (!comment_begin && *c == '/') {
+ ++c;
+ if (!*c)
+ break;
+ if (*c == '*')
+ comment_begin = c-1;
+ } else if (comment_begin && !comment_end && *c == '*') {
+ ++c;
+ if (*c == '/') {
+ comment_end = c;
+ break;
+ }
+ }
+ ++c;
+ }
+
+ if (comment_begin && comment_end) {
+ int size = (int)(comment_begin - Char(s));
+ String *stripmore = 0;
+ stripped = NewStringWithSize(s, size);
+ Printv(stripped, comment_end + 1, NIL);
+ do {
+ stripmore = Swig_strip_c_comments(stripped);
+ if (stripmore) {
+ Delete(stripped);
+ stripped = stripmore;
+ }
+ } while (stripmore);
+ }
+ return stripped;
+}
+
+/* -----------------------------------------------------------------------------
+ * is_directory()
+ * ----------------------------------------------------------------------------- */
+static int is_directory(String *directory) {
+ int last = Len(directory) - 1;
+ int statres;
+ struct stat st;
+ char *dir = Char(directory);
+ if (dir[last] == SWIG_FILE_DELIMITER[0]) {
+ /* remove trailing slash - can cause S_ISDIR to fail on Windows, at least */
+ dir[last] = 0;
+ statres = stat(dir, &st);
+ dir[last] = SWIG_FILE_DELIMITER[0];
+ } else {
+ statres = stat(dir, &st);
+ }
+ return (statres == 0 && S_ISDIR(st.st_mode));
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_new_subdirectory()
+ *
+ * Create the subdirectory only if the basedirectory already exists as a directory.
+ * basedirectory can be empty to indicate current directory but not NULL.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_new_subdirectory(String *basedirectory, String *subdirectory) {
+ String *error = 0;
+ int current_directory = Len(basedirectory) == 0;
+
+ if (current_directory || is_directory(basedirectory)) {
+ Iterator it;
+ String *dir = NewString(basedirectory);
+ List *subdirs = Split(subdirectory, SWIG_FILE_DELIMITER[0], INT_MAX);
+
+ for (it = First(subdirs); it.item; it = Next(it)) {
+ int result;
+ String *subdirectory = it.item;
+ Printf(dir, "%s", subdirectory);
+#ifdef _WIN32
+ result = _mkdir(Char(dir));
+#else
+ result = mkdir(Char(dir), 0777);
+#endif
+ if (result != 0 && errno != EEXIST) {
+ error = NewStringf("Cannot create directory %s: %s", dir, strerror(errno));
+ break;
+ }
+ if (!is_directory(dir)) {
+ error = NewStringf("Cannot create directory %s: it may already exist but not be a directory", dir);
+ break;
+ }
+ Printf(dir, SWIG_FILE_DELIMITER);
+ }
+ } else {
+ error = NewStringf("Cannot create subdirectory %s under the base directory %s. Either the base does not exist as a directory or it is not readable.", subdirectory, basedirectory);
+ }
+ return error;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_filename_correct()
+ *
+ * Corrects filename paths by removing duplicate delimiters and on non-unix
+ * systems use the correct delimiter across the whole name.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_filename_correct(String *filename) {
+ int network_path = 0;
+ if (Len(filename) >= 2) {
+ const char *fname = Char(filename);
+ if (fname[0] == '\\' && fname[1] == '\\')
+ network_path = 1;
+ if (fname[0] == '/' && fname[1] == '/')
+ network_path = 1;
+ }
+#if defined(_WIN32)
+ /* accept Unix path separator on non-Unix systems */
+ Replaceall(filename, "/", SWIG_FILE_DELIMITER);
+#endif
+#if defined(__CYGWIN__)
+ /* accept Windows path separator in addition to Unix path separator */
+ Replaceall(filename, "\\", SWIG_FILE_DELIMITER);
+#endif
+ /* remove all duplicate file name delimiters */
+ while (Replaceall(filename, SWIG_FILE_DELIMITER SWIG_FILE_DELIMITER, SWIG_FILE_DELIMITER)) {
+ }
+ /* Network paths can start with a double slash on Windows - unremove the duplicate slash we just removed */
+ if (network_path)
+ Insert(filename, 0, SWIG_FILE_DELIMITER);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_filename_escape()
+ *
+ * Escapes backslashes in filename - for Windows
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_filename_escape(String *filename) {
+ String *adjusted_filename = Copy(filename);
+ Swig_filename_correct(adjusted_filename);
+#if defined(_WIN32) /* Note not on Cygwin else filename is displayed with double '/' */
+ Replaceall(adjusted_filename, "\\", "\\\\");
+#endif
+ return adjusted_filename;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_filename_escape()
+ *
+ * Escapes spaces in filename - for Makefiles
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_filename_escape_space(String *filename) {
+ String *adjusted_filename = Copy(filename);
+ Swig_filename_correct(adjusted_filename);
+ Replaceall(adjusted_filename, " ", "\\ ");
+ return adjusted_filename;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_filename_unescape()
+ *
+ * Remove double backslash escaping in filename - for Windows
+ * ----------------------------------------------------------------------------- */
+
+void Swig_filename_unescape(String *filename) {
+ (void)filename;
+#if defined(_WIN32)
+ Replaceall(filename, "\\\\", "\\");
+#endif
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_storage_isextern()
+ *
+ * Determine if the storage class specifier is extern (but not externc)
+ * ----------------------------------------------------------------------------- */
+
+int Swig_storage_isextern(Node *n) {
+ const String *storage = Getattr(n, "storage");
+ return storage ? Strcmp(storage, "extern") == 0 || Strncmp(storage, "extern ", 7) == 0 : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_storage_isexternc()
+ *
+ * Determine if the storage class specifier is externc (but not plain extern)
+ * ----------------------------------------------------------------------------- */
+
+int Swig_storage_isexternc(Node *n) {
+ const String *storage = Getattr(n, "storage");
+ return storage ? Strcmp(storage, "externc") == 0 || Strncmp(storage, "externc ", 8) == 0 : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_storage_isstatic_custom()
+ *
+ * Determine if the storage class specifier is static
+ * ----------------------------------------------------------------------------- */
+
+int Swig_storage_isstatic_custom(Node *n, const_String_or_char_ptr storage_name) {
+ const String *storage = Getattr(n, storage_name);
+ return storage ? Strncmp(storage, "static", 6) == 0 : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_storage_isstatic()
+ *
+ * Determine if the storage class specifier is static
+ * ----------------------------------------------------------------------------- */
+
+int Swig_storage_isstatic(Node *n) {
+ return Swig_storage_isstatic_custom(n, "storage");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_escape()
+ *
+ * Takes a string object and produces a string with escape codes added to it.
+ * Octal escaping is used.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_escape(String *s) {
+ String *ns;
+ int c;
+ ns = NewStringEmpty();
+
+ while ((c = Getc(s)) != EOF) {
+ if (c == '\n') {
+ Printf(ns, "\\n");
+ } else if (c == '\r') {
+ Printf(ns, "\\r");
+ } else if (c == '\t') {
+ Printf(ns, "\\t");
+ } else if (c == '\\') {
+ Printf(ns, "\\\\");
+ } else if (c == '\'') {
+ Printf(ns, "\\'");
+ } else if (c == '\"') {
+ Printf(ns, "\\\"");
+ } else if (c == ' ') {
+ Putc(c, ns);
+ } else if (!isgraph(c)) {
+ if (c < 0)
+ c += UCHAR_MAX + 1;
+ Printf(ns, "\\%o", c);
+ } else {
+ Putc(c, ns);
+ }
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_hexescape()
+ *
+ * Takes a string object and produces a string with escape codes added to it.
+ * Hex escaping is used.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_hexescape(String *s) {
+ String *ns;
+ int c;
+ ns = NewStringEmpty();
+
+ while ((c = Getc(s)) != EOF) {
+ if (c == '\n') {
+ Printf(ns, "\\n");
+ } else if (c == '\r') {
+ Printf(ns, "\\r");
+ } else if (c == '\t') {
+ Printf(ns, "\\t");
+ } else if (c == '\\') {
+ Printf(ns, "\\\\");
+ } else if (c == '\'') {
+ Printf(ns, "\\'");
+ } else if (c == '\"') {
+ Printf(ns, "\\\"");
+ } else if (c == ' ') {
+ Putc(c, ns);
+ } else if (!isgraph(c)) {
+ if (c < 0)
+ c += UCHAR_MAX + 1;
+ Printf(ns, "\\x%X", c);
+ } else {
+ Putc(c, ns);
+ }
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_upper()
+ *
+ * Takes a string object and returns a copy that is uppercase
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_upper(String *s) {
+ String *ns;
+ int c;
+ ns = NewStringEmpty();
+
+ Seek(s, 0, SEEK_SET);
+ while ((c = Getc(s)) != EOF) {
+ Putc(toupper(c), ns);
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_lower()
+ *
+ * Takes a string object and returns a copy that is lowercase
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_lower(String *s) {
+ String *ns;
+ int c;
+ ns = NewStringEmpty();
+
+ Seek(s, 0, SEEK_SET);
+ while ((c = Getc(s)) != EOF) {
+ Putc(tolower(c), ns);
+ }
+ return ns;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_title()
+ *
+ * Takes a string object and returns a copy that is lowercase with first letter
+ * capitalized
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_title(String *s) {
+ String *ns;
+ int first = 1;
+ int c;
+ ns = NewStringEmpty();
+
+ Seek(s, 0, SEEK_SET);
+ while ((c = Getc(s)) != EOF) {
+ Putc(first ? toupper(c) : tolower(c), ns);
+ first = 0;
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_ccase()
+ *
+ * Takes a string object and returns a copy that is lowercase with the first
+ * letter capitalized and the one following '_', which are removed.
+ *
+ * camel_case -> CamelCase
+ * camelCase -> CamelCase
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_ccase(String *s) {
+ String *ns;
+ int first = 1;
+ int c;
+ ns = NewStringEmpty();
+
+ Seek(s, 0, SEEK_SET);
+ while ((c = Getc(s)) != EOF) {
+ if (c == '_') {
+ first = 1;
+ continue;
+ }
+ Putc(first ? toupper(c) : c, ns);
+ first = 0;
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_lccase()
+ *
+ * Takes a string object and returns a copy with the character after
+ * each '_' capitalised, and the '_' removed. The first character is
+ * also forced to lowercase.
+ *
+ * camel_case -> camelCase
+ * CamelCase -> camelCase
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_lccase(String *s) {
+ String *ns;
+ int first = 1;
+ int after_underscore = 0;
+ int c;
+ ns = NewStringEmpty();
+
+ Seek(s, 0, SEEK_SET);
+ while ((c = Getc(s)) != EOF) {
+ if (c == '_') {
+ after_underscore = 1;
+ continue;
+ }
+ if (first) {
+ Putc(tolower(c), ns);
+ first = 0;
+ } else {
+ Putc(after_underscore ? toupper(c) : c, ns);
+ }
+ after_underscore = 0;
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_ucase()
+ *
+ * This is the reverse case of ccase, ie
+ *
+ * CamelCase -> camel_case
+ * get2D -> get_2d
+ * asFloat2 -> as_float2
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_ucase(String *s) {
+ String *ns;
+ int c;
+ int lastC = 0;
+ int nextC = 0;
+ int underscore = 0;
+ ns = NewStringEmpty();
+
+ /* We insert a underscore when:
+ 1. Lower case char followed by upper case char
+ getFoo > get_foo; getFOo > get_foo; GETFOO > getfoo
+ 2. Number preceded by char and not end of string
+ get2D > get_2d; get22D > get_22d; GET2D > get_2d
+ but:
+ asFloat2 > as_float2
+ */
+
+ Seek(s, 0, SEEK_SET);
+
+ while ((c = Getc(s)) != EOF) {
+ nextC = Getc(s); Ungetc(nextC, s);
+ if (isdigit(c) && isalpha(lastC) && nextC != EOF)
+ underscore = 1;
+ else if (isupper(c) && isalpha(lastC) && !isupper(lastC))
+ underscore = 1;
+
+ lastC = c;
+
+ if (underscore) {
+ Putc('_', ns);
+ underscore = 0;
+ }
+
+ Putc(tolower(c), ns);
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_first_upper()
+ *
+ * Make the first character in the string uppercase, leave all the
+ * rest the same. This is used by the Ruby module to provide backwards
+ * compatibility with the old way of naming classes and constants. For
+ * more info see the Ruby documentation.
+ *
+ * firstUpper -> FirstUpper
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_first_upper(String *s) {
+ String *ns = NewStringEmpty();
+ char *cs = Char(s);
+ if (cs && cs[0] != 0) {
+ Putc(toupper((int)cs[0]), ns);
+ Append(ns, cs + 1);
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_first_lower()
+ *
+ * Make the first character in the string lowercase, leave all the
+ * rest the same. This is used by the Ruby module to provide backwards
+ * compatibility with the old way of naming classes and constants. For
+ * more info see the Ruby documentation.
+ *
+ * firstLower -> FirstLower
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_first_lower(String *s) {
+ String *ns = NewStringEmpty();
+ char *cs = Char(s);
+ if (cs && cs[0] != 0) {
+ Putc(tolower((int)cs[0]), ns);
+ Append(ns, cs + 1);
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_schemify()
+ *
+ * Replace underscores with dashes, to make identifiers look nice to Schemers.
+ *
+ * under_scores -> under-scores
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_schemify(String *s) {
+ String *ns = NewString(s);
+ Replaceall(ns, "_", "-");
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_typecode()
+ *
+ * Takes a string with possible type-escapes in it and replaces them with
+ * real C datatypes.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_typecode(String *s) {
+ String *ns;
+ int c;
+ String *tc;
+ ns = NewStringEmpty();
+ while ((c = Getc(s)) != EOF) {
+ if (c == '`') {
+ String *str = 0;
+ tc = NewStringEmpty();
+ while ((c = Getc(s)) != EOF) {
+ if (c == '`')
+ break;
+ Putc(c, tc);
+ }
+ str = SwigType_str(tc, 0);
+ Append(ns, str);
+ Delete(str);
+ } else {
+ Putc(c, ns);
+ if (c == '\'') {
+ while ((c = Getc(s)) != EOF) {
+ Putc(c, ns);
+ if (c == '\'')
+ break;
+ if (c == '\\') {
+ c = Getc(s);
+ Putc(c, ns);
+ }
+ }
+ } else if (c == '\"') {
+ while ((c = Getc(s)) != EOF) {
+ Putc(c, ns);
+ if (c == '\"')
+ break;
+ if (c == '\\') {
+ c = Getc(s);
+ Putc(c, ns);
+ }
+ }
+ }
+ }
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_mangle()
+ *
+ * Take a string and mangle it by stripping all non-valid C identifier
+ * characters.
+ *
+ * This routine skips unnecessary blank spaces, therefore mangling
+ * 'char *' and 'char*', 'std::pair<int, int >' and
+ * 'std::pair<int,int>', produce the same result.
+ *
+ * However, note that 'long long' and 'long_long' produce different
+ * mangled strings.
+ *
+ * The mangling method still is not 'perfect', for example std::pair and
+ * std_pair return the same mangling. This is just a little better
+ * than before, but it seems to be enough for most of the purposes.
+ *
+ * Having a perfect mangling will break some examples and code which
+ * assume, for example, that A::get_value will be mangled as
+ * A_get_value.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_mangle(const String *s) {
+#if 0
+ /* old mangling, not suitable for using in macros */
+ String *t = Copy(s);
+ char *c = Char(t);
+ while (*c) {
+ if (!isalnum(*c))
+ *c = '_';
+ c++;
+ }
+ return t;
+#else
+ String *result = NewStringEmpty();
+ int space = 0;
+ int state = 0;
+ char *pc, *cb;
+ String *b = Copy(s);
+ if (SwigType_istemplate(b)) {
+ String *st = Swig_symbol_template_deftype(b, 0);
+ String *sq = Swig_symbol_type_qualify(st, 0);
+ String *t = SwigType_namestr(sq);
+ Delete(st);
+ Delete(sq);
+ Delete(b);
+ b = t;
+ }
+ pc = cb = Char(b);
+ while (*pc) {
+ char c = *pc;
+ if (isalnum((int) c) || (c == '_')) {
+ state = 1;
+ if (space && (space == state)) {
+ Append(result, "_SS_");
+ }
+ space = 0;
+ Printf(result, "%c", (int) c);
+
+ } else {
+ if (isspace((int) c)) {
+ space = state;
+ ++pc;
+ continue;
+ } else {
+ state = 3;
+ space = 0;
+ }
+ switch (c) {
+ case '.':
+ if ((cb != pc) && (*(pc - 1) == 'p')) {
+ Append(result, "_");
+ ++pc;
+ continue;
+ } else {
+ c = 'f';
+ }
+ break;
+ case ':':
+ if (*(pc + 1) == ':') {
+ Append(result, "_");
+ ++pc;
+ ++pc;
+ continue;
+ }
+ break;
+ case '*':
+ c = 'm';
+ break;
+ case '&':
+ c = 'A';
+ break;
+ case '<':
+ c = 'l';
+ break;
+ case '>':
+ c = 'g';
+ break;
+ case '=':
+ c = 'e';
+ break;
+ case ',':
+ c = 'c';
+ break;
+ case '(':
+ c = 'p';
+ break;
+ case ')':
+ c = 'P';
+ break;
+ case '[':
+ c = 'b';
+ break;
+ case ']':
+ c = 'B';
+ break;
+ case '^':
+ c = 'x';
+ break;
+ case '|':
+ c = 'o';
+ break;
+ case '~':
+ c = 'n';
+ break;
+ case '!':
+ c = 'N';
+ break;
+ case '%':
+ c = 'M';
+ break;
+ case '?':
+ c = 'q';
+ break;
+ case '+':
+ c = 'a';
+ break;
+ case '-':
+ c = 's';
+ break;
+ case '/':
+ c = 'd';
+ break;
+ default:
+ break;
+ }
+ if (isalpha((int) c)) {
+ Printf(result, "_S%c_", (int) c);
+ } else {
+ Printf(result, "_S%02X_", (int) c);
+ }
+ }
+ ++pc;
+ }
+ Delete(b);
+ return result;
+#endif
+}
+
+String *Swig_string_emangle(String *s) {
+ return Swig_string_mangle(s);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_split()
+ *
+ * Take a qualified name like "A::B::C" and splits off the last name.
+ * In this case, returns "C" as last and "A::B" as prefix.
+ * Always returns non NULL for last, but prefix may be NULL if there is no prefix.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
+ char *tmp = Char(s);
+ char *c = tmp;
+ char *cc = c;
+ char *co = 0;
+ if (!strstr(c, "::")) {
+ *rprefix = 0;
+ *rlast = Copy(s);
+ }
+
+ co = strstr(cc, "operator ");
+ if (co) {
+ if (co == cc) {
+ *rprefix = 0;
+ *rlast = Copy(s);
+ return;
+ } else {
+ *rprefix = NewStringWithSize(cc, (int)(co - cc - 2));
+ *rlast = NewString(co);
+ return;
+ }
+ }
+ while (*c) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ cc = c;
+ c += 2;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+
+ if (cc != tmp) {
+ *rprefix = NewStringWithSize(tmp, (int)(cc - tmp));
+ *rlast = NewString(cc + 2);
+ return;
+ } else {
+ *rprefix = 0;
+ *rlast = Copy(s);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_prefix()
+ *
+ * Take a qualified name like "A::B::C" and return the scope name.
+ * In this case, "A::B". Returns NULL if there is no base.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_scopename_prefix(const String *s) {
+ char *tmp = Char(s);
+ char *c = tmp;
+ char *cc = c;
+ char *co = 0;
+ if (!strstr(c, "::"))
+ return 0;
+ co = strstr(cc, "operator ");
+
+ if (co) {
+ if (co == cc) {
+ return 0;
+ } else {
+ String *prefix = NewStringWithSize(cc, (int)(co - cc - 2));
+ return prefix;
+ }
+ }
+ while (*c) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ cc = c;
+ c += 2;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+
+ if (cc != tmp) {
+ return NewStringWithSize(tmp, (int)(cc - tmp));
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_last()
+ *
+ * Take a qualified name like "A::B::C" and returns the last. In this
+ * case, "C".
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_scopename_last(const String *s) {
+ char *tmp = Char(s);
+ char *c = tmp;
+ char *cc = c;
+ char *co = 0;
+ if (!strstr(c, "::"))
+ return NewString(s);
+
+ co = strstr(cc, "operator ");
+ if (co) {
+ return NewString(co);
+ }
+
+
+ while (*c) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ c += 2;
+ cc = c;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+ return NewString(cc);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_first()
+ *
+ * Take a qualified name like "A::B::C" and returns the first scope name.
+ * In this case, "A". Returns NULL if there is no base.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_scopename_first(const String *s) {
+ char *tmp = Char(s);
+ char *c = tmp;
+ char *co = 0;
+ if (!strstr(c, "::"))
+ return 0;
+
+ co = strstr(c, "operator ");
+ if (co) {
+ if (co == c) {
+ return 0;
+ }
+ } else {
+ co = c + Len(s);
+ }
+
+ while (*c && (c != co)) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ break;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+ if (*c && (c != tmp)) {
+ return NewStringWithSize(tmp, (int)(c - tmp));
+ } else {
+ return 0;
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_suffix()
+ *
+ * Take a qualified name like "A::B::C" and returns the suffix.
+ * In this case, "B::C". Returns NULL if there is no suffix.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_scopename_suffix(const String *s) {
+ char *tmp = Char(s);
+ char *c = tmp;
+ char *co = 0;
+ if (!strstr(c, "::"))
+ return 0;
+
+ co = strstr(c, "operator ");
+ if (co) {
+ if (co == c)
+ return 0;
+ }
+ while (*c) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ break;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+ if (*c && (c != tmp)) {
+ return NewString(c + 2);
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_tolist()
+ *
+ * Take a qualified scope name like "A::B::C" and convert it to a list.
+ * In this case, return a list of 3 elements "A", "B", "C".
+ * Returns an empty list if the input is empty.
+ * ----------------------------------------------------------------------------- */
+
+List *Swig_scopename_tolist(const String *s) {
+ List *scopes = NewList();
+ String *name = Len(s) == 0 ? 0 : NewString(s);
+
+ while (name) {
+ String *last = 0;
+ String *prefix = 0;
+ Swig_scopename_split(name, &prefix, &last);
+ Insert(scopes, 0, last);
+ Delete(last);
+ Delete(name);
+ name = prefix;
+ }
+ Delete(name);
+ return scopes;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_check()
+ *
+ * Checks to see if a name is qualified with a scope name, examples:
+ * foo -> 0
+ * ::foo -> 1
+ * foo::bar -> 1
+ * foo< ::bar > -> 0
+ * ----------------------------------------------------------------------------- */
+
+int Swig_scopename_check(const String *s) {
+ char *c = Char(s);
+ char *co = strstr(c, "operator ");
+
+ if (co) {
+ if (co == c)
+ return 0;
+ }
+ if (!strstr(c, "::"))
+ return 0;
+ while (*c) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ return 1;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_command()
+ *
+ * Feature removed in SWIG 4.1.0.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_command(String *s) {
+ Swig_error("SWIG", Getline(s), "Command encoder no longer supported - use regex encoder instead.\n");
+ Exit(EXIT_FAILURE);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_strip()
+ *
+ * Strip given prefix from identifiers
+ *
+ * Printf(stderr,"%(strip:[wx])s","wxHello") -> Hello
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_strip(String *s) {
+ String *ns;
+ if (!Len(s)) {
+ ns = NewString(s);
+ } else {
+ const char *cs = Char(s);
+ const char *ce = Strchr(cs, ']');
+ if (*cs != '[' || !ce) {
+ ns = NewString(s);
+ } else {
+ String *fmt = NewStringf("%%.%ds", ce-cs-1);
+ String *prefix = NewStringf(fmt, cs+1);
+ if (0 == Strncmp(ce+1, prefix, Len(prefix))) {
+ ns = NewString(ce+1+Len(prefix));
+ } else {
+ ns = NewString(ce+1);
+ }
+ }
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_rstrip()
+ *
+ * Strip given suffix from identifiers
+ *
+ * Printf(stderr,"%(rstrip:[Cls])s","HelloCls") -> Hello
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_rstrip(String *s) {
+ String *ns;
+ int len = Len(s);
+ if (!len) {
+ ns = NewString(s);
+ } else {
+ const char *cs = Char(s);
+ const char *ce = Strchr(cs, ']');
+ if (*cs != '[' || !ce) {
+ ns = NewString(s);
+ } else {
+ String *fmt = NewStringf("%%.%ds", ce-cs-1);
+ String *suffix = NewStringf(fmt, cs+1);
+ int suffix_len = Len(suffix);
+ if (0 == Strncmp(cs+len-suffix_len, suffix, suffix_len)) {
+ int copy_len = len-suffix_len-(int)(ce+1-cs);
+ ns = NewStringWithSize(ce+1, copy_len);
+ } else {
+ ns = NewString(ce+1);
+ }
+ }
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_offset_string()
+ *
+ * Insert number tabs before each new line in s
+ * ----------------------------------------------------------------------------- */
+
+void Swig_offset_string(String *s, int number) {
+ char *res, *p, *end, *start;
+ /* count a number of lines in s */
+ int lines = 1;
+ int len = Len(s);
+ if (len == 0)
+ return;
+ start = strchr(Char(s), '\n');
+ while (start) {
+ ++lines;
+ start = strchr(start + 1, '\n');
+ }
+ /* do not count pending new line */
+ if ((Char(s))[len-1] == '\n')
+ --lines;
+ /* allocate a temporary storage for a padded string */
+ res = (char*)Malloc(len + lines * number * 2 + 1);
+ res[len + lines * number * 2] = 0;
+
+ /* copy lines to res, prepending tabs to each line */
+ p = res; /* output pointer */
+ start = Char(s); /* start of a current line */
+ end = strchr(start, '\n'); /* end of a current line */
+ while (end) {
+ memset(p, ' ', number*2);
+ p += number*2;
+ memcpy(p, start, end - start + 1);
+ p += end - start + 1;
+ start = end + 1;
+ end = strchr(start, '\n');
+ }
+ /* process the last line */
+ if (*start) {
+ memset(p, ' ', number*2);
+ p += number*2;
+ strcpy(p, start);
+ }
+ /* replace 's' contents with 'res' */
+ Clear(s);
+ Append(s, res);
+ Free(res);
+}
+
+
+#ifdef HAVE_PCRE
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+
+static int split_regex_pattern_subst(String *s, String **pattern, String **subst, const char **input)
+{
+ const char *pats, *pate;
+ const char *subs, *sube;
+
+ /* Locate the search pattern */
+ const char *p = Char(s);
+ if (*p++ != '/') goto err_out;
+ pats = p;
+ p = strchr(p, '/');
+ if (!p) goto err_out;
+ pate = p;
+
+ /* Locate the substitution string */
+ subs = ++p;
+ p = strchr(p, '/');
+ if (!p) goto err_out;
+ sube = p;
+
+ *pattern = NewStringWithSize(pats, (int)(pate - pats));
+ *subst = NewStringWithSize(subs, (int)(sube - subs));
+ *input = p + 1;
+ return 1;
+
+err_out:
+ Swig_error("SWIG", Getline(s), "Invalid regex substitution: '%s'.\n", s);
+ Exit(EXIT_FAILURE);
+ return 0;
+}
+
+/* This function copies len characters from src to dst, possibly applying case conversions to them: if convertCase is 1, to upper case and if it is -1, to lower
+ * case. If convertNextOnly is 1, only a single character is converted (and convertCase is reset), otherwise all of them are. */
+static void copy_with_maybe_case_conversion(String *dst, const char *src, int len, int *convertCase, int convertNextOnly)
+{
+ /* Deal with the trivial cases first. */
+ if (!len)
+ return;
+
+ if (!*convertCase) {
+ Write(dst, src, len);
+ return;
+ }
+
+ /* If we must convert only the first character, do it and write the rest at once. */
+ if (convertNextOnly) {
+ int src_char = *src;
+ Putc(*convertCase == 1 ? toupper(src_char) : tolower(src_char), dst);
+ *convertCase = 0;
+ if (len > 1) {
+ Write(dst, src + 1, len - 1);
+ }
+ } else {
+ /* We need to convert all characters. */
+ int i;
+ for (i = 0; i < len; i++, src++) {
+ int src_char = *src;
+ Putc(*convertCase == 1 ? toupper(src_char) : tolower(src_char), dst);
+ }
+ }
+}
+
+String *replace_captures(int num_captures, const char *input, String *subst, size_t captures[], String *pattern, String *s)
+{
+ int convertCase = 0, convertNextOnly = 0;
+ String *result = NewStringEmpty();
+ const char *p = Char(subst);
+
+ while (*p) {
+ /* Copy part without substitutions */
+ const char *q = strchr(p, '\\');
+ if (!q) {
+ copy_with_maybe_case_conversion(result, p, (int)strlen(p), &convertCase, convertNextOnly);
+ break;
+ }
+ copy_with_maybe_case_conversion(result, p, (int)(q - p), &convertCase, convertNextOnly);
+ p = q + 1;
+
+ /* Handle substitution */
+ if (*p == '\0') {
+ Putc('\\', result);
+ } else if (isdigit((unsigned char)*p)) {
+ int group = *p++ - '0';
+ if (group < num_captures) {
+ int l = (int)captures[group*2], r = (int)captures[group*2 + 1];
+ if (l != -1) {
+ copy_with_maybe_case_conversion(result, input + l, r - l, &convertCase, convertNextOnly);
+ }
+ } else {
+ Swig_error("SWIG", Getline(s), "PCRE capture replacement failed while matching \"%s\" using \"%s\" - request for group %d is greater than the number of captures %d.\n",
+ Char(pattern), input, group, num_captures-1);
+ }
+ } else {
+ /* Handle Perl-like case conversion escapes. */
+ switch (*p) {
+ case 'u':
+ convertCase = 1;
+ convertNextOnly = 1;
+ break;
+ case 'U':
+ convertCase = 1;
+ convertNextOnly = 0;
+ break;
+ case 'l':
+ convertCase = -1;
+ convertNextOnly = 1;
+ break;
+ case 'L':
+ convertCase = -1;
+ convertNextOnly = 0;
+ break;
+ case 'E':
+ convertCase = 0;
+ break;
+ default:
+ Swig_error("SWIG", Getline(s), "Unrecognized escape character '%c' in the replacement string \"%s\".\n",
+ *p, Char(subst));
+ }
+ p++;
+ }
+ }
+
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_regex()
+ *
+ * Executes a regular expression substitution. For example:
+ *
+ * Printf(stderr,"gsl%(regex:/GSL_(.*)_/\\1/)s", "GSL_Hello_") -> gslHello
+ * ----------------------------------------------------------------------------- */
+String *Swig_string_regex(String *s) {
+ const int pcre_options = 0;
+
+ String *res = 0;
+ pcre2_code *compiled_pat = 0;
+ const char *input;
+ PCRE2_UCHAR pcre_error[256];
+ int pcre_errornum;
+ size_t pcre_errorpos;
+ String *pattern = 0, *subst = 0;
+ size_t *captures = 0;
+ pcre2_match_data *match_data = 0;
+ if (split_regex_pattern_subst(s, &pattern, &subst, &input)) {
+ int rc;
+
+ compiled_pat = pcre2_compile(
+ (PCRE2_SPTR8)Char(pattern), PCRE2_ZERO_TERMINATED, pcre_options, &pcre_errornum, &pcre_errorpos, NULL);
+ if (!compiled_pat) {
+ pcre2_get_error_message (pcre_errornum, pcre_error, sizeof pcre_error);
+ Swig_error("SWIG", Getline(s), "PCRE compilation failed: '%s' in '%s':%i.\n",
+ pcre_error, Char(pattern), pcre_errorpos);
+ Exit(EXIT_FAILURE);
+ }
+ match_data = pcre2_match_data_create_from_pattern (compiled_pat, NULL);
+ rc = pcre2_match(compiled_pat, (PCRE2_SPTR8)input, PCRE2_ZERO_TERMINATED, 0, 0, match_data, NULL);
+ captures = pcre2_get_ovector_pointer (match_data);
+ if (rc >= 0) {
+ res = replace_captures(rc, input, subst, captures, pattern, s);
+ } else if (rc != PCRE2_ERROR_NOMATCH) {
+ Swig_error("SWIG", Getline(s), "PCRE execution failed: error %d while matching \"%s\" using \"%s\".\n",
+ rc, Char(pattern), input);
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ DohDelete(pattern);
+ DohDelete(subst);
+ pcre2_code_free(compiled_pat);
+ pcre2_match_data_free(match_data);
+ return res ? res : NewStringEmpty();
+}
+
+String *Swig_pcre_version(void) {
+ int len = pcre2_config(PCRE2_CONFIG_VERSION, NULL);
+ char *buf = Malloc(len);
+ String *result;
+ pcre2_config(PCRE2_CONFIG_VERSION, buf);
+ result = NewStringf("PCRE2 Version: %s", buf);
+ Free(buf);
+ return result;
+}
+
+#else
+
+String *Swig_string_regex(String *s) {
+ Swig_error("SWIG", Getline(s), "PCRE regex support not enabled in this SWIG build.\n");
+ Exit(EXIT_FAILURE);
+ return 0;
+}
+
+String *Swig_pcre_version(void) {
+ return NewStringf("PCRE not used");
+}
+
+#endif
+
+/* ------------------------------------------------------------
+ * Swig_is_generated_overload()
+ * Check if the function is an automatically generated
+ * overload created because a method has default parameters.
+ * ------------------------------------------------------------ */
+int Swig_is_generated_overload(Node *n) {
+ Node *base_method = Getattr(n, "sym:overloaded");
+ Node *default_args = Getattr(n, "defaultargs");
+ return ((base_method != NULL) && (default_args != NULL) && (base_method == default_args));
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_init()
+ *
+ * Initialize the SWIG core
+ * ----------------------------------------------------------------------------- */
+
+void Swig_init(void) {
+ /* Set some useful string encoding methods */
+ DohEncoding("escape", Swig_string_escape);
+ DohEncoding("hexescape", Swig_string_hexescape);
+ DohEncoding("upper", Swig_string_upper);
+ DohEncoding("lower", Swig_string_lower);
+ DohEncoding("title", Swig_string_title);
+ DohEncoding("ctitle", Swig_string_ccase);
+ DohEncoding("lctitle", Swig_string_lccase);
+ DohEncoding("utitle", Swig_string_ucase);
+ DohEncoding("typecode", Swig_string_typecode);
+ DohEncoding("mangle", Swig_string_emangle);
+ DohEncoding("command", Swig_string_command);
+ DohEncoding("schemify", Swig_string_schemify);
+ DohEncoding("strip", Swig_string_strip);
+ DohEncoding("rstrip", Swig_string_rstrip);
+ DohEncoding("regex", Swig_string_regex);
+
+ /* aliases for the case encoders */
+ DohEncoding("uppercase", Swig_string_upper);
+ DohEncoding("lowercase", Swig_string_lower);
+ DohEncoding("camelcase", Swig_string_ccase);
+ DohEncoding("lowercamelcase", Swig_string_lccase);
+ DohEncoding("undercase", Swig_string_ucase);
+ DohEncoding("firstuppercase", Swig_string_first_upper);
+ DohEncoding("firstlowercase", Swig_string_first_lower);
+
+ /* Initialize typemaps */
+ Swig_typemap_init();
+
+ /* Initialize symbol table */
+ Swig_symbol_init();
+
+ /* Initialize type system */
+ SwigType_typesystem_init();
+
+ /* Initialize template system */
+ SwigType_template_init();
+}
diff --git a/contrib/tools/swig/Source/Swig/naming.c b/contrib/tools/swig/Source/Swig/naming.c
new file mode 100644
index 0000000000..c4613f6c62
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/naming.c
@@ -0,0 +1,1771 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * naming.c
+ *
+ * Functions for generating various kinds of names during code generation.
+ *
+ * Swig_name_register is used to register a format string for generating names.
+ * The format string makes use of the following format specifiers:
+ *
+ * %c - class name is substituted
+ * %f - function name is substituted
+ * %m - member name is substituted
+ * %n - namespace is substituted
+ * %v - variable name is substituted
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+#include <ctype.h>
+
+/* Hash table containing naming data */
+
+static Hash *naming_hash = 0;
+
+#if 0
+#define SWIG_DEBUG
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_register()
+ *
+ * Register a new naming format.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_name_register(const_String_or_char_ptr method, const_String_or_char_ptr format) {
+ if (!naming_hash)
+ naming_hash = NewHash();
+ Setattr(naming_hash, method, format);
+}
+
+void Swig_name_unregister(const_String_or_char_ptr method) {
+ if (naming_hash) {
+ Delattr(naming_hash, method);
+ }
+}
+
+/* Return naming format for the specified method or the default format if none was explicitly registered */
+static String* get_naming_format_for(const char *method, const char *def_format) {
+ String* f = naming_hash ? Getattr(naming_hash, method) : NULL;
+
+ return f ? Copy(f) : NewString(def_format);
+}
+
+static int name_mangle(String *r) {
+ char *c;
+ int special;
+ special = 0;
+ Replaceall(r, "::", "_");
+ c = Char(r);
+ while (*c) {
+ if (!isalnum((int) *c) && (*c != '_')) {
+ special = 1;
+ switch (*c) {
+ case '+':
+ *c = 'a';
+ break;
+ case '-':
+ *c = 's';
+ break;
+ case '*':
+ *c = 'm';
+ break;
+ case '/':
+ *c = 'd';
+ break;
+ case '<':
+ *c = 'l';
+ break;
+ case '>':
+ *c = 'g';
+ break;
+ case '=':
+ *c = 'e';
+ break;
+ case ',':
+ *c = 'c';
+ break;
+ case '(':
+ *c = 'p';
+ break;
+ case ')':
+ *c = 'P';
+ break;
+ case '[':
+ *c = 'b';
+ break;
+ case ']':
+ *c = 'B';
+ break;
+ case '^':
+ *c = 'x';
+ break;
+ case '&':
+ *c = 'A';
+ break;
+ case '|':
+ *c = 'o';
+ break;
+ case '~':
+ *c = 'n';
+ break;
+ case '!':
+ *c = 'N';
+ break;
+ case '%':
+ *c = 'M';
+ break;
+ case '.':
+ *c = 'f';
+ break;
+ case '?':
+ *c = 'q';
+ break;
+ default:
+ *c = '_';
+ break;
+ }
+ }
+ c++;
+ }
+ if (special)
+ Append(r, "___");
+ return special;
+}
+
+/* -----------------------------------------------------------------------------
+ * replace_nspace()
+ *
+ * Mangles in the namespace from nspace by replacing %n in name if nspace feature required.
+ * ----------------------------------------------------------------------------- */
+
+static void replace_nspace(String *name, const_String_or_char_ptr nspace) {
+ if (nspace) {
+ String *namspace = NewStringf("%s_", nspace);
+ Replaceall(namspace, NSPACE_SEPARATOR, "_");
+ Replace(name, "%n", namspace, DOH_REPLACE_ANY);
+ Delete(namspace);
+ } else {
+ Replace(name, "%n", "", DOH_REPLACE_ANY);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_mangle()
+ *
+ * Converts all of the non-identifier characters of a string to underscores.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_mangle(const_String_or_char_ptr s) {
+#if 0
+ String *r = NewString(s);
+ name_mangle(r);
+ return r;
+#else
+ return Swig_string_mangle(s);
+#endif
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_wrapper()
+ *
+ * Returns the name of a wrapper function.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_wrapper(const_String_or_char_ptr fname) {
+ String *r = get_naming_format_for("wrapper", "_wrap_%f");
+
+ Replace(r, "%f", fname, DOH_REPLACE_ANY);
+ name_mangle(r);
+ return r;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_member()
+ *
+ * Returns the name of a class method.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_member(const_String_or_char_ptr nspace, const_String_or_char_ptr classname, const_String_or_char_ptr membername) {
+ String *r;
+ String *rclassname;
+ char *cname;
+
+ rclassname = SwigType_namestr(classname);
+ r = get_naming_format_for("member", "%n%c_%m");
+ cname = Char(rclassname);
+ if ((strncmp(cname, "struct ", 7) == 0) || ((strncmp(cname, "class ", 6) == 0)) || ((strncmp(cname, "union ", 6) == 0))) {
+ cname = strchr(cname, ' ') + 1;
+ }
+ replace_nspace(r, nspace);
+ Replace(r, "%c", cname, DOH_REPLACE_ANY);
+ Replace(r, "%m", membername, DOH_REPLACE_ANY);
+ /* name_mangle(r); */
+ Delete(rclassname);
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_get()
+ *
+ * Returns the name of the accessor function used to get a variable.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_get(const_String_or_char_ptr nspace, const_String_or_char_ptr vname) {
+ String *r = get_naming_format_for("get", "%n%v_get");
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_get: '%s'\n", vname);
+#endif
+
+ replace_nspace(r, nspace);
+ Replace(r, "%v", vname, DOH_REPLACE_ANY);
+ /* name_mangle(r); */
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_set()
+ *
+ * Returns the name of the accessor function used to set a variable.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_set(const_String_or_char_ptr nspace, const_String_or_char_ptr vname) {
+ String *r = get_naming_format_for("set", "%n%v_set");
+
+ replace_nspace(r, nspace);
+ Replace(r, "%v", vname, DOH_REPLACE_ANY);
+ /* name_mangle(r); */
+ return r;
+}
+
+/* Common implementation of all Swig_name_<special-method>() functions below. */
+static String *make_full_name_for(const char *method, const char *def_format, const_String_or_char_ptr nspace, const_String_or_char_ptr classname) {
+ String *r;
+ String *rclassname;
+ char *cname;
+
+ rclassname = SwigType_namestr(classname);
+ r = get_naming_format_for(method, def_format);
+
+ cname = Char(rclassname);
+ if ((strncmp(cname, "struct ", 7) == 0) || ((strncmp(cname, "class ", 6) == 0)) || ((strncmp(cname, "union ", 6) == 0))) {
+ cname = strchr(cname, ' ') + 1;
+ }
+
+ replace_nspace(r, nspace);
+ Replace(r, "%c", cname, DOH_REPLACE_ANY);
+ Delete(rclassname);
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_construct()
+ *
+ * Returns the name of the accessor function used to create an object.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_construct(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) {
+ return make_full_name_for("construct", "new_%n%c", nspace, classname);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_copyconstructor()
+ *
+ * Returns the name of the accessor function used to copy an object.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_copyconstructor(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) {
+ return make_full_name_for("copy", "copy_%n%c", nspace, classname);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_destroy()
+ *
+ * Returns the name of the accessor function used to destroy an object.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_destroy(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) {
+ return make_full_name_for("destroy", "delete_%n%c", nspace, classname);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_disown()
+ *
+ * Returns the name of the accessor function used to disown an object.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_disown(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) {
+ return make_full_name_for("disown", "disown_%n%c", nspace, classname);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_object_set()
+ *
+ * Sets an object associated with a name and optional declarators.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_name_object_set(Hash *namehash, String *name, SwigType *decl, DOH *object) {
+ DOH *n;
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_object_set: '%s', '%s'\n", name, decl);
+#endif
+ n = Getattr(namehash, name);
+ if (!n) {
+ n = NewHash();
+ Setattr(namehash, name, n);
+ Delete(n);
+ }
+ /* Add an object based on the declarator value */
+ if (!decl) {
+ Setattr(n, "start", object);
+ } else {
+ SwigType *cd = Copy(decl);
+ Setattr(n, cd, object);
+ Delete(cd);
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_object_get()
+ *
+ * Return an object associated with an optional class prefix, name, and
+ * declarator. This function operates according to name matching rules
+ * described for the %rename directive in the SWIG manual.
+ * ----------------------------------------------------------------------------- */
+
+static DOH *get_object(Hash *n, String *decl) {
+ DOH *rn = 0;
+ if (!n)
+ return 0;
+ if (decl) {
+ rn = Getattr(n, decl);
+ } else {
+ rn = Getattr(n, "start");
+ }
+ return rn;
+}
+
+static DOH *name_object_get(Hash *namehash, String *tname, SwigType *decl, SwigType *ncdecl) {
+ DOH *rn = 0;
+ Hash *n = Getattr(namehash, tname);
+ if (n) {
+ rn = get_object(n, decl);
+ if ((!rn) && ncdecl)
+ rn = get_object(n, ncdecl);
+ if (!rn)
+ rn = get_object(n, 0);
+ }
+ return rn;
+}
+
+DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType *decl) {
+ String *tname = NewStringEmpty();
+ DOH *rn = 0;
+ char *ncdecl = 0;
+
+ if (!namehash)
+ return 0;
+
+ /* DB: This removed to more tightly control feature/name matching */
+ /* if ((decl) && (SwigType_isqualifier(decl))) {
+ ncdecl = strchr(Char(decl),'.');
+ ncdecl++;
+ }
+ */
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_object_get: '%s' '%s', '%s'\n", prefix, name, decl);
+#endif
+
+
+ /* Perform a class-based lookup (if class prefix supplied) */
+ if (prefix) {
+ if (Len(prefix)) {
+ Printf(tname, "%s::%s", prefix, name);
+ rn = name_object_get(namehash, tname, decl, ncdecl);
+ if (!rn) {
+ String *cls = Swig_scopename_last(prefix);
+ if (!Equal(cls, prefix)) {
+ Clear(tname);
+ Printf(tname, "*::%s::%s", cls, name);
+ rn = name_object_get(namehash, tname, decl, ncdecl);
+ }
+ Delete(cls);
+ }
+ /* Lookup a name within a templated-based class */
+ if (!rn) {
+ String *t_name = SwigType_istemplate_templateprefix(prefix);
+ if (t_name) {
+ Clear(tname);
+ Printf(tname, "%s::%s", t_name, name);
+ rn = name_object_get(namehash, tname, decl, ncdecl);
+ Delete(t_name);
+ }
+ }
+ /* Lookup a template-based name within a class */
+ if (!rn) {
+ String *t_name = SwigType_istemplate_templateprefix(name);
+ if (t_name)
+ rn = Swig_name_object_get(namehash, prefix, t_name, decl);
+ Delete(t_name);
+ }
+ }
+ /* A wildcard-based class lookup */
+ if (!rn) {
+ Clear(tname);
+ Printf(tname, "*::%s", name);
+ rn = name_object_get(namehash, tname, decl, ncdecl);
+ }
+ } else {
+ /* Lookup in the global namespace only */
+ Clear(tname);
+ Printf(tname, "::%s", name);
+ rn = name_object_get(namehash, tname, decl, ncdecl);
+ }
+ /* Catch-all */
+ if (!rn) {
+ rn = name_object_get(namehash, name, decl, ncdecl);
+ }
+ if (!rn && Swig_scopename_check(name)) {
+ String *nprefix = 0;
+ String *nlast = 0;
+ Swig_scopename_split(name, &nprefix, &nlast);
+ rn = name_object_get(namehash, nlast, decl, ncdecl);
+ Delete(nlast);
+ Delete(nprefix);
+ }
+
+ Delete(tname);
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_object_get: found %d\n", rn ? 1 : 0);
+#endif
+
+ return rn;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_object_inherit()
+ *
+ * Implements name-based inheritance scheme.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_name_object_inherit(Hash *namehash, String *base, String *derived) {
+ Iterator ki;
+ Hash *derh;
+ String *bprefix;
+ String *dprefix;
+ char *cbprefix;
+ int plen;
+
+ if (!namehash)
+ return;
+
+ /* Temporary hash holding all the entries we add while we iterate over
+ namehash itself as we can't modify the latter while iterating over it. */
+ derh = NULL;
+ bprefix = NewStringf("%s::", base);
+ dprefix = NewStringf("%s::", derived);
+ cbprefix = Char(bprefix);
+ plen = (int)strlen(cbprefix);
+ for (ki = First(namehash); ki.key; ki = Next(ki)) {
+ char *k = Char(ki.key);
+ if (strncmp(k, cbprefix, plen) == 0) {
+ /* Copy, adjusting name, this element to the derived hash. */
+ Iterator oi;
+ String *nkey = NewStringf("%s%s", dprefix, k + plen);
+ Hash *n = ki.item;
+ Hash *newh;
+
+ /* Don't overwrite an existing value for the derived class, if any. */
+ newh = Getattr(namehash, nkey);
+ if (!newh) {
+ if (!derh)
+ derh = NewHash();
+
+ newh = NewHash();
+ Setattr(derh, nkey, newh);
+ Delete(newh);
+ }
+ for (oi = First(n); oi.key; oi = Next(oi)) {
+ if (!Getattr(newh, oi.key)) {
+ String *ci = Copy(oi.item);
+ Setattr(newh, oi.key, ci);
+ Delete(ci);
+ }
+ }
+ Delete(nkey);
+ }
+ }
+
+ /* Merge the contents of derived hash into the main hash. */
+ if (derh) {
+ for (ki = First(derh); ki.key; ki = Next(ki)) {
+ Setattr(namehash, ki.key, ki.item);
+ }
+ }
+
+ Delete(bprefix);
+ Delete(dprefix);
+ Delete(derh);
+}
+
+/* -----------------------------------------------------------------------------
+ * merge_features()
+ *
+ * Given a hash, this function merges the features in the hash into the node.
+ * ----------------------------------------------------------------------------- */
+
+static void merge_features(Hash *features, Node *n) {
+ Iterator ki;
+
+ if (!features)
+ return;
+ for (ki = First(features); ki.key; ki = Next(ki)) {
+ String *ci = Copy(ki.item);
+ Setattr(n, ki.key, ci);
+ Delete(ci);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_features_get()
+ *
+ * Attaches any features in the features hash to the node that matches
+ * the declaration, decl.
+ * ----------------------------------------------------------------------------- */
+
+static void features_get(Hash *features, const String *tname, SwigType *decl, SwigType *ncdecl, Node *node) {
+ Node *n = Getattr(features, tname);
+#ifdef SWIG_DEBUG
+ Printf(stdout, " features_get: %s\n", tname);
+#endif
+ if (n) {
+ merge_features(get_object(n, 0), node);
+ if (ncdecl)
+ merge_features(get_object(n, ncdecl), node);
+ merge_features(get_object(n, decl), node);
+ }
+}
+
+void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *decl, Node *node) {
+ char *ncdecl = 0;
+ String *rdecl = 0;
+ String *rname = 0;
+ if (!features)
+ return;
+
+ /* MM: This removed to more tightly control feature/name matching */
+ /*
+ if ((decl) && (SwigType_isqualifier(decl))) {
+ ncdecl = strchr(Char(decl),'.');
+ ncdecl++;
+ }
+ */
+
+ /* very specific hack for template constructors/destructors */
+ if (name && SwigType_istemplate(name)) {
+ String *nodetype = nodeType(node);
+ if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) {
+ String *nprefix = 0;
+ String *nlast = 0;
+ String *tprefix;
+ Swig_scopename_split(name, &nprefix, &nlast);
+ tprefix = SwigType_templateprefix(nlast);
+ Delete(nlast);
+ if (Len(nprefix)) {
+ Append(nprefix, "::");
+ Append(nprefix, tprefix);
+ Delete(tprefix);
+ rname = nprefix;
+ } else {
+ rname = tprefix;
+ Delete(nprefix);
+ }
+ rdecl = Copy(decl);
+ Replaceall(rdecl, name, rname);
+ decl = rdecl;
+ name = rname;
+ }
+ }
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_features_get: '%s' '%s' '%s'\n", prefix, name, decl);
+#endif
+
+ /* Global features */
+ features_get(features, "", 0, 0, node);
+ if (name) {
+ String *tname = NewStringEmpty();
+ /* add features for 'root' template */
+ String *dname = SwigType_istemplate_templateprefix(name);
+ if (dname) {
+ features_get(features, dname, decl, ncdecl, node);
+ }
+ /* Catch-all */
+ features_get(features, name, decl, ncdecl, node);
+ /* Perform a class-based lookup (if class prefix supplied) */
+ if (prefix) {
+ /* A class-generic feature */
+ if (Len(prefix)) {
+ Printf(tname, "%s::", prefix);
+ features_get(features, tname, decl, ncdecl, node);
+ }
+ /* A wildcard-based class lookup */
+ Clear(tname);
+ Printf(tname, "*::%s", name);
+ features_get(features, tname, decl, ncdecl, node);
+ /* A specific class lookup */
+ if (Len(prefix)) {
+ /* A template-based class lookup */
+ String *tprefix = SwigType_istemplate_templateprefix(prefix);
+ if (tprefix) {
+ Clear(tname);
+ Printf(tname, "%s::%s", tprefix, name);
+ features_get(features, tname, decl, ncdecl, node);
+ }
+ Clear(tname);
+ Printf(tname, "%s::%s", prefix, name);
+ features_get(features, tname, decl, ncdecl, node);
+ Delete(tprefix);
+ }
+ } else {
+ /* Lookup in the global namespace only */
+ Clear(tname);
+ Printf(tname, "::%s", name);
+ features_get(features, tname, decl, ncdecl, node);
+ }
+ Delete(tname);
+ Delete(dname);
+ }
+ if (name && SwigType_istemplate(name)) {
+ /* add features for complete template type */
+ String *dname = Swig_symbol_template_deftype(name, 0);
+ if (!Equal(dname, name)) {
+ Swig_features_get(features, prefix, dname, decl, node);
+ }
+ Delete(dname);
+ }
+
+ if (rname)
+ Delete(rname);
+ if (rdecl)
+ Delete(rdecl);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_feature_set()
+ *
+ * Sets a feature name and value. Also sets optional feature attributes as
+ * passed in by featureattribs. Optional feature attributes are given a full name
+ * concatenating the feature name plus ':' plus the attribute name.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_feature_set(Hash *features, const_String_or_char_ptr name, SwigType *decl, const_String_or_char_ptr featurename, const_String_or_char_ptr value, Hash *featureattribs) {
+ Hash *n;
+ Hash *fhash;
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_feature_set: '%s' '%s' '%s' '%s'\n", name, decl, featurename, value);
+#endif
+
+ n = Getattr(features, name);
+ if (!n) {
+ n = NewHash();
+ Setattr(features, name, n);
+ Delete(n);
+ }
+ if (!decl) {
+ fhash = Getattr(n, "start");
+ if (!fhash) {
+ fhash = NewHash();
+ Setattr(n, "start", fhash);
+ Delete(fhash);
+ }
+ } else {
+ fhash = Getattr(n, decl);
+ if (!fhash) {
+ String *cdecl_ = Copy(decl);
+ fhash = NewHash();
+ Setattr(n, cdecl_, fhash);
+ Delete(cdecl_);
+ Delete(fhash);
+ }
+ }
+ if (value) {
+ Setattr(fhash, featurename, value);
+ } else {
+ Delattr(fhash, featurename);
+ }
+
+ {
+ /* Add in the optional feature attributes */
+ Hash *attribs = featureattribs;
+ while (attribs) {
+ String *attribname = Getattr(attribs, "name");
+ String *featureattribname = NewStringf("%s:%s", featurename, attribname);
+ if (value) {
+ String *attribvalue = Getattr(attribs, "value");
+ Setattr(fhash, featureattribname, attribvalue);
+ } else {
+ Delattr(fhash, featureattribname);
+ }
+ attribs = nextSibling(attribs);
+ Delete(featureattribname);
+ }
+ }
+
+ if (name && SwigType_istemplate(name)) {
+ String *dname = Swig_symbol_template_deftype(name, 0);
+ if (Strcmp(dname, name)) {
+ Swig_feature_set(features, dname, decl, featurename, value, featureattribs);
+ }
+ Delete(dname);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * The rename/namewarn engine
+ *
+ * Code below was in parser.y for a while
+ * ----------------------------------------------------------------------------- */
+
+static Hash *namewarn_hash = 0;
+static Hash *name_namewarn_hash(void) {
+ if (!namewarn_hash)
+ namewarn_hash = NewHash();
+ return namewarn_hash;
+}
+
+static Hash *rename_hash = 0;
+static Hash *name_rename_hash(void) {
+ if (!rename_hash)
+ rename_hash = NewHash();
+ return rename_hash;
+}
+
+static List *namewarn_list = 0;
+static List *name_namewarn_list(void) {
+ if (!namewarn_list)
+ namewarn_list = NewList();
+ return namewarn_list;
+}
+
+static List *rename_list = 0;
+static List *name_rename_list(void) {
+ if (!rename_list)
+ rename_list = NewList();
+ return rename_list;
+}
+
+/* -----------------------------------------------------------------------------
+ * int need_name_warning(Node *n)
+ *
+ * Detects if a node needs name warnings
+ *
+ * ----------------------------------------------------------------------------- */
+
+static int need_name_warning(Node *n) {
+ int need = 1;
+ /*
+ We don't use name warnings for:
+ - class forwards, no symbol is generated at the target language.
+ - template declarations, only for real instances using %template(name).
+ - typedefs, have no effect at the target language.
+ - using declarations and using directives, have no effect at the target language.
+ */
+ if (checkAttribute(n, "nodeType", "classforward")) {
+ need = 0;
+ } else if (checkAttribute(n, "nodeType", "using")) {
+ need = 0;
+ } else if (checkAttribute(n, "storage", "typedef")) {
+ need = 0;
+ } else if (Getattr(n, "hidden")) {
+ need = 0;
+ } else if (Getattr(n, "ignore")) {
+ need = 0;
+ } else if (Getattr(n, "templatetype")) {
+ need = 0;
+ } else if (GetFlag(n, "parsing_template_declaration")) {
+ need = 0;
+ }
+ return need;
+}
+
+/* -----------------------------------------------------------------------------
+ * int Swig_need_redefined_warn()
+ *
+ * Detects when a redefined object needs a warning
+ *
+ * ----------------------------------------------------------------------------- */
+
+static int nodes_are_equivalent(Node *a, Node *b, int a_inclass) {
+ /* they must have the same type */
+ String *ta = nodeType(a);
+ String *tb = nodeType(b);
+ if (!Equal(ta, tb)) {
+ if (!(Equal(ta, "using") && Equal(tb, "cdecl"))) {
+ return 0;
+ }
+ }
+
+ if (Cmp(ta, "cdecl") == 0) {
+ /* both cdecl case */
+ /* typedef */
+ String *a_storage = Getattr(a, "storage");
+ String *b_storage = Getattr(b, "storage");
+
+ if ((Cmp(a_storage, "typedef") == 0)
+ || (Cmp(b_storage, "typedef") == 0)) {
+ if (Cmp(a_storage, b_storage) == 0) {
+ String *a_type = (Getattr(a, "type"));
+ String *b_type = (Getattr(b, "type"));
+ if (Cmp(a_type, b_type) == 0)
+ return 1;
+ }
+ return 0;
+ }
+
+ /* static functions */
+ if (Swig_storage_isstatic(a) || Swig_storage_isstatic(b)) {
+ if (Cmp(a_storage, b_storage) != 0)
+ return 0;
+ }
+
+ /* friend methods */
+
+ if (!a_inclass || (Cmp(a_storage, "friend") == 0)) {
+ /* check declaration */
+
+ String *a_decl = (Getattr(a, "decl"));
+ String *b_decl = (Getattr(b, "decl"));
+ if (Cmp(a_decl, b_decl) == 0) {
+ /* check return type */
+ String *a_type = (Getattr(a, "type"));
+ String *b_type = (Getattr(b, "type"));
+ if (Cmp(a_type, b_type) == 0) {
+ /* check parameters */
+ Parm *ap = (Getattr(a, "parms"));
+ Parm *bp = (Getattr(b, "parms"));
+ while (ap && bp) {
+ SwigType *at = Getattr(ap, "type");
+ SwigType *bt = Getattr(bp, "type");
+ if (Cmp(at, bt) != 0)
+ return 0;
+ ap = nextSibling(ap);
+ bp = nextSibling(bp);
+ }
+ if (ap || bp) {
+ return 0;
+ } else {
+ Node *a_template = Getattr(a, "template");
+ Node *b_template = Getattr(b, "template");
+ /* Not equivalent if one is a template instantiation (via %template) and the other is a non-templated function */
+ if ((a_template && !b_template) || (!a_template && b_template))
+ return 0;
+ }
+ return 1;
+ }
+ }
+ }
+ } else if (Equal(ta, "using")) {
+ /* using and cdecl case */
+ String *b_storage = Getattr(b, "storage");
+ if (Equal(b_storage, "typedef")) {
+ String *a_name = Getattr(a, "name");
+ String *b_name = Getattr(b, "name");
+ if (Equal(a_name, b_name))
+ return 1;
+ }
+ } else {
+ /* both %constant case */
+ String *a_storage = Getattr(a, "storage");
+ String *b_storage = Getattr(b, "storage");
+ if ((Cmp(a_storage, "%constant") == 0)
+ || (Cmp(b_storage, "%constant") == 0)) {
+ if (Cmp(a_storage, b_storage) == 0) {
+ String *a_type = (Getattr(a, "type"));
+ String *b_type = (Getattr(b, "type"));
+ if ((Cmp(a_type, b_type) == 0)
+ && (Cmp(Getattr(a, "value"), Getattr(b, "value")) == 0))
+ return 1;
+ }
+ return 0;
+ }
+ if (Equal(ta, "template") && Equal(tb, "template")) {
+ if (Cmp(a_storage, "friend") == 0 || Cmp(b_storage, "friend") == 0)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int Swig_need_redefined_warn(Node *a, Node *b, int InClass) {
+ String *a_name = Getattr(a, "name");
+ String *b_name = Getattr(b, "name");
+ String *a_symname = Getattr(a, "sym:name");
+ String *b_symname = Getattr(b, "sym:name");
+ /* always send a warning if a 'rename' is involved */
+ if ((a_symname && !Equal(a_symname, a_name))
+ || (b_symname && !Equal(b_symname, b_name))) {
+ if (!Equal(a_name, b_name)) {
+ return 1;
+ }
+ }
+
+
+ return !nodes_are_equivalent(a, b, InClass);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * int Swig_need_protected(Node* n)
+ *
+ * Detects when we need to fully register the protected member.
+ * This is basically any protected members when the allprotected mode is set.
+ * Otherwise we take just the protected virtual methods and non-static methods
+ * (potentially virtual methods) as well as constructors/destructors.
+ * Also any "using" statements in a class may potentially be virtual.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_need_protected(Node *n) {
+ String *nodetype = nodeType(n);
+ if (checkAttribute(n, "access", "protected")) {
+ if ((Equal(nodetype, "cdecl"))) {
+ if (Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode()) {
+ return 1;
+ }
+ if (SwigType_isfunction(Getattr(n, "decl"))) {
+ String *storage = Getattr(n, "storage");
+ /* The function is declared virtual, or it has no storage. This eliminates typedef, static etc. */
+ return !storage || Equal(storage, "virtual");
+ }
+ } else if (Equal(nodetype, "constructor") || Equal(nodetype, "destructor")) {
+ return 1;
+ } else if (Equal(nodetype, "using") && !Getattr(n, "namespace")) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * void name_nameobj_add()
+ *
+ * Add nameobj (rename/namewarn)
+ *
+ * ----------------------------------------------------------------------------- */
+
+static List *make_attrlist(const char *ckey) {
+ List *list = NewList();
+ const char *cattr = strchr(ckey, '$');
+ if (cattr) {
+ String *nattr;
+ const char *rattr = strchr(++cattr, '$');
+ while (rattr) {
+ nattr = NewStringWithSize(cattr, (int)(rattr - cattr));
+ Append(list, nattr);
+ Delete(nattr);
+ cattr = rattr + 1;
+ rattr = strchr(cattr, '$');
+ }
+ nattr = NewString(cattr);
+ Append(list, nattr);
+ Delete(nattr);
+ } else {
+ Append(list, "nodeType");
+ }
+ return list;
+}
+
+static void name_object_attach_keys(const char *keys[], Hash *nameobj) {
+ Node *kw = nextSibling(nameobj);
+ List *matchlist = 0;
+ while (kw) {
+ Node *next = nextSibling(kw);
+ String *kname = Getattr(kw, "name");
+ char *ckey = kname ? Char(kname) : 0;
+ if (ckey) {
+ const char **rkey;
+ int isnotmatch = 0;
+ int isregexmatch = 0;
+ if ((strncmp(ckey, "match", 5) == 0)
+ || (isnotmatch = (strncmp(ckey, "notmatch", 8) == 0))
+ || (isregexmatch = (strncmp(ckey, "regexmatch", 10) == 0))
+ || (isnotmatch = isregexmatch = (strncmp(ckey, "notregexmatch", 13) == 0))) {
+ Hash *mi = NewHash();
+ List *attrlist = make_attrlist(ckey);
+ if (!matchlist)
+ matchlist = NewList();
+ Setattr(mi, "value", Getattr(kw, "value"));
+ Setattr(mi, "attrlist", attrlist);
+ if (isnotmatch)
+ SetFlag(mi, "notmatch");
+ if (isregexmatch)
+ SetFlag(mi, "regexmatch");
+ Delete(attrlist);
+ Append(matchlist, mi);
+ Delete(mi);
+ removeNode(kw);
+ } else {
+ for (rkey = keys; *rkey != 0; ++rkey) {
+ if (strcmp(ckey, *rkey) == 0) {
+ Setattr(nameobj, *rkey, Getattr(kw, "value"));
+ removeNode(kw);
+ }
+ }
+ }
+ }
+ kw = next;
+ }
+ if (matchlist) {
+ Setattr(nameobj, "matchlist", matchlist);
+ Delete(matchlist);
+ }
+}
+
+static void name_nameobj_add(Hash *name_hash, List *name_list, String *prefix, String *name, SwigType *decl, Hash *nameobj) {
+ String *nname = 0;
+ if (name && Len(name)) {
+ String *target_fmt = Getattr(nameobj, "targetfmt");
+ nname = prefix ? NewStringf("%s::%s", prefix, name) : NewString(name);
+ if (target_fmt) {
+ String *tmp = NewStringf(target_fmt, nname);
+ Delete(nname);
+ nname = tmp;
+ }
+ }
+
+ if (!nname || !Len(nname) || Getattr(nameobj, "fullname") || /* any of these options trigger a 'list' nameobj */
+ Getattr(nameobj, "sourcefmt") || Getattr(nameobj, "matchlist") || Getattr(nameobj, "regextarget")) {
+ if (decl)
+ Setattr(nameobj, "decl", decl);
+ if (nname && Len(nname))
+ Setattr(nameobj, "targetname", nname);
+ /* put the new nameobj at the beginning of the list, such that the
+ last inserted rule take precedence */
+ Insert(name_list, 0, nameobj);
+ } else {
+ /* here we add an old 'hash' nameobj, simple and fast */
+ Swig_name_object_set(name_hash, nname, decl, nameobj);
+ }
+ Delete(nname);
+}
+
+/* -----------------------------------------------------------------------------
+ * int name_match_nameobj()
+ *
+ * Apply and check the nameobj's math list to the node
+ *
+ * ----------------------------------------------------------------------------- */
+
+static DOH *get_lattr(Node *n, List *lattr) {
+ DOH *res = 0;
+ int ilen = Len(lattr);
+ int i;
+ for (i = 0; n && (i < ilen); ++i) {
+ String *nattr = Getitem(lattr, i);
+ res = Getattr(n, nattr);
+#ifdef SWIG_DEBUG
+ if (!res) {
+ Printf(stdout, "missing %s %s %s\n", nattr, Getattr(n, "name"), Getattr(n, "member"));
+ } else {
+ Printf(stdout, "lattr %d %s %s\n", i, nattr, DohIsString(res) ? res : Getattr(res, "name"));
+ }
+#endif
+ n = res;
+ }
+ return res;
+}
+
+#ifdef HAVE_PCRE
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+
+static int name_regexmatch_value(Node *n, String *pattern, String *s) {
+ pcre2_code *compiled_pat;
+ PCRE2_UCHAR err[256];
+ int errornum;
+ size_t errpos;
+ int rc;
+ pcre2_match_data *match_data = 0;
+
+ compiled_pat = pcre2_compile((PCRE2_SPTR8)Char(pattern), PCRE2_ZERO_TERMINATED, 0, &errornum, &errpos, NULL);
+ if (!compiled_pat) {
+ pcre2_get_error_message (errornum, err, sizeof err);
+ Swig_error("SWIG", Getline(n),
+ "Invalid regex \"%s\": compilation failed at %d: %s\n",
+ Char(pattern), errpos, err);
+ Exit(EXIT_FAILURE);
+ }
+
+ match_data = pcre2_match_data_create_from_pattern (compiled_pat, NULL);
+ rc = pcre2_match(compiled_pat, (PCRE2_SPTR8)Char(s), PCRE2_ZERO_TERMINATED, 0, 0, match_data, 0);
+ pcre2_code_free(compiled_pat);
+ pcre2_match_data_free(match_data);
+
+ if (rc == PCRE2_ERROR_NOMATCH)
+ return 0;
+
+ if (rc < 0 ) {
+ Swig_error("SWIG", Getline(n),
+ "Matching \"%s\" against regex \"%s\" failed: %d\n",
+ Char(s), Char(pattern), rc);
+ Exit(EXIT_FAILURE);
+ }
+
+ return 1;
+}
+
+#else /* !HAVE_PCRE */
+
+static int name_regexmatch_value(Node *n, String *pattern, String *s) {
+ (void)pattern;
+ (void)s;
+ Swig_error("SWIG", Getline(n),
+ "PCRE regex matching is not available in this SWIG build.\n");
+ Exit(EXIT_FAILURE);
+ return 0;
+}
+
+#endif /* HAVE_PCRE/!HAVE_PCRE */
+
+static int name_match_value(String *mvalue, String *value) {
+#if defined(SWIG_USE_SIMPLE_MATCHOR)
+ int match = 0;
+ char *cvalue = Char(value);
+ char *cmvalue = Char(mvalue);
+ char *sep = strchr(cmvalue, '|');
+ while (sep && !match) {
+ match = strncmp(cvalue, cmvalue, sep - cmvalue) == 0;
+#ifdef SWIG_DEBUG
+ Printf(stdout, "match_value: %s %s %d\n", cvalue, cmvalue, match);
+#endif
+ cmvalue = sep + 1;
+ sep = strchr(cmvalue, '|');
+ }
+ if (!match) {
+ match = strcmp(cvalue, cmvalue) == 0;
+#ifdef SWIG_DEBUG
+ Printf(stdout, "match_value: %s %s %d\n", cvalue, cmvalue, match);
+#endif
+ }
+ return match;
+#else
+ return Equal(mvalue, value);
+#endif
+}
+
+static int name_match_nameobj(Hash *rn, Node *n) {
+ int match = 1;
+ List *matchlist = Getattr(rn, "matchlist");
+#ifdef SWIG_DEBUG
+ Printf(stdout, "name_match_nameobj: %s\n", Getattr(n, "name"));
+#endif
+ if (matchlist) {
+ int ilen = Len(matchlist);
+ int i;
+ for (i = 0; match && (i < ilen); ++i) {
+ Node *mi = Getitem(matchlist, i);
+ List *lattr = Getattr(mi, "attrlist");
+ String *nval = get_lattr(n, lattr);
+ int notmatch = GetFlag(mi, "notmatch");
+ int regexmatch = GetFlag(mi, "regexmatch");
+ match = 0;
+ if (nval) {
+ String *kwval = Getattr(mi, "value");
+ match = regexmatch ? name_regexmatch_value(n, kwval, nval)
+ : name_match_value(kwval, nval);
+#ifdef SWIG_DEBUG
+ Printf(stdout, "val %s %s %d %d \n", nval, kwval, match, ilen);
+#endif
+ }
+ if (notmatch)
+ match = !match;
+ }
+ }
+#ifdef SWIG_DEBUG
+ Printf(stdout, "name_match_nameobj: %d\n", match);
+#endif
+ return match;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash *name_nameobj_lget()
+ *
+ * Get a nameobj (rename/namewarn) from the list of filters
+ *
+ * ----------------------------------------------------------------------------- */
+
+static Hash *name_nameobj_lget(List *namelist, Node *n, String *prefix, String *name, String *decl) {
+ Hash *res = 0;
+ if (namelist) {
+ int len = Len(namelist);
+ int i;
+ int match = 0;
+ for (i = 0; !match && (i < len); i++) {
+ Hash *rn = Getitem(namelist, i);
+ String *rdecl = Getattr(rn, "decl");
+ if (rdecl && (!decl || !Equal(rdecl, decl))) {
+ continue;
+ } else if (name_match_nameobj(rn, n)) {
+ String *tname = Getattr(rn, "targetname");
+ if (tname) {
+ String *sfmt = Getattr(rn, "sourcefmt");
+ String *sname = 0;
+ int fullname = GetFlag(rn, "fullname");
+ int regextarget = GetFlag(rn, "regextarget");
+ if (sfmt) {
+ if (fullname && prefix) {
+ String *pname = NewStringf("%s::%s", prefix, name);
+ sname = NewStringf(sfmt, pname);
+ Delete(pname);
+ } else {
+ sname = NewStringf(sfmt, name);
+ }
+ } else {
+ if (fullname && prefix) {
+ sname = NewStringf("%s::%s", prefix, name);
+ } else {
+ sname = name;
+ DohIncref(name);
+ }
+ }
+ match = regextarget ? name_regexmatch_value(n, tname, sname)
+ : name_match_value(tname, sname);
+ Delete(sname);
+ } else {
+ /* Applying the renaming rule may fail if it contains a %(regex)s expression that doesn't match the given name. */
+ String *sname = NewStringf(Getattr(rn, "name"), name);
+ if (sname) {
+ if (Len(sname))
+ match = 1;
+ Delete(sname);
+ }
+ }
+ }
+ if (match) {
+ res = rn;
+ break;
+ }
+ }
+ }
+ return res;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_namewarn_add
+ *
+ * Add a namewarn objects
+ *
+ * ----------------------------------------------------------------------------- */
+
+void Swig_name_namewarn_add(String *prefix, String *name, SwigType *decl, Hash *namewrn) {
+ const char *namewrn_keys[] = { "rename", "error", "fullname", "sourcefmt", "targetfmt", 0 };
+ name_object_attach_keys(namewrn_keys, namewrn);
+ name_nameobj_add(name_namewarn_hash(), name_namewarn_list(), prefix, name, decl, namewrn);
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash *name_namewarn_get()
+ *
+ * Return the namewarn object, if there is one.
+ *
+ * ----------------------------------------------------------------------------- */
+
+static Hash *name_namewarn_get(Node *n, String *prefix, String *name, SwigType *decl) {
+ if (!namewarn_hash && !namewarn_list)
+ return 0;
+ if (n) {
+ /* Return in the obvious cases */
+ if (!name || !need_name_warning(n)) {
+ return 0;
+ } else {
+ String *access = Getattr(n, "access");
+ int is_public = !access || Equal(access, "public");
+ if (!is_public && !Swig_need_protected(n)) {
+ return 0;
+ }
+ }
+ }
+ if (name) {
+ /* Check to see if the name is in the hash */
+ Hash *wrn = Swig_name_object_get(name_namewarn_hash(), prefix, name, decl);
+ if (wrn && !name_match_nameobj(wrn, n))
+ wrn = 0;
+ if (!wrn) {
+ wrn = name_nameobj_lget(name_namewarn_list(), n, prefix, name, decl);
+ }
+ if (wrn && Getattr(wrn, "error")) {
+ if (n) {
+ Swig_error(Getfile(n), Getline(n), "%s\n", Getattr(wrn, "name"));
+ } else {
+ Swig_error(cparse_file, cparse_line, "%s\n", Getattr(wrn, "name"));
+ }
+ }
+ return wrn;
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * String *Swig_name_warning()
+ *
+ * Return the name warning, if there is one.
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_warning(Node *n, String *prefix, String *name, SwigType *decl) {
+ Hash *wrn = name_namewarn_get(n, prefix, name, decl);
+ return (name && wrn) ? Getattr(wrn, "name") : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_rename_add()
+ *
+ * Manage the rename objects
+ *
+ * ----------------------------------------------------------------------------- */
+
+static void single_rename_add(String *prefix, String *name, SwigType *decl, Hash *newname) {
+ name_nameobj_add(name_rename_hash(), name_rename_list(), prefix, name, decl, newname);
+}
+
+/* Add a new rename. Works much like new_feature including default argument handling. */
+void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *newname, ParmList *declaratorparms) {
+
+ ParmList *declparms = declaratorparms;
+
+ const char *rename_keys[] = { "fullname", "sourcefmt", "targetfmt", "continue", "regextarget", 0 };
+ name_object_attach_keys(rename_keys, newname);
+
+ /* Add the name */
+ single_rename_add(prefix, name, decl, newname);
+
+ /* Add extra names if there are default parameters in the parameter list */
+ if (decl) {
+ int constqualifier = SwigType_isconst(decl);
+ while (declparms) {
+ if (ParmList_has_defaultargs(declparms)) {
+
+ /* Create a parameter list for the new rename by copying all
+ but the last (defaulted) parameter */
+ ParmList *newparms = CopyParmListMax(declparms,ParmList_len(declparms)-1);
+
+ /* Create new declaration - with the last parameter removed */
+ SwigType *newdecl = Copy(decl);
+ Delete(SwigType_pop_function(newdecl)); /* remove the old parameter list from newdecl */
+ SwigType_add_function(newdecl, newparms);
+ if (constqualifier)
+ SwigType_add_qualifier(newdecl, "const");
+
+ single_rename_add(prefix, name, newdecl, newname);
+ declparms = newparms;
+ Delete(newdecl);
+ } else {
+ declparms = 0;
+ }
+ }
+ }
+}
+
+
+/* Create a name for the given node applying rename/namewarn if needed */
+static String *apply_rename(Node* n, String *newname, int fullname, String *prefix, String *name) {
+ String *result = 0;
+ if (newname && Len(newname)) {
+ if (Strcmp(newname, "$ignore") == 0) {
+ /* $ignore doesn't apply to parameters and while it's rare to explicitly write %ignore directives for them they could be caught by a wildcard ignore using
+ regex match, just ignore the attempt to ignore them in this case */
+ if (!Equal(nodeType(n), "parm"))
+ result = Copy(newname);
+ } else {
+ char *cnewname = Char(newname);
+ if (cnewname) {
+ int destructor = name && (*(Char(name)) == '~');
+ String *fmt = newname;
+ /* use name as a fmt, but avoid C++ "%" and "%=" operators */
+ if (Len(newname) > 1 && strchr(cnewname, '%') && !(strcmp(cnewname, "%=") == 0)) {
+ if (fullname && prefix) {
+ result = NewStringf(fmt, prefix, name);
+ } else {
+ result = NewStringf(fmt, name);
+ }
+ } else {
+ result = Copy(newname);
+ }
+ if (destructor && result && (*(Char(result)) != '~')) {
+ Insert(result, 0, "~");
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * String *Swig_name_make()
+ *
+ * Make a name after applying all the rename/namewarn objects
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_make(Node *n, String *prefix, const_String_or_char_ptr cname, SwigType *decl, String *oldname) {
+ String *nname = 0;
+ String *result = 0;
+ String *name = NewString(cname);
+ Hash *wrn = 0;
+ String *rdecl = 0;
+ String *rname = 0;
+
+ /* very specific hack for template constructors/destructors */
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_make: looking for %s %s %s %s\n", prefix, name, decl, oldname);
+#endif
+
+ if (name && n && SwigType_istemplate(name)) {
+ String *nodetype = nodeType(n);
+ if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) {
+ String *nprefix = 0;
+ String *nlast = 0;
+ String *tprefix;
+ Swig_scopename_split(name, &nprefix, &nlast);
+ tprefix = SwigType_templateprefix(nlast);
+ Delete(nlast);
+ if (Len(nprefix)) {
+ Append(nprefix, "::");
+ Append(nprefix, tprefix);
+ Delete(tprefix);
+ rname = nprefix;
+ } else {
+ rname = tprefix;
+ Delete(nprefix);
+ }
+ rdecl = Copy(decl);
+ Replaceall(rdecl, name, rname);
+#ifdef SWIG_DEBUG
+ Printf(stdout, "SWIG_name_make: use new name %s %s : %s %s\n", name, decl, rname, rdecl);
+#endif
+ decl = rdecl;
+ Delete(name);
+ name = rname;
+ }
+ }
+
+ if (rename_hash || rename_list || namewarn_hash || namewarn_list) {
+ Hash *rn = Swig_name_object_get(name_rename_hash(), prefix, name, decl);
+ if (!rn || !name_match_nameobj(rn, n)) {
+ rn = name_nameobj_lget(name_rename_list(), n, prefix, name, decl);
+ if (rn) {
+ String *sfmt = Getattr(rn, "sourcefmt");
+ int fullname = GetFlag(rn, "fullname");
+ if (fullname && prefix) {
+ String *sname = NewStringf("%s::%s", prefix, name);
+ Delete(name);
+ name = sname;
+ prefix = 0;
+ }
+ if (sfmt) {
+ String *sname = NewStringf(sfmt, name);
+ Delete(name);
+ name = sname;
+ }
+ }
+ }
+ if (rn) {
+ String *newname = Getattr(rn, "name");
+ int fullname = GetFlag(rn, "fullname");
+ result = apply_rename(n, newname, fullname, prefix, name);
+ }
+ if (result && !Equal(result, name)) {
+ /* operators in C++ allow aliases, we look for them */
+ char *cresult = Char(result);
+ if (cresult && (strncmp(cresult, "operator ", 9) == 0)) {
+ String *nresult = Swig_name_make(n, prefix, result, decl, oldname);
+ if (!Equal(nresult, result)) {
+ Delete(result);
+ result = nresult;
+ } else {
+ Delete(nresult);
+ }
+ }
+ }
+ nname = result ? result : name;
+ wrn = name_namewarn_get(n, prefix, nname, decl);
+ if (wrn) {
+ String *rename = Getattr(wrn, "rename");
+ if (rename) {
+ String *msg = Getattr(wrn, "name");
+ int fullname = GetFlag(wrn, "fullname");
+ if (result)
+ Delete(result);
+ result = apply_rename(n, rename, fullname, prefix, name);
+ if ((msg) && (Len(msg))) {
+ if (!Getmeta(nname, "already_warned")) {
+ String* suffix = 0;
+ if (Strcmp(result, "$ignore") == 0) {
+ suffix = NewStringf(": ignoring '%s'\n", name);
+ } else if (Strcmp(result, name) != 0) {
+ suffix = NewStringf(", renaming to '%s'\n", result);
+ } else {
+ /* No rename was performed */
+ suffix = NewString("\n");
+ }
+ if (n) {
+ /* Parameter renaming is not fully implemented. Mainly because there is no C/C++ syntax to
+ * for %rename to fully qualify a function's parameter name from outside the function. Hence it
+ * is not possible to implemented targeted warning suppression on one parameter in one function. */
+ int suppress_parameter_rename_warning = Equal(nodeType(n), "parm");
+ if (!suppress_parameter_rename_warning) {
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(0, Getfile(n), Getline(n), "%s%s", msg, suffix);
+ SWIG_WARN_NODE_END(n);
+ }
+ } else {
+ Swig_warning(0, Getfile(name), Getline(name), "%s%s", msg, suffix);
+ }
+ Setmeta(nname, "already_warned", "1");
+ Delete(suffix);
+ }
+ }
+ }
+ }
+ }
+ if (!result || !Len(result)) {
+ if (result)
+ Delete(result);
+ if (oldname) {
+ result = NewString(oldname);
+ } else {
+ result = NewString(cname);
+ }
+ }
+ Delete(name);
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_make: result '%s' '%s'\n", cname, result);
+#endif
+
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * void Swig_name_inherit()
+ *
+ * Inherit namewarn, rename, and feature objects
+ *
+ * ----------------------------------------------------------------------------- */
+
+void Swig_name_inherit(String *base, String *derived) {
+ /* Printf(stdout,"base = '%s', derived = '%s'\n", base, derived); */
+ Swig_name_object_inherit(name_rename_hash(), base, derived);
+ Swig_name_object_inherit(name_namewarn_hash(), base, derived);
+ Swig_name_object_inherit(Swig_cparse_features(), base, derived);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_inherit_base_symbols()
+ * ----------------------------------------------------------------------------- */
+
+void Swig_inherit_base_symbols(List *bases) {
+ if (bases) {
+ Iterator s;
+ for (s = First(bases); s.item; s = Next(s)) {
+ Symtab *st = Getattr(s.item, "symtab");
+ if (st) {
+ Setfile(st, Getfile(s.item));
+ Setline(st, Getline(s.item));
+ Swig_symbol_inherit(st);
+ }
+ }
+ Delete(bases);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_make_inherit_list()
+ * ----------------------------------------------------------------------------- */
+
+List *Swig_make_inherit_list(String *clsname, List *names, String *Namespaceprefix) {
+ int i, ilen;
+ String *derived;
+ List *bases = NewList();
+
+ if (Namespaceprefix)
+ derived = NewStringf("%s::%s", Namespaceprefix, clsname);
+ else
+ derived = NewString(clsname);
+
+ ilen = Len(names);
+ for (i = 0; i < ilen; i++) {
+ String *base;
+ String *n = Getitem(names, i);
+ /* Try to figure out where this symbol is */
+ Node *s = Swig_symbol_clookup(n, 0);
+ if (s) {
+ while (s && (Strcmp(nodeType(s), "class") != 0)) {
+ /* Not a class. Could be a typedef though. */
+ String *storage = Getattr(s, "storage");
+ if (storage && (Strcmp(storage, "typedef") == 0)) {
+ String *nn = Getattr(s, "type");
+ s = Swig_symbol_clookup(nn, Getattr(s, "sym:symtab"));
+ } else {
+ break;
+ }
+ }
+ if (s && ((Strcmp(nodeType(s), "class") == 0) || (Strcmp(nodeType(s), "template") == 0))) {
+ String *q = Swig_symbol_qualified(s);
+ Append(bases, s);
+ if (q) {
+ base = NewStringf("%s::%s", q, Getattr(s, "name"));
+ Delete(q);
+ } else {
+ base = NewString(Getattr(s, "name"));
+ }
+ } else {
+ base = NewString(n);
+ }
+ } else {
+ base = NewString(n);
+ }
+ if (base) {
+ Swig_name_inherit(base, derived);
+ Delete(base);
+ }
+ }
+ return bases;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * void Swig_name_str()
+ *
+ * Return a stringified version of a C/C++ symbol from a node.
+ * The node passed in is expected to be a function, constructor, destructor or
+ * variable. Some example return values:
+ * "MyNameSpace::MyTemplate<MyNameSpace::ABC >::~MyTemplate"
+ * "MyNameSpace::ABC::ABC"
+ * "MyNameSpace::ABC::constmethod"
+ * "MyNameSpace::ABC::variablename"
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_str(Node *n) {
+ String *qname;
+ String *qualifier = Swig_symbol_qualified(n);
+ String *name = Swig_scopename_last(Getattr(n, "name"));
+ if (qualifier)
+ qualifier = SwigType_namestr(qualifier);
+
+ /* Very specific hack for template constructors/destructors */
+ if (SwigType_istemplate(name)) {
+ String *nodetype = nodeType(n);
+ if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) {
+ String *nprefix = 0;
+ String *nlast = 0;
+ String *tprefix;
+ Swig_scopename_split(name, &nprefix, &nlast);
+ tprefix = SwigType_templateprefix(nlast);
+ Delete(nlast);
+ Delete(nprefix);
+ Delete(name);
+ name = tprefix;
+ }
+ }
+
+ qname = NewString("");
+ if (qualifier && Len(qualifier) > 0)
+ Printf(qname, "%s::", qualifier);
+ Printf(qname, "%s", SwigType_str(name, 0));
+
+ Delete(name);
+ Delete(qualifier);
+
+ return qname;
+}
+
+/* -----------------------------------------------------------------------------
+ * void Swig_name_decl()
+ *
+ * Return a stringified version of a C/C++ declaration without the return type.
+ * The node passed in is expected to be a function, constructor, destructor or
+ * variable. Some example return values:
+ * "MyNameSpace::MyTemplate<MyNameSpace::ABC >::~MyTemplate()"
+ * "MyNameSpace::ABC::ABC(int,double)"
+ * "MyNameSpace::ABC::constmethod(int) const"
+ * "MyNameSpace::ABC::refqualifiermethod(int) const &"
+ * "MyNameSpace::ABC::variablename"
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_decl(Node *n) {
+ String *qname;
+ String *decl;
+
+ qname = Swig_name_str(n);
+ decl = NewStringf("%s", qname);
+
+ if (!checkAttribute(n, "kind", "variable")) {
+ String *d = Getattr(n, "decl");
+ Printv(decl, "(", ParmList_errorstr(Getattr(n, "parms")), ")", NIL);
+ if (SwigType_isfunction(d)) {
+ SwigType *decl_temp = Copy(d);
+ SwigType *qualifiers = SwigType_pop_function_qualifiers(decl_temp);
+ if (qualifiers) {
+ String *qualifiers_string = SwigType_str(qualifiers, 0);
+ Printv(decl, " ", qualifiers_string, NIL);
+ Delete(qualifiers_string);
+ }
+ Delete(decl_temp);
+ }
+ }
+
+ Delete(qname);
+
+ return decl;
+}
+
+/* -----------------------------------------------------------------------------
+ * void Swig_name_fulldecl()
+ *
+ * Return a stringified version of a C/C++ declaration including the return type.
+ * The node passed in is expected to be a function, constructor or destructor.
+ * Some example return values:
+ * "MyNameSpace::MyTemplate<MyNameSpace::ABC >::~MyTemplate()"
+ * "MyNameSpace::ABC::ABC(int,double)"
+ * "int * MyNameSpace::ABC::constmethod(int) const"
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_fulldecl(Node *n) {
+ String *decl = Swig_name_decl(n);
+ String *type = Getattr(n, "type");
+ String *nodetype = nodeType(n);
+ String *fulldecl;
+ /* add on the return type */
+ if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) {
+ fulldecl = decl;
+ } else {
+ String *t = SwigType_str(type, 0);
+ fulldecl = NewStringf("%s %s", t, decl);
+ Delete(decl);
+ Delete(t);
+ }
+ return fulldecl;
+}
+
diff --git a/contrib/tools/swig/Source/Swig/parms.c b/contrib/tools/swig/Source/Swig/parms.c
new file mode 100644
index 0000000000..11071ce0cd
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/parms.c
@@ -0,0 +1,272 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * parms.c
+ *
+ * Parameter list class.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+
+/* ------------------------------------------------------------------------
+ * NewParm()
+ *
+ * Create a new parameter from datatype 'type' and name 'name' copying
+ * the file and line number from the Node from_node.
+ * ------------------------------------------------------------------------ */
+
+Parm *NewParm(SwigType *type, const_String_or_char_ptr name, Node *from_node) {
+ Parm *p = NewParmWithoutFileLineInfo(type, name);
+ Setfile(p, Getfile(from_node));
+ Setline(p, Getline(from_node));
+ return p;
+}
+
+/* ------------------------------------------------------------------------
+ * NewParmWithoutFileLineInfo()
+ *
+ * Create a new parameter from datatype 'type' and name 'name' without any
+ * file / line numbering information.
+ * ------------------------------------------------------------------------ */
+
+Parm *NewParmWithoutFileLineInfo(SwigType *type, const_String_or_char_ptr name) {
+ Parm *p = NewHash();
+ set_nodeType(p, "parm");
+ if (type) {
+ SwigType *ntype = Copy(type);
+ Setattr(p, "type", ntype);
+ Delete(ntype);
+ }
+ Setattr(p, "name", name);
+ return p;
+}
+
+/* ------------------------------------------------------------------------
+ * NewParmNode()
+ *
+ * Create a new parameter from datatype 'type' and name and symbol table as
+ * well as file and line number from the 'from_node'.
+ * The resulting Parm will be similar to a Node used for typemap lookups.
+ * ------------------------------------------------------------------------ */
+
+Parm *NewParmNode(SwigType *type, Node *from_node) {
+ Parm *p = NewParm(type, Getattr(from_node, "name"), from_node);
+ Setattr(p, "sym:symtab", Getattr(from_node, "sym:symtab"));
+ return p;
+}
+
+/* ------------------------------------------------------------------------
+ * CopyParm()
+ * ------------------------------------------------------------------------ */
+
+Parm *CopyParm(Parm *p) {
+ Parm *np = NewHash();
+ Iterator ki;
+ for (ki = First(p); ki.key; ki = Next(ki)) {
+ if (DohIsString(ki.item)) {
+ DOH *c = Copy(ki.item);
+ Setattr(np,ki.key,c);
+ Delete(c);
+ }
+ }
+ Setfile(np, Getfile(p));
+ Setline(np, Getline(p));
+ return np;
+}
+
+/* ------------------------------------------------------------------
+ * CopyParmListMax()
+ * CopyParmList()
+ * ------------------------------------------------------------------ */
+
+ParmList *CopyParmListMax(ParmList *p, int count) {
+ Parm *np;
+ Parm *pp = 0;
+ Parm *fp = 0;
+
+ if (!p)
+ return 0;
+
+ while (p) {
+ if (count == 0) break;
+ np = CopyParm(p);
+ if (pp) {
+ set_nextSibling(pp, np);
+ Delete(np);
+ } else {
+ fp = np;
+ }
+ pp = np;
+ p = nextSibling(p);
+ count--;
+ }
+ return fp;
+}
+
+ParmList *CopyParmList(ParmList *p) {
+ return CopyParmListMax(p,-1);
+}
+
+/* -----------------------------------------------------------------------------
+ * int ParmList_numrequired(). Return number of required arguments
+ * ----------------------------------------------------------------------------- */
+
+int ParmList_numrequired(ParmList *p) {
+ int i = 0;
+ while (p) {
+ SwigType *t = Getattr(p, "type");
+ String *value = Getattr(p, "value");
+ if (value)
+ return i;
+ if (!(SwigType_type(t) == T_VOID))
+ i++;
+ else
+ break;
+ p = nextSibling(p);
+ }
+ return i;
+}
+
+/* -----------------------------------------------------------------------------
+ * int ParmList_len()
+ * ----------------------------------------------------------------------------- */
+
+int ParmList_len(ParmList *p) {
+ int i = 0;
+ while (p) {
+ i++;
+ p = nextSibling(p);
+ }
+ return i;
+}
+
+/* ---------------------------------------------------------------------
+ * get_empty_type()
+ * ---------------------------------------------------------------------- */
+
+static SwigType *get_empty_type(void) {
+ return NewStringEmpty();
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_str()
+ *
+ * Generates a string of parameters
+ * ---------------------------------------------------------------------- */
+
+String *ParmList_str(ParmList *p) {
+ String *out = NewStringEmpty();
+ while (p) {
+ String *type = Getattr(p, "type");
+ String *pstr = SwigType_str(type ? type : get_empty_type(), Getattr(p, "name"));
+ Append(out, pstr);
+ p = nextSibling(p);
+ if (p) {
+ Append(out, ",");
+ }
+ Delete(pstr);
+ }
+ return out;
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_str_defaultargs()
+ *
+ * Generates a string of parameters including default arguments
+ * ---------------------------------------------------------------------- */
+
+String *ParmList_str_defaultargs(ParmList *p) {
+ String *out = NewStringEmpty();
+ while (p) {
+ String *value = Getattr(p, "value");
+ String *type = Getattr(p, "type");
+ String *pstr = SwigType_str(type ? type : get_empty_type(), Getattr(p, "name"));
+ Append(out, pstr);
+ if (value) {
+ Printf(out, "=%s", value);
+ }
+ p = nextSibling(p);
+ if (p) {
+ Append(out, ",");
+ }
+ Delete(pstr);
+ }
+ return out;
+}
+
+/* -----------------------------------------------------------------------------
+ * ParmList_str_multibrackets()
+ *
+ * Generates a string of parameters including default arguments adding brackets
+ * if more than one parameter
+ * ----------------------------------------------------------------------------- */
+
+String *ParmList_str_multibrackets(ParmList *p) {
+ String *out;
+ String *parm_str = ParmList_str_defaultargs(p);
+ if (ParmList_len(p) > 1)
+ out = NewStringf("(%s)", parm_str);
+ else
+ out = NewStringf("%s", parm_str);
+ Delete(parm_str);
+ return out;
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_protostr()
+ *
+ * Generate a prototype string.
+ * ---------------------------------------------------------------------- */
+
+String *ParmList_protostr(ParmList *p) {
+ String *out = NewStringEmpty();
+ while (p) {
+ String *type = Getattr(p, "type");
+ String *pstr = SwigType_str(type ? type : get_empty_type(), 0);
+ Append(out, pstr);
+ p = nextSibling(p);
+ if (p) {
+ Append(out, ",");
+ }
+ Delete(pstr);
+ }
+ return out;
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_has_defaultargs()
+ *
+ * Returns 1 if the parameter list passed in is has one or more default
+ * arguments. Otherwise returns 0.
+ * ---------------------------------------------------------------------- */
+
+int ParmList_has_defaultargs(ParmList *p) {
+ while (p) {
+ if (Getattr(p, "value")) {
+ return 1;
+ }
+ p = nextSibling(p);
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_has_varargs()
+ *
+ * Returns 1 if the parameter list passed in has varargs.
+ * Otherwise returns 0.
+ * ---------------------------------------------------------------------- */
+
+int ParmList_has_varargs(ParmList *p) {
+ Parm *lp = 0;
+ while (p) {
+ lp = p;
+ p = nextSibling(p);
+ }
+ return lp ? SwigType_isvarargs(Getattr(lp, "type")) : 0;
+}
diff --git a/contrib/tools/swig/Source/Swig/scanner.c b/contrib/tools/swig/Source/Swig/scanner.c
new file mode 100644
index 0000000000..9dbb353648
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/scanner.c
@@ -0,0 +1,1898 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * scanner.c
+ *
+ * This file implements a general purpose C/C++ compatible lexical scanner.
+ * This scanner isn't intended to be plugged directly into a parser built
+ * with yacc. Rather, it contains a lot of generic code that could be used
+ * to easily construct yacc-compatible scanners.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <ctype.h>
+
+extern String *cparse_file;
+extern int cparse_line;
+extern int cparse_cplusplus;
+extern int cparse_start_line;
+
+struct Scanner {
+ String *text; /* Current token value */
+ List *scanobjs; /* Objects being scanned */
+ String *str; /* Current object being scanned */
+ char *idstart; /* Optional identifier start characters */
+ int nexttoken; /* Next token to be returned */
+ int start_line; /* Starting line of certain declarations */
+ int line;
+ int yylen; /* Length of text pushed into text */
+ String *file;
+ String *error; /* Last error message (if any) */
+ int error_line; /* Error line number */
+ int freeze_line; /* Suspend line number updates */
+ List *brackets; /* Current level of < > brackets on each level */
+};
+
+typedef struct Locator {
+ String *filename;
+ int line_number;
+ struct Locator *next;
+} Locator;
+static int follow_locators = 0;
+
+static void brackets_push(Scanner *);
+static void brackets_clear(Scanner *);
+
+/* -----------------------------------------------------------------------------
+ * NewScanner()
+ *
+ * Create a new scanner object
+ * ----------------------------------------------------------------------------- */
+
+Scanner *NewScanner(void) {
+ Scanner *s;
+ s = (Scanner *) Malloc(sizeof(Scanner));
+ s->line = 1;
+ s->file = 0;
+ s->nexttoken = -1;
+ s->start_line = 1;
+ s->yylen = 0;
+ s->idstart = NULL;
+ s->scanobjs = NewList();
+ s->text = NewStringEmpty();
+ s->str = 0;
+ s->error = 0;
+ s->error_line = 0;
+ s->freeze_line = 0;
+ s->brackets = NewList();
+ brackets_push(s);
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * DelScanner()
+ *
+ * Delete a scanner object.
+ * ----------------------------------------------------------------------------- */
+
+void DelScanner(Scanner *s) {
+ assert(s);
+ Delete(s->scanobjs);
+ Delete(s->brackets);
+ Delete(s->text);
+ Delete(s->file);
+ Delete(s->error);
+ Delete(s->str);
+ Free(s->idstart);
+ Free(s);
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_clear()
+ *
+ * Clear the contents of a scanner object.
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_clear(Scanner *s) {
+ assert(s);
+ Delete(s->str);
+ Clear(s->text);
+ Clear(s->scanobjs);
+ brackets_clear(s);
+ Delete(s->error);
+ s->str = 0;
+ s->error = 0;
+ s->line = 1;
+ s->nexttoken = -1;
+ s->start_line = 0;
+ s->yylen = 0;
+ /* Should these be cleared too?
+ s->idstart;
+ s->file;
+ s->error_line;
+ s->freeze_line;
+ */
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_push()
+ *
+ * Push some new text into the scanner. The scanner will start parsing this text
+ * immediately before returning to the old text.
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_push(Scanner *s, String *txt) {
+ assert(s && txt);
+ Push(s->scanobjs, txt);
+ if (s->str) {
+ Setline(s->str,s->line);
+ Delete(s->str);
+ }
+ s->str = txt;
+ DohIncref(s->str);
+ s->line = Getline(txt);
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_pushtoken()
+ *
+ * Push a token into the scanner. This token will be returned on the next
+ * call to Scanner_token().
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_pushtoken(Scanner *s, int nt, const_String_or_char_ptr val) {
+ assert(s);
+ assert((nt >= 0) && (nt < SWIG_MAXTOKENS));
+ s->nexttoken = nt;
+ if ( Char(val) != Char(s->text) ) {
+ Clear(s->text);
+ Append(s->text,val);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_set_location()
+ *
+ * Set the file and line number location of the scanner.
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_set_location(Scanner *s, String *file, int line) {
+ Setline(s->str, line);
+ Setfile(s->str, file);
+ s->line = line;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_file()
+ *
+ * Get the current file.
+ * ----------------------------------------------------------------------------- */
+
+String *Scanner_file(Scanner *s) {
+ return Getfile(s->str);
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_line()
+ *
+ * Get the current line number
+ * ----------------------------------------------------------------------------- */
+int Scanner_line(Scanner *s) {
+ return s->line;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_start_line()
+ *
+ * Get the line number on which the current token starts
+ * ----------------------------------------------------------------------------- */
+int Scanner_start_line(Scanner *s) {
+ return s->start_line;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_idstart()
+ *
+ * Change the set of additional characters that can be used to start an identifier.
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_idstart(Scanner *s, const char *id) {
+ Free(s->idstart);
+ s->idstart = Swig_copy_string(id);
+}
+
+/* -----------------------------------------------------------------------------
+ * nextchar()
+ *
+ * Returns the next character from the scanner or 0 if end of the string.
+ * ----------------------------------------------------------------------------- */
+static char nextchar(Scanner *s) {
+ int nc;
+ if (!s->str)
+ return 0;
+ while ((nc = Getc(s->str)) == EOF) {
+ Delete(s->str);
+ s->str = 0;
+ Delitem(s->scanobjs, 0);
+ if (Len(s->scanobjs) == 0)
+ return 0;
+ s->str = Getitem(s->scanobjs, 0);
+ s->line = Getline(s->str);
+ DohIncref(s->str);
+ }
+ if ((nc == '\n') && (!s->freeze_line))
+ s->line++;
+ Putc(nc,s->text);
+ return (char)nc;
+}
+
+/* -----------------------------------------------------------------------------
+ * set_error()
+ *
+ * Sets error information on the scanner.
+ * ----------------------------------------------------------------------------- */
+
+static void set_error(Scanner *s, int line, const_String_or_char_ptr msg) {
+ s->error_line = line;
+ s->error = NewString(msg);
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_errmsg()
+ * Scanner_errline()
+ *
+ * Returns error information (if any)
+ * ----------------------------------------------------------------------------- */
+
+String *Scanner_errmsg(Scanner *s) {
+ return s->error;
+}
+
+int Scanner_errline(Scanner *s) {
+ return s->error_line;
+}
+
+/* -----------------------------------------------------------------------------
+ * freeze_line()
+ *
+ * Freezes the current line number.
+ * ----------------------------------------------------------------------------- */
+
+static void freeze_line(Scanner *s, int val) {
+ s->freeze_line = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_count()
+ *
+ * Returns the number of brackets at the current depth.
+ * A syntax error with unbalanced ) brackets will result in a NULL pointer return.
+ * ----------------------------------------------------------------------------- */
+static int *brackets_count(Scanner *s) {
+ int *count;
+ if (Len(s->brackets) > 0)
+ count = (int *)Data(Getitem(s->brackets, 0));
+ else
+ count = 0;
+ return count;
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_clear()
+ *
+ * Resets the current depth and clears all brackets.
+ * Usually called at the end of statements;
+ * ----------------------------------------------------------------------------- */
+static void brackets_clear(Scanner *s) {
+ Clear(s->brackets);
+ brackets_push(s); /* base bracket count should always be created */
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_increment()
+ *
+ * Increases the number of brackets at the current depth.
+ * Usually called when a single '<' is found.
+ * ----------------------------------------------------------------------------- */
+static void brackets_increment(Scanner *s) {
+ int *count = brackets_count(s);
+ if (count)
+ (*count)++;
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_decrement()
+ *
+ * Decreases the number of brackets at the current depth.
+ * Usually called when a single '>' is found.
+ * ----------------------------------------------------------------------------- */
+static void brackets_decrement(Scanner *s) {
+ int *count = brackets_count(s);
+ if (count)
+ (*count)--;
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_reset()
+ *
+ * Sets the number of '<' brackets back to zero. Called at the point where
+ * it is no longer possible to have a matching closing >> pair for a template.
+ * ----------------------------------------------------------------------------- */
+static void brackets_reset(Scanner *s) {
+ int *count = brackets_count(s);
+ if (count)
+ *count = 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_push()
+ *
+ * Increases the depth of brackets.
+ * Usually called when '(' is found.
+ * ----------------------------------------------------------------------------- */
+static void brackets_push(Scanner *s) {
+ int *newInt = (int *)Malloc(sizeof(int));
+ *newInt = 0;
+ Push(s->brackets, NewVoid(newInt, Free));
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_pop()
+ *
+ * Decreases the depth of brackets.
+ * Usually called when ')' is found.
+ * ----------------------------------------------------------------------------- */
+static void brackets_pop(Scanner *s) {
+ if (Len(s->brackets) > 0) /* protect against unbalanced ')' brackets */
+ Delitem(s->brackets, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_allow_shift()
+ *
+ * Return 1 to allow shift (>>), or 0 if (>>) should be split into (> >).
+ * This is for C++11 template syntax for closing templates.
+ * ----------------------------------------------------------------------------- */
+static int brackets_allow_shift(Scanner *s) {
+ int *count = brackets_count(s);
+ return !count || (*count <= 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * retract()
+ *
+ * Retract n characters
+ * ----------------------------------------------------------------------------- */
+static void retract(Scanner *s, int n) {
+ int i, l;
+ char *str;
+
+ str = Char(s->text);
+ l = Len(s->text);
+ assert(n <= l);
+ for (i = 0; i < n; i++) {
+ if (str[l - 1] == '\n') {
+ if (!s->freeze_line) s->line--;
+ }
+ (void)Seek(s->str, -1, SEEK_CUR);
+ Delitem(s->text, DOH_END);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * get_escape()
+ *
+ * Get escape sequence. Called when a backslash is found in a string
+ * ----------------------------------------------------------------------------- */
+
+static void get_escape(Scanner *s) {
+ int result = 0;
+ int state = 0;
+ int c;
+
+ while (1) {
+ c = nextchar(s);
+ if (c == 0)
+ break;
+ switch (state) {
+ case 0:
+ if (c == 'n') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\n");
+ return;
+ }
+ if (c == 'r') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\r");
+ return;
+ }
+ if (c == 't') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\t");
+ return;
+ }
+ if (c == 'a') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\a");
+ return;
+ }
+ if (c == 'b') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\b");
+ return;
+ }
+ if (c == 'f') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\f");
+ return;
+ }
+ if (c == '\\') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\\");
+ return;
+ }
+ if (c == 'v') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\v");
+ return;
+ }
+ if (c == 'e') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\033");
+ return;
+ }
+ if (c == '\'') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\'");
+ return;
+ }
+ if (c == '\"') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\"");
+ return;
+ }
+ if (c == '\n') {
+ Delitem(s->text, DOH_END);
+ return;
+ }
+ if (isdigit(c)) {
+ state = 10;
+ result = (c - '0');
+ Delitem(s->text, DOH_END);
+ } else if (c == 'x') {
+ state = 20;
+ Delitem(s->text, DOH_END);
+ } else {
+ char tmp[3];
+ tmp[0] = '\\';
+ tmp[1] = (char)c;
+ tmp[2] = 0;
+ Delitem(s->text, DOH_END);
+ Append(s->text, tmp);
+ return;
+ }
+ break;
+ case 10:
+ if (!isdigit(c)) {
+ retract(s,1);
+ Putc((char)result,s->text);
+ return;
+ }
+ result = (result << 3) + (c - '0');
+ Delitem(s->text, DOH_END);
+ break;
+ case 20:
+ if (!isxdigit(c)) {
+ retract(s,1);
+ Putc((char)result, s->text);
+ return;
+ }
+ if (isdigit(c))
+ result = (result << 4) + (c - '0');
+ else
+ result = (result << 4) + (10 + tolower(c) - 'a');
+ Delitem(s->text, DOH_END);
+ break;
+ }
+ }
+ return;
+}
+
+/* -----------------------------------------------------------------------------
+ * look()
+ *
+ * Return the raw value of the next token.
+ * ----------------------------------------------------------------------------- */
+
+static int look(Scanner *s) {
+ int state = 0;
+ int c = 0;
+ String *str_delimiter = 0;
+
+ Clear(s->text);
+ s->start_line = s->line;
+ Setfile(s->text, Getfile(s->str));
+
+
+ while (1) {
+ switch (state) {
+ case 0:
+ if ((c = nextchar(s)) == 0)
+ return (0);
+
+ /* Process delimiters */
+
+ if (c == '\n') {
+ return SWIG_TOKEN_ENDLINE;
+ } else if (!isspace(c)) {
+ retract(s, 1);
+ state = 1000;
+ Clear(s->text);
+ Setline(s->text, s->line);
+ Setfile(s->text, Getfile(s->str));
+ }
+ break;
+
+ case 1000:
+ if ((c = nextchar(s)) == 0)
+ return (0);
+ if (c == '%')
+ state = 4; /* Possibly a SWIG directive */
+
+ /* Look for possible identifiers or unicode/delimiter strings */
+ else if ((isalpha(c)) || (c == '_') ||
+ (s->idstart && strchr(s->idstart, c))) {
+ state = 7;
+ }
+
+ /* Look for single character symbols */
+
+ else if (c == '(') {
+ brackets_push(s);
+ return SWIG_TOKEN_LPAREN;
+ }
+ else if (c == ')') {
+ brackets_pop(s);
+ return SWIG_TOKEN_RPAREN;
+ }
+ else if (c == ';') {
+ brackets_clear(s);
+ return SWIG_TOKEN_SEMI;
+ }
+ else if (c == ',')
+ return SWIG_TOKEN_COMMA;
+ else if (c == '*')
+ state = 220;
+ else if (c == '}')
+ return SWIG_TOKEN_RBRACE;
+ else if (c == '{') {
+ brackets_reset(s);
+ return SWIG_TOKEN_LBRACE;
+ }
+ else if (c == '=')
+ state = 33;
+ else if (c == '+')
+ state = 200;
+ else if (c == '-')
+ state = 210;
+ else if (c == '&')
+ state = 31;
+ else if (c == '|')
+ state = 32;
+ else if (c == '^')
+ state = 230;
+ else if (c == '<')
+ state = 60;
+ else if (c == '>')
+ state = 61;
+ else if (c == '~')
+ return SWIG_TOKEN_NOT;
+ else if (c == '!')
+ state = 3;
+ else if (c == '\\')
+ return SWIG_TOKEN_BACKSLASH;
+ else if (c == '@')
+ return SWIG_TOKEN_AT;
+ else if (c == '$')
+ state = 75;
+ else if (c == '#')
+ return SWIG_TOKEN_POUND;
+ else if (c == '?')
+ return SWIG_TOKEN_QUESTION;
+
+ /* Look for multi-character sequences */
+
+ else if (c == '/') {
+ state = 1; /* Comment (maybe) */
+ s->start_line = s->line;
+ }
+
+ else if (c == ':')
+ state = 5; /* maybe double colon */
+ else if (c == '0')
+ state = 83; /* An octal or hex value */
+ else if (c == '\"') {
+ state = 2; /* A string constant */
+ s->start_line = s->line;
+ Clear(s->text);
+ }
+ else if (c == '\'') {
+ s->start_line = s->line;
+ Clear(s->text);
+ state = 9; /* A character constant */
+ } else if (c == '`') {
+ s->start_line = s->line;
+ Clear(s->text);
+ state = 900;
+ }
+
+ else if (c == '.')
+ state = 100; /* Maybe a number, maybe ellipsis, just a period */
+ else if (c == '[')
+ state = 102; /* Maybe a bracket or a double bracket */
+ else if (c == ']')
+ state = 103; /* Maybe a bracket or a double bracket */
+ else if (isdigit(c))
+ state = 8; /* A numerical value */
+ else
+ state = 99; /* An error */
+ break;
+
+ case 1: /* Comment block */
+ if ((c = nextchar(s)) == 0)
+ return (0);
+ if (c == '/') {
+ state = 10; /* C++ style comment */
+ Clear(s->text);
+ Setline(s->text, Getline(s->str));
+ Setfile(s->text, Getfile(s->str));
+ Append(s->text, "//");
+ } else if (c == '*') {
+ state = 11; /* C style comment */
+ Clear(s->text);
+ Setline(s->text, Getline(s->str));
+ Setfile(s->text, Getfile(s->str));
+ Append(s->text, "/*");
+ } else if (c == '=') {
+ return SWIG_TOKEN_DIVEQUAL;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_SLASH;
+ }
+ break;
+ case 10: /* C++ style comment */
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '\n') {
+ retract(s,1);
+ return SWIG_TOKEN_COMMENT;
+ } else {
+ state = 10;
+ }
+ break;
+ case 11: /* C style comment block */
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '*') {
+ state = 12;
+ } else {
+ state = 11;
+ }
+ break;
+ case 12: /* Still in C style comment */
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '*') {
+ state = 12;
+ } else if (c == '/') {
+ return SWIG_TOKEN_COMMENT;
+ } else {
+ state = 11;
+ }
+ break;
+
+ case 2: /* Processing a string */
+ if (!str_delimiter) {
+ state=20;
+ break;
+ }
+
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated string\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ else if (c == '(') {
+ state = 20;
+ }
+ else {
+ char temp[2] = { 0, 0 };
+ temp[0] = c;
+ Append( str_delimiter, temp );
+ }
+
+ break;
+
+ case 20: /* Inside the string */
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated string\n");
+ return SWIG_TOKEN_ERROR;
+ }
+
+ if (!str_delimiter) { /* Ordinary string: "value" */
+ if (c == '\"') {
+ Delitem(s->text, DOH_END);
+ return SWIG_TOKEN_STRING;
+ } else if (c == '\\') {
+ Delitem(s->text, DOH_END);
+ get_escape(s);
+ }
+ } else { /* Custom delimiter string: R"XXXX(value)XXXX" */
+ if (c==')') {
+ int i=0;
+ String *end_delimiter = NewStringEmpty();
+ while ((c = nextchar(s)) != 0 && c!='\"') {
+ char temp[2] = { 0, 0 };
+ temp[0] = c;
+ Append( end_delimiter, temp );
+ i++;
+ }
+
+ if (Strcmp( str_delimiter, end_delimiter )==0) {
+ int len = Len(s->text);
+ Delslice(s->text, len - 2 - Len(str_delimiter), len); /* Delete ending )XXXX" */
+ Delslice(s->text, 0, Len(str_delimiter) + 1); /* Delete starting XXXX( */
+ Delete( end_delimiter ); /* Correct end delimiter )XXXX" occurred */
+ Delete( str_delimiter );
+ str_delimiter = 0;
+ return SWIG_TOKEN_STRING;
+ } else { /* Incorrect end delimiter occurred */
+ if (c == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated raw string, started with R\"%s( is not terminated by )%s\"\n", str_delimiter, str_delimiter);
+ return SWIG_TOKEN_ERROR;
+ }
+ retract( s, i );
+ Delete( end_delimiter );
+ }
+ }
+ }
+
+ break;
+
+ case 3: /* Maybe a not equals */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_LNOT;
+ else if (c == '=')
+ return SWIG_TOKEN_NOTEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_LNOT;
+ }
+ break;
+
+ case 31: /* AND or Logical AND or ANDEQUAL */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_AND;
+ else if (c == '&')
+ return SWIG_TOKEN_LAND;
+ else if (c == '=')
+ return SWIG_TOKEN_ANDEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_AND;
+ }
+ break;
+
+ case 32: /* OR or Logical OR */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_OR;
+ else if (c == '|')
+ return SWIG_TOKEN_LOR;
+ else if (c == '=')
+ return SWIG_TOKEN_OREQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_OR;
+ }
+ break;
+
+ case 33: /* EQUAL or EQUALTO */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_EQUAL;
+ else if (c == '=')
+ return SWIG_TOKEN_EQUALTO;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_EQUAL;
+ }
+ break;
+
+ case 4: /* A wrapper generator directive (maybe) */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_PERCENT;
+ if (c == '{') {
+ state = 40; /* Include block */
+ Clear(s->text);
+ Setline(s->text, Getline(s->str));
+ Setfile(s->text, Getfile(s->str));
+ s->start_line = s->line;
+ } else if (s->idstart && strchr(s->idstart, '%') &&
+ ((isalpha(c)) || (c == '_'))) {
+ state = 7;
+ } else if (c == '=') {
+ return SWIG_TOKEN_MODEQUAL;
+ } else if (c == '}') {
+ Swig_error(cparse_file, cparse_line, "Syntax error. Extraneous '%%}'\n");
+ Exit(EXIT_FAILURE);
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_PERCENT;
+ }
+ break;
+
+ case 40: /* Process an include block */
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated block\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '%')
+ state = 41;
+ break;
+ case 41: /* Still processing include block */
+ if ((c = nextchar(s)) == 0) {
+ set_error(s,s->start_line,"Unterminated code block");
+ return 0;
+ }
+ if (c == '}') {
+ Delitem(s->text, DOH_END);
+ Delitem(s->text, DOH_END);
+ Seek(s->text,0,SEEK_SET);
+ return SWIG_TOKEN_CODEBLOCK;
+ } else {
+ state = 40;
+ }
+ break;
+
+ case 5: /* Maybe a double colon */
+
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_COLON;
+ if (c == ':')
+ state = 50;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_COLON;
+ }
+ break;
+
+ case 50: /* DCOLON, DCOLONSTAR */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_DCOLON;
+ else if (c == '*')
+ return SWIG_TOKEN_DCOLONSTAR;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_DCOLON;
+ }
+ break;
+
+ case 60: /* shift operators */
+ if ((c = nextchar(s)) == 0) {
+ brackets_increment(s);
+ return SWIG_TOKEN_LESSTHAN;
+ }
+ if (c == '<')
+ state = 240;
+ else if (c == '=') {
+ if ((c = nextchar(s)) == 0) {
+ return SWIG_TOKEN_LTEQUAL;
+ } else if (c == '>' && cparse_cplusplus) { /* Spaceship operator */
+ return SWIG_TOKEN_LTEQUALGT;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_LTEQUAL;
+ }
+ } else {
+ retract(s, 1);
+ brackets_increment(s);
+ return SWIG_TOKEN_LESSTHAN;
+ }
+ break;
+ case 61:
+ if ((c = nextchar(s)) == 0) {
+ brackets_decrement(s);
+ return SWIG_TOKEN_GREATERTHAN;
+ }
+ if (c == '>' && brackets_allow_shift(s))
+ state = 250;
+ else if (c == '=')
+ return SWIG_TOKEN_GTEQUAL;
+ else {
+ retract(s, 1);
+ brackets_decrement(s);
+ return SWIG_TOKEN_GREATERTHAN;
+ }
+ break;
+
+ case 7: /* Identifier or true/false or unicode/custom delimiter string */
+ if (c == 'R') { /* Possibly CUSTOM DELIMITER string */
+ state = 72;
+ break;
+ }
+ else if (c == 'L') { /* Probably identifier but may be a wide string literal */
+ state = 77;
+ break;
+ }
+ else if (c != 'u' && c != 'U') { /* Definitely an identifier */
+ state = 70;
+ break;
+ }
+
+ if ((c = nextchar(s)) == 0) {
+ state = 76;
+ }
+ else if (c == '\"') { /* Definitely u, U or L string */
+ retract(s, 1);
+ state = 1000;
+ }
+ else if (c == '\'') { /* Definitely u, U or L char */
+ retract(s, 1);
+ state = 77;
+ }
+ else if (c == 'R') { /* Possibly CUSTOM DELIMITER u, U, L string */
+ state = 73;
+ }
+ else if (c == '8') { /* Possibly u8 string/char */
+ state = 71;
+ }
+ else {
+ retract(s, 1); /* Definitely an identifier */
+ state = 70;
+ }
+ break;
+
+ case 70: /* Identifier */
+ if ((c = nextchar(s)) == 0)
+ state = 76;
+ else if (isalnum(c) || (c == '_') || (c == '$')) {
+ state = 70;
+ } else {
+ retract(s, 1);
+ state = 76;
+ }
+ break;
+
+ case 71: /* Possibly u8 string/char */
+ if ((c = nextchar(s)) == 0) {
+ state = 76;
+ }
+ else if (c=='\"') {
+ retract(s, 1); /* Definitely u8 string */
+ state = 1000;
+ }
+ else if (c=='\'') {
+ retract(s, 1); /* Definitely u8 char */
+ state = 77;
+ }
+ else if (c=='R') {
+ state = 74; /* Possibly CUSTOM DELIMITER u8 string */
+ }
+ else {
+ retract(s, 2); /* Definitely an identifier. Retract 8" */
+ state = 70;
+ }
+
+ break;
+
+ case 72: /* Possibly CUSTOM DELIMITER string */
+ case 73:
+ case 74:
+ if ((c = nextchar(s)) == 0) {
+ state = 76;
+ }
+ else if (c=='\"') {
+ retract(s, 1); /* Definitely custom delimiter u, U or L string */
+ str_delimiter = NewStringEmpty();
+ state = 1000;
+ }
+ else {
+ if (state==72) {
+ retract(s, 1); /* Definitely an identifier. Retract ? */
+ }
+ else if (state==73) {
+ retract(s, 2); /* Definitely an identifier. Retract R? */
+ }
+ else if (state==74) {
+ retract(s, 3); /* Definitely an identifier. Retract 8R? */
+ }
+ state = 70;
+ }
+
+ break;
+
+ case 75: /* Special identifier $ */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_DOLLAR;
+ if (isalnum(c) || (c == '_') || (c == '*') || (c == '&')) {
+ state = 70;
+ } else {
+ retract(s,1);
+ if (Len(s->text) == 1) return SWIG_TOKEN_DOLLAR;
+ state = 76;
+ }
+ break;
+
+ case 76: /* Identifier or true/false */
+ if (cparse_cplusplus) {
+ if (Strcmp(s->text, "true") == 0)
+ return SWIG_TOKEN_BOOL;
+ else if (Strcmp(s->text, "false") == 0)
+ return SWIG_TOKEN_BOOL;
+ }
+ return SWIG_TOKEN_ID;
+ break;
+
+ case 77: /*identifier or wide string literal*/
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_ID;
+ else if (c == '\"') {
+ s->start_line = s->line;
+ Clear(s->text);
+ state = 78;
+ }
+ else if (c == '\'') {
+ s->start_line = s->line;
+ Clear(s->text);
+ state = 79;
+ }
+ else if (isalnum(c) || (c == '_') || (c == '$'))
+ state = 7;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_ID;
+ }
+ break;
+
+ case 78: /* Processing a wide string literal*/
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated wide string\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '\"') {
+ Delitem(s->text, DOH_END);
+ return SWIG_TOKEN_WSTRING;
+ } else if (c == '\\') {
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated wide string\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ }
+ break;
+
+ case 79: /* Processing a wide char literal */
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated wide character constant\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '\'') {
+ Delitem(s->text, DOH_END);
+ return (SWIG_TOKEN_WCHAR);
+ } else if (c == '\\') {
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated wide character literal\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ }
+ break;
+
+ case 8: /* A numerical digit */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_INT;
+ if (c == '.') {
+ state = 81;
+ } else if ((c == 'e') || (c == 'E')) {
+ state = 82;
+ } else if ((c == 'f') || (c == 'F')) {
+ Delitem(s->text, DOH_END);
+ return SWIG_TOKEN_FLOAT;
+ } else if (isdigit(c)) {
+ state = 8;
+ } else if ((c == 'l') || (c == 'L')) {
+ state = 87;
+ } else if ((c == 'u') || (c == 'U')) {
+ state = 88;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_INT;
+ }
+ break;
+ case 81: /* A floating pointer number of some sort */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_DOUBLE;
+ if (isdigit(c))
+ state = 81;
+ else if ((c == 'e') || (c == 'E'))
+ state = 820;
+ else if ((c == 'f') || (c == 'F')) {
+ Delitem(s->text, DOH_END);
+ return SWIG_TOKEN_FLOAT;
+ } else if ((c == 'l') || (c == 'L')) {
+ Delitem(s->text, DOH_END);
+ return SWIG_TOKEN_DOUBLE;
+ } else {
+ retract(s, 1);
+ return (SWIG_TOKEN_DOUBLE);
+ }
+ break;
+ case 82:
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if ((isdigit(c)) || (c == '-') || (c == '+'))
+ state = 86;
+ else {
+ retract(s, 2);
+ Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ break;
+ case 820:
+ /* Like case 82, but we've seen a decimal point. */
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if ((isdigit(c)) || (c == '-') || (c == '+'))
+ state = 86;
+ else {
+ retract(s, 2);
+ Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ break;
+ case 83:
+ /* Might be a hexadecimal or octal number */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_INT;
+ if (isdigit(c))
+ state = 84;
+ else if ((c == 'e') || (c == 'E'))
+ state = 82;
+ else if ((c == 'x') || (c == 'X'))
+ state = 85;
+ else if ((c == 'b') || (c == 'B'))
+ state = 850;
+ else if (c == '.')
+ state = 81;
+ else if ((c == 'l') || (c == 'L')) {
+ state = 87;
+ } else if ((c == 'u') || (c == 'U')) {
+ state = 88;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_INT;
+ }
+ break;
+ case 84:
+ /* This is an octal number */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_INT;
+ if (isdigit(c))
+ state = 84;
+ else if (c == '.')
+ state = 81;
+ else if ((c == 'e') || (c == 'E'))
+ state = 82;
+ else if ((c == 'l') || (c == 'L')) {
+ state = 87;
+ } else if ((c == 'u') || (c == 'U')) {
+ state = 88;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_INT;
+ }
+ break;
+ case 85:
+ /* This is an hex number */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_INT;
+ if (isxdigit(c))
+ state = 85;
+ else if (c == '.') /* hexadecimal float */
+ state = 860;
+ else if ((c == 'p') || (c == 'P')) /* hexadecimal float */
+ state = 820;
+ else if ((c == 'l') || (c == 'L')) {
+ state = 87;
+ } else if ((c == 'u') || (c == 'U')) {
+ state = 88;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_INT;
+ }
+ break;
+ case 850:
+ /* This is a binary number */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_INT;
+ if ((c == '0') || (c == '1'))
+ state = 850;
+ else if ((c == 'l') || (c == 'L')) {
+ state = 87;
+ } else if ((c == 'u') || (c == 'U')) {
+ state = 88;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_INT;
+ }
+ break;
+ case 860:
+ /* hexadecimal float */
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (isxdigit(c))
+ state = 860;
+ else if ((c == 'p') || (c == 'P'))
+ state = 820;
+ else {
+ retract(s, 2);
+ Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ break;
+ case 86:
+ /* Rest of floating point number */
+
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_DOUBLE;
+ if (isdigit(c))
+ state = 86;
+ else if ((c == 'f') || (c == 'F')) {
+ Delitem(s->text, DOH_END);
+ return SWIG_TOKEN_FLOAT;
+ } else if ((c == 'l') || (c == 'L')) {
+ Delitem(s->text, DOH_END);
+ return SWIG_TOKEN_DOUBLE;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_DOUBLE;
+ }
+ break;
+
+ case 87:
+ /* A long integer of some sort */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_LONG;
+ if ((c == 'u') || (c == 'U')) {
+ return SWIG_TOKEN_ULONG;
+ } else if ((c == 'l') || (c == 'L')) {
+ state = 870;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_LONG;
+ }
+ break;
+
+ /* A long long integer */
+
+ case 870:
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_LONGLONG;
+ if ((c == 'u') || (c == 'U')) {
+ return SWIG_TOKEN_ULONGLONG;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_LONGLONG;
+ }
+
+ /* An unsigned number */
+ case 88:
+
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_UINT;
+ if ((c == 'l') || (c == 'L')) {
+ state = 880;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_UINT;
+ }
+ break;
+
+ /* Possibly an unsigned long long or unsigned long */
+ case 880:
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_ULONG;
+ if ((c == 'l') || (c == 'L'))
+ return SWIG_TOKEN_ULONGLONG;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_ULONG;
+ }
+
+ /* A character constant */
+ case 9:
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated character constant\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '\'') {
+ Delitem(s->text, DOH_END);
+ return (SWIG_TOKEN_CHAR);
+ } else if (c == '\\') {
+ Delitem(s->text, DOH_END);
+ get_escape(s);
+ }
+ break;
+
+ /* A period or an ellipsis or maybe a floating point number */
+
+ case 100:
+ if ((c = nextchar(s)) == 0)
+ return (0);
+ if (isdigit(c))
+ state = 81;
+ else if (c == '.')
+ state = 101;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_PERIOD;
+ }
+ break;
+
+ /* An ellipsis */
+
+ case 101:
+ if ((c = nextchar(s)) == 0)
+ return (0);
+ if (c == '.') {
+ return SWIG_TOKEN_ELLIPSIS;
+ } else {
+ retract(s, 2);
+ return SWIG_TOKEN_PERIOD;
+ }
+ break;
+
+ /* A left bracket or a double left bracket */
+ case 102:
+
+ if ((c = nextchar(s)) == 0) {
+ return SWIG_TOKEN_LBRACKET;
+ } else if (c == '[') {
+ return SWIG_TOKEN_LLBRACKET;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_LBRACKET;
+ }
+ break;
+
+ /* a right bracket or a double right bracket */
+ case 103:
+ if ((c = nextchar(s)) == 0) {
+ return SWIG_TOKEN_RBRACKET;
+ } else if (c == ']') {
+ return SWIG_TOKEN_RRBRACKET;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_RBRACKET;
+ }
+ break;
+
+ case 200: /* PLUS, PLUSPLUS, PLUSEQUAL */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_PLUS;
+ else if (c == '+')
+ return SWIG_TOKEN_PLUSPLUS;
+ else if (c == '=')
+ return SWIG_TOKEN_PLUSEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_PLUS;
+ }
+ break;
+
+ case 210: /* MINUS, MINUSMINUS, MINUSEQUAL, ARROW */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_MINUS;
+ else if (c == '-')
+ return SWIG_TOKEN_MINUSMINUS;
+ else if (c == '=')
+ return SWIG_TOKEN_MINUSEQUAL;
+ else if (c == '>')
+ state = 211;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_MINUS;
+ }
+ break;
+
+ case 211: /* ARROW, ARROWSTAR */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_ARROW;
+ else if (c == '*')
+ return SWIG_TOKEN_ARROWSTAR;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_ARROW;
+ }
+ break;
+
+
+ case 220: /* STAR, TIMESEQUAL */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_STAR;
+ else if (c == '=')
+ return SWIG_TOKEN_TIMESEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_STAR;
+ }
+ break;
+
+ case 230: /* XOR, XOREQUAL */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_XOR;
+ else if (c == '=')
+ return SWIG_TOKEN_XOREQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_XOR;
+ }
+ break;
+
+ case 240: /* LSHIFT, LSEQUAL */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_LSHIFT;
+ else if (c == '=')
+ return SWIG_TOKEN_LSEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_LSHIFT;
+ }
+ break;
+
+ case 250: /* RSHIFT, RSEQUAL */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_RSHIFT;
+ else if (c == '=')
+ return SWIG_TOKEN_RSEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_RSHIFT;
+ }
+ break;
+
+
+ /* An illegal character */
+
+ /* Reverse string */
+ case 900:
+ if ((c = nextchar(s)) == 0) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated character constant\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '`') {
+ Delitem(s->text, DOH_END);
+ return (SWIG_TOKEN_RSTRING);
+ }
+ break;
+
+ default:
+ return SWIG_TOKEN_ILLEGAL;
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_token()
+ *
+ * Real entry point to return the next token. Returns 0 if at end of input.
+ * ----------------------------------------------------------------------------- */
+
+int Scanner_token(Scanner *s) {
+ int t;
+ Delete(s->error);
+ if (s->nexttoken >= 0) {
+ t = s->nexttoken;
+ s->nexttoken = -1;
+ return t;
+ }
+ s->start_line = 0;
+ t = look(s);
+ if (!s->start_line) {
+ Setline(s->text,s->line);
+ } else {
+ Setline(s->text,s->start_line);
+ }
+ return t;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_text()
+ *
+ * Return the lexene associated with the last returned token.
+ * ----------------------------------------------------------------------------- */
+
+String *Scanner_text(Scanner *s) {
+ return s->text;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_skip_line()
+ *
+ * Skips to the end of a line
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_skip_line(Scanner *s) {
+ char c;
+ int done = 0;
+ Clear(s->text);
+ Setfile(s->text, Getfile(s->str));
+ Setline(s->text, s->line);
+ while (!done) {
+ if ((c = nextchar(s)) == 0)
+ return;
+ if (c == '\\') {
+ nextchar(s);
+ } else if (c == '\n') {
+ done = 1;
+ }
+ }
+ return;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_skip_balanced()
+ *
+ * Skips a piece of code enclosed in begin/end symbols such as '{...}' or
+ * (...). Ignores symbols inside comments or strings.
+ * ----------------------------------------------------------------------------- */
+
+int Scanner_skip_balanced(Scanner *s, int startchar, int endchar) {
+ char c;
+ int num_levels = 1;
+ int state = 0;
+ char temp[2] = { 0, 0 };
+ String *locator = 0;
+ temp[0] = (char) startchar;
+ Clear(s->text);
+ Setfile(s->text, Getfile(s->str));
+ Setline(s->text, s->line);
+
+ Append(s->text, temp);
+ while (num_levels > 0) {
+ if ((c = nextchar(s)) == 0) {
+ Delete(locator);
+ return -1;
+ }
+ switch (state) {
+ case 0:
+ if (c == startchar)
+ num_levels++;
+ else if (c == endchar)
+ num_levels--;
+ else if (c == '/')
+ state = 10;
+ else if (c == '\"')
+ state = 20;
+ else if (c == '\'')
+ state = 30;
+ break;
+ case 10:
+ if (c == '/')
+ state = 11;
+ else if (c == '*')
+ state = 12;
+ else if (c == startchar) {
+ state = 0;
+ num_levels++;
+ }
+ else
+ state = 0;
+ break;
+ case 11:
+ if (c == '\n')
+ state = 0;
+ else
+ state = 11;
+ break;
+ case 12: /* first character inside C comment */
+ if (c == '*')
+ state = 14;
+ else if (c == '@')
+ state = 40;
+ else
+ state = 13;
+ break;
+ case 13:
+ if (c == '*')
+ state = 14;
+ break;
+ case 14: /* possible end of C comment */
+ if (c == '*')
+ state = 14;
+ else if (c == '/')
+ state = 0;
+ else
+ state = 13;
+ break;
+ case 20:
+ if (c == '\"')
+ state = 0;
+ else if (c == '\\')
+ state = 21;
+ break;
+ case 21:
+ state = 20;
+ break;
+ case 30:
+ if (c == '\'')
+ state = 0;
+ else if (c == '\\')
+ state = 31;
+ break;
+ case 31:
+ state = 30;
+ break;
+ /* 40-45 SWIG locator checks - a C comment with contents starting: @SWIG */
+ case 40:
+ state = (c == 'S') ? 41 : (c == '*') ? 14 : 13;
+ break;
+ case 41:
+ state = (c == 'W') ? 42 : (c == '*') ? 14 : 13;
+ break;
+ case 42:
+ state = (c == 'I') ? 43 : (c == '*') ? 14 : 13;
+ break;
+ case 43:
+ state = (c == 'G') ? 44 : (c == '*') ? 14 : 13;
+ if (c == 'G') {
+ Delete(locator);
+ locator = NewString("/*@SWIG");
+ }
+ break;
+ case 44:
+ if (c == '*')
+ state = 45;
+ Putc(c, locator);
+ break;
+ case 45: /* end of SWIG locator in C comment */
+ if (c == '/') {
+ state = 0;
+ Putc(c, locator);
+ Scanner_locator(s, locator);
+ } else {
+ /* malformed locator */
+ state = (c == '*') ? 14 : 13;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ Delete(locator);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_get_raw_text_balanced()
+ *
+ * Returns raw text between 2 braces, does not change scanner state in any way
+ * ----------------------------------------------------------------------------- */
+
+String *Scanner_get_raw_text_balanced(Scanner *s, int startchar, int endchar) {
+ String *result = 0;
+ char c;
+ int old_line = s->line;
+ String *old_text = Copy(s->text);
+ long position = Tell(s->str);
+
+ int num_levels = 1;
+ int state = 0;
+ char temp[2] = { 0, 0 };
+ temp[0] = (char) startchar;
+ Clear(s->text);
+ Setfile(s->text, Getfile(s->str));
+ Setline(s->text, s->line);
+ Append(s->text, temp);
+ while (num_levels > 0) {
+ if ((c = nextchar(s)) == 0) {
+ Clear(s->text);
+ Append(s->text, old_text);
+ Delete(old_text);
+ s->line = old_line;
+ return 0;
+ }
+ switch (state) {
+ case 0:
+ if (c == startchar)
+ num_levels++;
+ else if (c == endchar)
+ num_levels--;
+ else if (c == '/')
+ state = 10;
+ else if (c == '\"')
+ state = 20;
+ else if (c == '\'')
+ state = 30;
+ break;
+ case 10:
+ if (c == '/')
+ state = 11;
+ else if (c == '*')
+ state = 12;
+ else if (c == startchar) {
+ state = 0;
+ num_levels++;
+ }
+ else
+ state = 0;
+ break;
+ case 11:
+ if (c == '\n')
+ state = 0;
+ else
+ state = 11;
+ break;
+ case 12: /* first character inside C comment */
+ if (c == '*')
+ state = 14;
+ else
+ state = 13;
+ break;
+ case 13:
+ if (c == '*')
+ state = 14;
+ break;
+ case 14: /* possible end of C comment */
+ if (c == '*')
+ state = 14;
+ else if (c == '/')
+ state = 0;
+ else
+ state = 13;
+ break;
+ case 20:
+ if (c == '\"')
+ state = 0;
+ else if (c == '\\')
+ state = 21;
+ break;
+ case 21:
+ state = 20;
+ break;
+ case 30:
+ if (c == '\'')
+ state = 0;
+ else if (c == '\\')
+ state = 31;
+ break;
+ case 31:
+ state = 30;
+ break;
+ default:
+ break;
+ }
+ }
+ Seek(s->str, position, SEEK_SET);
+ result = Copy(s->text);
+ Clear(s->text);
+ Append(s->text, old_text);
+ Delete(old_text);
+ s->line = old_line;
+ return result;
+}
+/* -----------------------------------------------------------------------------
+ * Scanner_isoperator()
+ *
+ * Returns 0 or 1 depending on whether or not a token corresponds to a C/C++
+ * operator.
+ * ----------------------------------------------------------------------------- */
+
+int Scanner_isoperator(int tokval) {
+ if (tokval >= 100) return 1;
+ return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * locator()
+ *
+ * Support for locator strings. These are strings of the form
+ * @SWIG:filename,line,id@ emitted by the SWIG preprocessor. They
+ * are primarily used for macro line number reporting.
+ * We just use the locator to mark when to activate/deactivate linecounting.
+ * ---------------------------------------------------------------------- */
+
+
+void Scanner_locator(Scanner *s, String *loc) {
+ static Locator *locs = 0;
+ static int expanding_macro = 0;
+
+ if (!follow_locators) {
+ if (Equal(loc, "/*@SWIG@*/")) {
+ /* End locator. */
+ if (expanding_macro)
+ --expanding_macro;
+ } else {
+ /* Begin locator. */
+ ++expanding_macro;
+ }
+ /* Freeze line number processing in Scanner */
+ freeze_line(s,expanding_macro);
+ } else {
+ int c;
+ Locator *l;
+ (void)Seek(loc, 7, SEEK_SET);
+ c = Getc(loc);
+ if (c == '@') {
+ /* Empty locator. We pop the last location off */
+ if (locs) {
+ Scanner_set_location(s, locs->filename, locs->line_number);
+ cparse_file = locs->filename;
+ cparse_line = locs->line_number;
+ l = locs->next;
+ Free(locs);
+ locs = l;
+ }
+ return;
+ }
+
+ /* We're going to push a new location */
+ l = (Locator *) Malloc(sizeof(Locator));
+ l->filename = cparse_file;
+ l->line_number = cparse_line;
+ l->next = locs;
+ locs = l;
+
+ /* Now, parse the new location out of the locator string */
+ {
+ String *fn = NewStringEmpty();
+ /* Putc(c, fn); */
+
+ while ((c = Getc(loc)) != EOF) {
+ if ((c == '@') || (c == ','))
+ break;
+ Putc(c, fn);
+ }
+ cparse_file = Swig_copy_string(Char(fn));
+ Clear(fn);
+ cparse_line = 1;
+ /* Get the line number */
+ while ((c = Getc(loc)) != EOF) {
+ if ((c == '@') || (c == ','))
+ break;
+ Putc(c, fn);
+ }
+ cparse_line = atoi(Char(fn));
+ Clear(fn);
+
+ /* Get the rest of it */
+ while ((c = Getc(loc)) != EOF) {
+ if (c == '@')
+ break;
+ Putc(c, fn);
+ }
+ /* Swig_diagnostic(cparse_file, cparse_line, "Scanner_set_location\n"); */
+ Scanner_set_location(s, cparse_file, cparse_line);
+ Delete(fn);
+ }
+ }
+}
+
+void Swig_cparse_follow_locators(int v) {
+ follow_locators = v;
+}
+
+
diff --git a/contrib/tools/swig/Source/Swig/stype.c b/contrib/tools/swig/Source/Swig/stype.c
new file mode 100644
index 0000000000..f227778f6c
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/stype.c
@@ -0,0 +1,1422 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * stype.c
+ *
+ * This file provides general support for datatypes that are encoded in
+ * the form of simple strings.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+#include <ctype.h>
+
+/* -----------------------------------------------------------------------------
+ * Synopsis
+ *
+ * The purpose of this module is to provide a general purpose type representation
+ * based on simple text strings.
+ *
+ * General idea:
+ *
+ * Types are represented by a base type (e.g., "int") and a collection of
+ * type operators applied to the base (e.g., pointers, arrays, etc...).
+ *
+ * Encoding:
+ *
+ * Types are encoded as strings of type constructors such as follows:
+ *
+ * String Encoding C Example
+ * --------------- ---------
+ * p.p.int int **
+ * a(300).a(400).int int [300][400]
+ * p.q(const).char char const *
+ *
+ * All type constructors are denoted by a trailing '.':
+ *
+ * 'p.' = Pointer (*)
+ * 'r.' = Reference (&)
+ * 'z.' = Rvalue reference (&&)
+ * 'a(n).' = Array of size n [n]
+ * 'f(..,..).' = Function with arguments (args)
+ * 'q(str).' = Qualifier, such as const or volatile (cv-qualifier)
+ * 'm(cls).' = Pointer to member (cls::*)
+ *
+ * The encoding follows the order that you might describe a type in words.
+ * For example "p.a(200).int" is "A pointer to array of int's" and
+ * "p.q(const).char" is "a pointer to a const char".
+ *
+ * This representation of types is fairly convenient because ordinary string
+ * operations can be used for type manipulation. For example, a type could be
+ * formed by combining two strings such as the following:
+ *
+ * "p.p." + "a(400).int" = "p.p.a(400).int"
+ *
+ * Similarly, one could strip a 'const' declaration from a type doing something
+ * like this:
+ *
+ * Replace(t,"q(const).","",DOH_REPLACE_ANY)
+ *
+ * More examples:
+ *
+ * String Encoding C++ Example
+ * --------------- -----------
+ * p.f(bool).r.q(const).long const long & (*)(bool)
+ * m(Funcs).q(const).f(bool).long long (Funcs::*)(bool) const
+ * r.q(const).m(Funcs).f(int).long long (Funcs::*const &)(int)
+ * m(Funcs).z.q(const).f(bool).long long (Funcs::*)(bool) const &&
+ *
+ * Function decl examples:
+ *
+ * f(bool). long a(bool);
+ * r.f(bool). long b(bool) &;
+ * z.f(bool). long c(bool) &&;
+ * z.q(const).f(bool). long d(bool) const &&;
+ *
+ * For the most part, this module tries to minimize the use of special
+ * characters (*, [, <, etc...) in its type encoding. One reason for this
+ * is that SWIG might be extended to encode data in formats such as XML
+ * where you might want to do this:
+ *
+ * <function>
+ * <type>p.p.int</type>
+ * ...
+ * </function>
+ *
+ * Or alternatively,
+ *
+ * <function type="p.p.int" ...>blah</function>
+ *
+ * In either case, it's probably best to avoid characters such as '&', '*', or '<'.
+ *
+ * Why not use C syntax? Well, C syntax is fairly complicated to parse
+ * and not particularly easy to manipulate---especially for adding, deleting and
+ * composing type constructors. The string representation presented here makes
+ * this pretty easy.
+ *
+ * Why not use a bunch of nested data structures? Are you kidding? How
+ * would that be easier to use than a few simple string operations?
+ * ----------------------------------------------------------------------------- */
+
+
+SwigType *NewSwigType(int t) {
+ switch (t) {
+ case T_BOOL:
+ return NewString("bool");
+ break;
+ case T_INT:
+ return NewString("int");
+ break;
+ case T_UINT:
+ return NewString("unsigned int");
+ break;
+ case T_SHORT:
+ return NewString("short");
+ break;
+ case T_USHORT:
+ return NewString("unsigned short");
+ break;
+ case T_LONG:
+ return NewString("long");
+ break;
+ case T_ULONG:
+ return NewString("unsigned long");
+ break;
+ case T_FLOAT:
+ return NewString("float");
+ break;
+ case T_DOUBLE:
+ return NewString("double");
+ break;
+ case T_COMPLEX:
+ return NewString("_Complex");
+ break;
+ case T_CHAR:
+ return NewString("char");
+ break;
+ case T_SCHAR:
+ return NewString("signed char");
+ break;
+ case T_UCHAR:
+ return NewString("unsigned char");
+ break;
+ case T_STRING: {
+ SwigType *t = NewString("char");
+ SwigType_add_qualifier(t, "const");
+ SwigType_add_pointer(t);
+ return t;
+ break;
+ }
+ case T_WCHAR:
+ return NewString("wchar_t");
+ break;
+ case T_WSTRING: {
+ SwigType *t = NewString("wchar_t");
+ SwigType_add_pointer(t);
+ return t;
+ break;
+ }
+ case T_LONGLONG:
+ return NewString("long long");
+ break;
+ case T_ULONGLONG:
+ return NewString("unsigned long long");
+ break;
+ case T_VOID:
+ return NewString("void");
+ break;
+ case T_AUTO:
+ return NewString("auto");
+ break;
+ default:
+ break;
+ }
+ return NewStringEmpty();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_push()
+ *
+ * Push a type constructor onto the type
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_push(SwigType *t, String *cons) {
+ if (!cons)
+ return;
+ if (!Len(cons))
+ return;
+
+ if (Len(t)) {
+ char *c = Char(cons);
+ if (c[strlen(c) - 1] != '.')
+ Insert(t, 0, ".");
+ }
+ Insert(t, 0, cons);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_ispointer_return()
+ *
+ * Testing functions for querying a raw datatype
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_ispointer_return(const SwigType *t) {
+ char *c;
+ int idx;
+ if (!t)
+ return 0;
+ c = Char(t);
+ idx = (int)strlen(c) - 4;
+ if (idx >= 0) {
+ return (strcmp(c + idx, ").p.") == 0);
+ }
+ return 0;
+}
+
+int SwigType_isreference_return(const SwigType *t) {
+ char *c;
+ int idx;
+ if (!t)
+ return 0;
+ c = Char(t);
+ idx = (int)strlen(c) - 4;
+ if (idx >= 0) {
+ return (strcmp(c + idx, ").r.") == 0);
+ }
+ return 0;
+}
+
+int SwigType_isconst(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "q(", 2) == 0) {
+ String *q = SwigType_parm(t);
+ if (strstr(Char(q), "const")) {
+ Delete(q);
+ return 1;
+ }
+ Delete(q);
+ }
+ /* Hmmm. Might be const through a typedef */
+ if (SwigType_issimple(t)) {
+ int ret;
+ SwigType *td = SwigType_typedef_resolve(t);
+ if (td) {
+ ret = SwigType_isconst(td);
+ Delete(td);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+int SwigType_ismutable(const SwigType *t) {
+ int r;
+ SwigType *qt = SwigType_typedef_resolve_all(t);
+ if (SwigType_isreference(qt) || SwigType_isrvalue_reference(qt) || SwigType_isarray(qt)) {
+ Delete(SwigType_pop(qt));
+ }
+ r = SwigType_isconst(qt);
+ Delete(qt);
+ return r ? 0 : 1;
+}
+
+int SwigType_isenum(const SwigType *t) {
+ char *c = Char(t);
+ if (!t)
+ return 0;
+ if (strncmp(c, "enum ", 5) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+int SwigType_issimple(const SwigType *t) {
+ char *c = Char(t);
+ if (!t)
+ return 0;
+ while (*c) {
+ if (*c == '<') {
+ int nest = 1;
+ c++;
+ while (*c && nest) {
+ if (*c == '<')
+ nest++;
+ if (*c == '>')
+ nest--;
+ c++;
+ }
+ c--;
+ }
+ if (*c == '.')
+ return 0;
+ c++;
+ }
+ return 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_default_create()
+ *
+ * Create the default type for this datatype. This takes a type and strips it
+ * down to a generic form first by resolving all typedefs.
+ *
+ * Rules:
+ * Pointers: p.SWIGTYPE
+ * References: r.SWIGTYPE
+ * Arrays no dimension: a().SWIGTYPE
+ * Arrays with dimension: a(ANY).SWIGTYPE
+ * Member pointer: m(CLASS).SWIGTYPE
+ * Function pointer: f(ANY).SWIGTYPE
+ * Enums: enum SWIGTYPE
+ * Types: SWIGTYPE
+ *
+ * Examples (also see SwigType_default_deduce):
+ *
+ * int [2][4]
+ * a(2).a(4).int
+ * a(ANY).a(ANY).SWIGTYPE
+ *
+ * struct A {};
+ * typedef A *Aptr;
+ * Aptr const &
+ * r.q(const).Aptr
+ * r.q(const).p.SWIGTYPE
+ *
+ * enum E {e1, e2};
+ * enum E const &
+ * r.q(const).enum E
+ * r.q(const).enum SWIGTYPE
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_default_create(const SwigType *ty) {
+ SwigType *r = 0;
+ List *l;
+ Iterator it;
+ int numitems;
+
+ if (!SwigType_isvarargs(ty)) {
+ SwigType *t = SwigType_typedef_resolve_all(ty);
+ r = NewStringEmpty();
+ l = SwigType_split(t);
+ numitems = Len(l);
+
+ if (numitems >= 1) {
+ String *last_subtype = Getitem(l, numitems-1);
+ if (SwigType_isenum(last_subtype))
+ Setitem(l, numitems-1, NewString("enum SWIGTYPE"));
+ else
+ Setitem(l, numitems-1, NewString("SWIGTYPE"));
+ }
+
+ for (it = First(l); it.item; it = Next(it)) {
+ String *subtype = it.item;
+ if (SwigType_isarray(subtype)) {
+ if (Equal(subtype, "a()."))
+ Append(r, NewString("a()."));
+ else
+ Append(r, NewString("a(ANY)."));
+ } else if (SwigType_isfunction(subtype)) {
+ Append(r, NewString("f(ANY).SWIGTYPE"));
+ break;
+ } else if (SwigType_ismemberpointer(subtype)) {
+ Append(r, NewString("m(CLASS).SWIGTYPE"));
+ break;
+ } else {
+ Append(r, subtype);
+ }
+ }
+
+ Delete(l);
+ Delete(t);
+ }
+
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_default_deduce()
+ *
+ * This function implements type deduction used in the typemap matching rules
+ * and is very close to the type deduction used in partial template class
+ * specialization matching in that the most specialized type is always chosen.
+ * SWIGTYPE is used as the generic type. The basic idea is to repeatedly call
+ * this function to find a deduced type until nothing matches.
+ *
+ * The type t must have already been converted to the default type via a call to
+ * SwigType_default_create() before calling this function.
+ *
+ * Example deductions (matching the examples described in SwigType_default_create),
+ * where the most specialized matches are highest in the list:
+ *
+ * a(ANY).a(ANY).SWIGTYPE
+ * a(ANY).a().SWIGTYPE
+ * a(ANY).p.SWIGTYPE
+ * a(ANY).SWIGTYPE
+ * a().SWIGTYPE
+ * p.SWIGTYPE
+ * SWIGTYPE
+ *
+ * r.q(const).p.SWIGTYPE
+ * r.q(const).SWIGTYPE
+ * r.SWIGTYPE
+ * SWIGTYPE
+ *
+ * r.q(const).enum SWIGTYPE
+ * r.enum SWIGTYPE
+ * r.SWIGTYPE
+ * SWIGTYPE
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_default_deduce(const SwigType *t) {
+ SwigType *r = NewStringEmpty();
+ List *l;
+ Iterator it;
+ int numitems;
+
+ l = SwigType_split(t);
+
+ numitems = Len(l);
+ if (numitems >= 1) {
+ String *last_subtype = Getitem(l, numitems-1);
+ int is_enum = SwigType_isenum(last_subtype);
+
+ if (numitems >=2 ) {
+ String *subtype = Getitem(l, numitems-2); /* last but one */
+ if (SwigType_isarray(subtype)) {
+ if (is_enum) {
+ /* enum deduction, enum SWIGTYPE => SWIGTYPE */
+ Setitem(l, numitems-1, NewString("SWIGTYPE"));
+ } else {
+ /* array deduction, a(ANY). => a(). => p. */
+ String *deduced_subtype = 0;
+ if (Strcmp(subtype, "a().") == 0) {
+ deduced_subtype = NewString("p.");
+ } else if (Strcmp(subtype, "a(ANY).") == 0) {
+ deduced_subtype = NewString("a().");
+ } else {
+ assert(0);
+ }
+ Setitem(l, numitems-2, deduced_subtype);
+ }
+ } else if (SwigType_ismemberpointer(subtype)) {
+ /* member pointer deduction, m(CLASS). => p. */
+ Setitem(l, numitems-2, NewString("p."));
+ } else if (is_enum && !SwigType_isqualifier(subtype)) {
+ /* enum deduction, enum SWIGTYPE => SWIGTYPE */
+ Setitem(l, numitems-1, NewString("SWIGTYPE"));
+ } else {
+ /* simple type deduction, eg, r.p.p. => r.p. */
+ /* also function pointers eg, p.f(ANY). => p. */
+ Delitem(l, numitems-2);
+ }
+ } else {
+ if (is_enum) {
+ /* enum deduction, enum SWIGTYPE => SWIGTYPE */
+ Setitem(l, numitems-1, NewString("SWIGTYPE"));
+ } else {
+ /* delete the only item, we are done with deduction */
+ Delitem(l, 0);
+ }
+ }
+ } else {
+ assert(0);
+ }
+
+ for (it = First(l); it.item; it = Next(it)) {
+ Append(r, it.item);
+ }
+
+ if (Len(r) == 0) {
+ Delete(r);
+ r = 0;
+ }
+
+ Delete(l);
+ return r;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_namestr()
+ *
+ * Returns a string of the base type. Takes care of template expansions
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_namestr(const SwigType *t) {
+ String *r;
+ String *suffix;
+ List *p;
+ int i, sz;
+ char *d = Char(t);
+ char *c = strstr(d, "<(");
+
+ if (!c || !strstr(c + 2, ")>"))
+ return NewString(t);
+
+ r = NewStringWithSize(d, (int)(c - d));
+ if (*(c - 1) == '<')
+ Putc(' ', r);
+ Putc('<', r);
+
+ p = SwigType_parmlist(c + 1);
+ sz = Len(p);
+ for (i = 0; i < sz; i++) {
+ String *str = SwigType_str(Getitem(p, i), 0);
+ /* Avoid creating a <: token, which is the same as [ in C++ - put a space after '<'. */
+ if (i == 0 && Len(str))
+ Putc(' ', r);
+ Append(r, str);
+ if ((i + 1) < sz)
+ Putc(',', r);
+ Delete(str);
+ }
+ Putc(' ', r);
+ Putc('>', r);
+ suffix = SwigType_templatesuffix(t);
+ if (Len(suffix) > 0) {
+ String *suffix_namestr = SwigType_namestr(suffix);
+ Append(r, suffix_namestr);
+ Delete(suffix_namestr);
+ } else {
+ Append(r, suffix);
+ }
+ Delete(suffix);
+ Delete(p);
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_str()
+ *
+ * Create a C string representation of a datatype.
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
+ String *result;
+ String *element = 0;
+ String *nextelement;
+ String *forwardelement;
+ SwigType *member_function_qualifiers = 0;
+ List *elements;
+ int nelements, i;
+
+ if (id) {
+ /* stringify the id expanding templates, for example when the id is a fully qualified templated class name */
+ String *id_str = NewString(id); /* unfortunate copy due to current const limitations */
+ result = SwigType_str(id_str, 0);
+ Delete(id_str);
+ } else {
+ result = NewStringEmpty();
+ }
+
+ elements = SwigType_split(s);
+ nelements = Len(elements);
+
+ if (nelements > 0) {
+ element = Getitem(elements, 0);
+ }
+ /* Now, walk the type list and start emitting */
+ for (i = 0; i < nelements; i++) {
+ if (i < (nelements - 1)) {
+ nextelement = Getitem(elements, i + 1);
+ forwardelement = nextelement;
+ if (SwigType_isqualifier(nextelement)) {
+ if (i < (nelements - 2))
+ forwardelement = Getitem(elements, i + 2);
+ }
+ } else {
+ nextelement = 0;
+ forwardelement = 0;
+ }
+ if (SwigType_isqualifier(element)) {
+ if (!member_function_qualifiers) {
+ DOH *q = 0;
+ q = SwigType_parm(element);
+ Insert(result, 0, " ");
+ Insert(result, 0, q);
+ Delete(q);
+ }
+ } else if (SwigType_ispointer(element)) {
+ Insert(result, 0, "*");
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ } else if (SwigType_ismemberpointer(element)) {
+ String *q;
+ q = SwigType_parm(element);
+ Insert(result, 0, "::*");
+ Insert(result, 0, q);
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ {
+ String *next3elements = NewStringEmpty();
+ int j;
+ for (j = i + 1; j < i + 4 && j < nelements; j++) {
+ Append(next3elements, Getitem(elements, j));
+ }
+ if (SwigType_isfunction(next3elements))
+ member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
+ Delete(next3elements);
+ }
+ Delete(q);
+ } else if (SwigType_isreference(element)) {
+ if (!member_function_qualifiers)
+ Insert(result, 0, "&");
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ } else if (SwigType_isrvalue_reference(element)) {
+ if (!member_function_qualifiers)
+ Insert(result, 0, "&&");
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ } else if (SwigType_isarray(element)) {
+ DOH *size;
+ Append(result, "[");
+ size = SwigType_parm(element);
+ Append(result, size);
+ Append(result, "]");
+ Delete(size);
+ } else if (SwigType_isfunction(element)) {
+ DOH *parms, *p;
+ int j, plen;
+ Append(result, "(");
+ parms = SwigType_parmlist(element);
+ plen = Len(parms);
+ for (j = 0; j < plen; j++) {
+ p = SwigType_str(Getitem(parms, j), 0);
+ Append(result, p);
+ if (j < (plen - 1))
+ Append(result, ",");
+ }
+ Append(result, ")");
+ if (member_function_qualifiers) {
+ String *p = SwigType_str(member_function_qualifiers, 0);
+ Append(result, " ");
+ Append(result, p);
+ Delete(p);
+ Delete(member_function_qualifiers);
+ member_function_qualifiers = 0;
+ }
+ Delete(parms);
+ } else {
+ if (strcmp(Char(element), "v(...)") == 0) {
+ Insert(result, 0, "...");
+ } else {
+ String *bs = SwigType_namestr(element);
+ Insert(result, 0, " ");
+ Insert(result, 0, bs);
+ Delete(bs);
+ }
+ }
+ element = nextelement;
+ }
+ Delete(elements);
+ Chop(result);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_ltype(const SwigType *ty)
+ *
+ * Create a locally assignable type
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_ltype(const SwigType *s) {
+ String *result;
+ String *element;
+ SwigType *td, *tc = 0;
+ List *elements;
+ int nelements, i;
+ int firstarray = 1;
+ int notypeconv = 0;
+ int ignore_member_function_qualifiers = 0;
+
+ result = NewStringEmpty();
+ tc = Copy(s);
+ /* Nuke all leading qualifiers */
+ while (SwigType_isqualifier(tc)) {
+ Delete(SwigType_pop(tc));
+ }
+ if (SwigType_issimple(tc)) {
+ /* Resolve any typedef definitions */
+ SwigType *tt = Copy(tc);
+ td = 0;
+ while ((td = SwigType_typedef_resolve(tt))) {
+ if (td && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td) || SwigType_isrvalue_reference(td))) {
+ /* We need to use the typedef type */
+ Delete(tt);
+ break;
+ } else if (td) {
+ Delete(tt);
+ tt = td;
+ }
+ }
+ if (td) {
+ Delete(tc);
+ tc = td;
+ }
+ }
+
+ elements = SwigType_split(tc);
+ nelements = Len(elements);
+
+ /* Now, walk the type list and start emitting */
+ for (i = 0; i < nelements; i++) {
+ element = Getitem(elements, i);
+ /* when we see a function, we need to preserve the following types */
+ if (SwigType_isfunction(element)) {
+ notypeconv = 1;
+ ignore_member_function_qualifiers = 0;
+ }
+ if (ignore_member_function_qualifiers) {
+ /* cv-qualifiers and ref-qualifiers up until the f() element have already been added */
+ } else if (SwigType_isqualifier(element)) {
+ /* swallow cv-qualifiers */
+ } else if (SwigType_ispointer(element)) {
+ Append(result, element);
+ firstarray = 0;
+ } else if (SwigType_ismemberpointer(element)) {
+ Append(result, element);
+ {
+ String *next3elements = NewStringEmpty();
+ int j;
+ for (j = i + 1; j < i + 4 && j < nelements; j++) {
+ Append(next3elements, Getitem(elements, j));
+ }
+ if (SwigType_isfunction(next3elements)) {
+ SwigType *member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
+ /* compilers won't let us cast from a member function without qualifiers to one with qualifiers, so the qualifiers are kept in the ltype */
+ if (member_function_qualifiers)
+ Append(result, member_function_qualifiers);
+ Delete(member_function_qualifiers);
+ ignore_member_function_qualifiers = 1;
+ }
+ Delete(next3elements);
+ }
+ firstarray = 0;
+ } else if (SwigType_isreference(element)) {
+ if (notypeconv) {
+ Append(result, element);
+ } else {
+ Append(result, "p.");
+ }
+ firstarray = 0;
+ } else if (SwigType_isrvalue_reference(element)) {
+ if (notypeconv) {
+ Append(result, element);
+ } else {
+ Append(result, "p.");
+ }
+ firstarray = 0;
+ } else if (SwigType_isarray(element) && firstarray) {
+ if (notypeconv) {
+ Append(result, element);
+ } else {
+ Append(result, "p.");
+ }
+ firstarray = 0;
+ } else if (SwigType_isenum(element)) {
+ int anonymous_enum = (Cmp(element, "enum ") == 0);
+ if (notypeconv || !anonymous_enum) {
+ Append(result, element);
+ } else {
+ Append(result, "int");
+ }
+ } else {
+ Append(result, element);
+ }
+ }
+ Delete(elements);
+ Delete(tc);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_lstr()
+ *
+ * Produces a type-string that is suitable as a lvalue in an expression.
+ * That is, a type that can be freely assigned a value without violating
+ * any C assignment rules.
+ *
+ * - Qualifiers such as 'const' and 'volatile' are stripped.
+ * Except for member function cv-qualifiers and ref-qualifiers.
+ * - Arrays are converted into a *single* pointer (i.e.,
+ * double [][] becomes double *).
+ * - References are converted into a pointer.
+ * - Typedef names that refer to read-only types will be replaced
+ * with an equivalent assignable version.
+ * -------------------------------------------------------------------- */
+
+String *SwigType_lstr(const SwigType *s, const_String_or_char_ptr id) {
+ String *result;
+ SwigType *tc;
+
+ tc = SwigType_ltype(s);
+ result = SwigType_str(tc, id);
+ Delete(tc);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_rcaststr()
+ *
+ * Produces a casting string that maps the type returned by lstr() to the real
+ * datatype printed by str().
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
+ String *result, *cast;
+ String *element = 0;
+ String *nextelement;
+ String *forwardelement;
+ String *member_function_qualifiers = 0;
+ SwigType *td, *tc = 0;
+ const SwigType *rs;
+ List *elements;
+ int nelements, i;
+ int clear = 1;
+ int firstarray = 1;
+ int isreference = 0;
+ int isfunction = 0;
+
+ result = NewStringEmpty();
+
+ if (SwigType_isconst(s)) {
+ tc = Copy(s);
+ Delete(SwigType_pop(tc));
+ if (SwigType_ismemberpointer(tc))
+ rs = s;
+ else
+ rs = tc;
+ } else {
+ rs = s;
+ }
+
+ if ((SwigType_isconst(rs) || SwigType_isarray(rs) || SwigType_isreference(rs) || SwigType_isrvalue_reference(rs))) {
+ td = 0;
+ } else {
+ td = SwigType_typedef_resolve(rs);
+ }
+
+ if (td) {
+ if ((SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td) || SwigType_isrvalue_reference(td))) {
+ elements = SwigType_split(td);
+ } else {
+ elements = SwigType_split(rs);
+ }
+ Delete(td);
+ } else {
+ elements = SwigType_split(rs);
+ }
+ nelements = Len(elements);
+ if (nelements > 0) {
+ element = Getitem(elements, 0);
+ }
+ /* Now, walk the type list and start emitting */
+ for (i = 0; i < nelements; i++) {
+ if (i < (nelements - 1)) {
+ nextelement = Getitem(elements, i + 1);
+ forwardelement = nextelement;
+ if (SwigType_isqualifier(nextelement)) {
+ if (i < (nelements - 2))
+ forwardelement = Getitem(elements, i + 2);
+ }
+ } else {
+ nextelement = 0;
+ forwardelement = 0;
+ }
+ if (SwigType_isqualifier(element)) {
+ if (!member_function_qualifiers) {
+ DOH *q = 0;
+ q = SwigType_parm(element);
+ Insert(result, 0, " ");
+ Insert(result, 0, q);
+ Delete(q);
+ clear = 0;
+ }
+ } else if (SwigType_ispointer(element)) {
+ Insert(result, 0, "*");
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ firstarray = 0;
+ } else if (SwigType_ismemberpointer(element)) {
+ String *q;
+ Insert(result, 0, "::*");
+ q = SwigType_parm(element);
+ Insert(result, 0, q);
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ {
+ String *next3elements = NewStringEmpty();
+ int j;
+ for (j = i + 1; j < i + 4 && j < nelements; j++) {
+ Append(next3elements, Getitem(elements, j));
+ }
+ if (SwigType_isfunction(next3elements))
+ member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
+ Delete(next3elements);
+ }
+ firstarray = 0;
+ Delete(q);
+ } else if (SwigType_isreference(element)) {
+ if (!member_function_qualifiers) {
+ Insert(result, 0, "&");
+ if (!isfunction)
+ isreference = 1;
+ }
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ } else if (SwigType_isrvalue_reference(element)) {
+ if (!member_function_qualifiers) {
+ Insert(result, 0, "&&");
+ if (!isfunction)
+ isreference = 1;
+ }
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ clear = 0;
+ } else if (SwigType_isarray(element)) {
+ DOH *size;
+ if (firstarray && !isreference) {
+ Append(result, "(*)");
+ firstarray = 0;
+ } else {
+ Append(result, "[");
+ size = SwigType_parm(element);
+ Append(result, size);
+ Append(result, "]");
+ Delete(size);
+ clear = 0;
+ }
+ } else if (SwigType_isfunction(element)) {
+ DOH *parms, *p;
+ int j, plen;
+ Append(result, "(");
+ parms = SwigType_parmlist(element);
+ plen = Len(parms);
+ for (j = 0; j < plen; j++) {
+ p = SwigType_str(Getitem(parms, j), 0);
+ Append(result, p);
+ Delete(p);
+ if (j < (plen - 1))
+ Append(result, ",");
+ }
+ Append(result, ")");
+ Delete(parms);
+ if (member_function_qualifiers) {
+ String *p = SwigType_str(member_function_qualifiers, 0);
+ Append(result, " ");
+ Append(result, p);
+ Delete(p);
+ Delete(member_function_qualifiers);
+ member_function_qualifiers = 0;
+ clear = 0;
+ }
+ isfunction = 1;
+ } else {
+ String *bs = SwigType_namestr(element);
+ Insert(result, 0, " ");
+ Insert(result, 0, bs);
+ Delete(bs);
+ }
+ element = nextelement;
+ }
+ Delete(elements);
+ if (clear) {
+ cast = NewStringEmpty();
+ } else {
+ cast = NewStringf("(%s)", result);
+ }
+ if (name) {
+ if (isreference) {
+ Append(cast, "*");
+ }
+ Append(cast, name);
+ }
+ Delete(result);
+ Delete(tc);
+ return cast;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_lcaststr()
+ *
+ * Casts a variable from the real type to the local datatype.
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_lcaststr(const SwigType *s, const_String_or_char_ptr name) {
+ String *result;
+
+ result = NewStringEmpty();
+
+ if (SwigType_isarray(s)) {
+ String *lstr = SwigType_lstr(s, 0);
+ Printf(result, "(%s)%s", lstr, name);
+ Delete(lstr);
+ } else if (SwigType_isreference(s)) {
+ String *str = SwigType_str(s, 0);
+ Printf(result, "(%s)", str);
+ Delete(str);
+ if (name)
+ Append(result, name);
+ } else if (SwigType_isrvalue_reference(s)) {
+ String *str = SwigType_str(s, 0);
+ Printf(result, "(%s)", str);
+ Delete(str);
+ if (name)
+ Append(result, name);
+ } else if (SwigType_isqualifier(s)) {
+ String *lstr = SwigType_lstr(s, 0);
+ Printf(result, "(%s)%s", lstr, name);
+ Delete(lstr);
+ } else {
+ if (name)
+ Append(result, name);
+ }
+ return result;
+}
+
+#if 0
+/* Alternative implementation for manglestr_default. Mangling is similar to the original
+ except for a few subtle differences for example in templates:
+ namespace foo {
+ template<class T> class bar {};
+ typedef int Integer;
+ void test2(bar<Integer *> *x);
+ }
+ Mangling is more consistent and changes from
+ _p_foo__barT_int_p_t to
+ _p_foo__barT_p_int_t.
+*/
+static void mangle_stringcopy(String *destination, const char *source, int count) {
+ while (count-- > 0) {
+ char newc = '_';
+ if (!(*source == '.' || *source == ':' || *source == ' '))
+ newc = *source;
+ /* TODO: occasionally '*' or numerics need converting to '_', eg in array dimensions and template expressions */
+ Putc(newc, destination);
+ source++;
+ }
+}
+
+static void mangle_subtype(String *mangled, SwigType *s);
+
+/* -----------------------------------------------------------------------------
+ * mangle_namestr()
+ *
+ * Mangles a type taking care of template expansions. Similar to SwigType_namestr().
+ * The type may include a trailing '.', for example "p."
+ * ----------------------------------------------------------------------------- */
+
+static void mangle_namestr(String *mangled, SwigType *t) {
+ int length = Len(t);
+ if (SwigType_isqualifier(t)) {
+ Append(mangled, "q_");
+ mangle_stringcopy(mangled, Char(t)+2, length-4);
+ Append(mangled, "__");
+ } else if (SwigType_ismemberpointer(t)) {
+ Append(mangled, "m_");
+ mangle_stringcopy(mangled, Char(t)+2, length-4);
+ Append(mangled, "__");
+ } else if (SwigType_isarray(t)) {
+ Append(mangled, "a_");
+ mangle_stringcopy(mangled, Char(t)+2, length-4);
+ Append(mangled, "__");
+ } else if (SwigType_isfunction(t)) {
+ List *p = SwigType_parmlist(t);
+ int sz = Len(p);
+ int i;
+ Append(mangled, "f_");
+ for (i = 0; i < sz; i++) {
+ mangle_subtype(mangled, Getitem(p, i));
+ Putc('_', mangled);
+ }
+ Append(mangled, (sz > 0) ? "_" : "__");
+ } else if (SwigType_isvarargs(t)) {
+ Append(mangled, "___");
+ } else {
+ char *d = Char(t);
+ char *c = strstr(d, "<(");
+ if (!c || !strstr(c + 2, ")>")) {
+ /* not a template type */
+ mangle_stringcopy(mangled, Char(t), Len(t));
+ } else {
+ /* a template type */
+ String *suffix;
+ List *p;
+ int i, sz;
+ mangle_stringcopy(mangled, d, c-d);
+ Putc('T', mangled);
+ Putc('_', mangled);
+
+ p = SwigType_parmlist(c + 1);
+ sz = Len(p);
+ for (i = 0; i < sz; i++) {
+ mangle_subtype(mangled, Getitem(p, i));
+ Putc('_', mangled);
+ }
+ Putc('t', mangled);
+ suffix = SwigType_templatesuffix(t);
+ if (Len(suffix) > 0) {
+ mangle_namestr(mangled, suffix);
+ } else {
+ Append(mangled, suffix);
+ }
+ Delete(suffix);
+ Delete(p);
+ }
+ }
+}
+
+static void mangle_subtype(String *mangled, SwigType *s) {
+ List *elements;
+ int nelements, i;
+
+ assert(s);
+ elements = SwigType_split(s);
+ nelements = Len(elements);
+ for (i = 0; i < nelements; i++) {
+ SwigType *element = Getitem(elements, i);
+ mangle_namestr(mangled, element);
+ }
+ Delete(elements);
+}
+
+static String *manglestr_default(const SwigType *s) {
+ String *mangled = NewString("_");
+ SwigType *sr = SwigType_typedef_resolve_all(s);
+ SwigType *sq = SwigType_typedef_qualified(sr);
+ SwigType *ss = SwigType_remove_global_scope_prefix(sq);
+ SwigType *type = ss;
+ SwigType *lt;
+
+ if (SwigType_istemplate(ss)) {
+ SwigType *ty = Swig_symbol_template_deftype(ss, 0);
+ Delete(ss);
+ ss = ty;
+ type = ss;
+ }
+
+ lt = SwigType_ltype(type);
+
+ Replace(lt, "struct ", "", DOH_REPLACE_ANY);
+ Replace(lt, "class ", "", DOH_REPLACE_ANY);
+ Replace(lt, "union ", "", DOH_REPLACE_ANY);
+ Replace(lt, "enum ", "", DOH_REPLACE_ANY);
+
+ mangle_subtype(mangled, lt);
+
+ Delete(ss);
+ Delete(sq);
+ Delete(sr);
+
+ return mangled;
+}
+
+#else
+
+static String *manglestr_default(const SwigType *s) {
+ char *c;
+ String *result = 0;
+ String *base = 0;
+ SwigType *lt;
+ SwigType *sr = SwigType_typedef_resolve_all(s);
+ SwigType *sq = SwigType_typedef_qualified(sr);
+ SwigType *ss = SwigType_remove_global_scope_prefix(sq);
+ SwigType *type = ss;
+
+ if (SwigType_istemplate(ss)) {
+ SwigType *ty = Swig_symbol_template_deftype(ss, 0);
+ Delete(ss);
+ ss = ty;
+ type = ss;
+ }
+
+ lt = SwigType_ltype(type);
+ result = SwigType_prefix(lt);
+ base = SwigType_base(lt);
+
+ c = Char(result);
+ while (*c) {
+ if (!isalnum((int) *c))
+ *c = '_';
+ c++;
+ }
+ if (SwigType_istemplate(base)) {
+ String *b = SwigType_namestr(base);
+ Delete(base);
+ base = b;
+ }
+
+ Replace(base, "struct ", "", DOH_REPLACE_ANY); /* This might be problematic */
+ Replace(base, "class ", "", DOH_REPLACE_ANY);
+ Replace(base, "union ", "", DOH_REPLACE_ANY);
+ Replace(base, "enum ", "", DOH_REPLACE_ANY);
+
+ c = Char(base);
+ while (*c) {
+ if (*c == '<')
+ *c = 'T';
+ else if (*c == '>')
+ *c = 't';
+ else if (*c == '*')
+ *c = 'p';
+ else if (*c == '[')
+ *c = 'a';
+ else if (*c == ']')
+ *c = 'A';
+ else if (*c == '&')
+ *c = 'R';
+ else if (*c == '(')
+ *c = 'f';
+ else if (*c == ')')
+ *c = 'F';
+ else if (!isalnum((int) *c))
+ *c = '_';
+ c++;
+ }
+ Append(result, base);
+ Insert(result, 0, "_");
+ Delete(lt);
+ Delete(base);
+ Delete(ss);
+ Delete(sq);
+ Delete(sr);
+ return result;
+}
+#endif
+
+String *SwigType_manglestr(const SwigType *s) {
+#if 0
+ /* Debugging checks to ensure a proper SwigType is passed in and not a stringified type */
+ String *angle = Strstr(s, "<");
+ if (angle && Strncmp(angle, "<(", 2) != 0)
+ Printf(stderr, "SwigType_manglestr error: %s\n", s);
+ else if (Strstr(s, "*") || Strstr(s, "&") || Strstr(s, "["))
+ Printf(stderr, "SwigType_manglestr error: %s\n", s);
+#endif
+ return manglestr_default(s);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typename_replace()
+ *
+ * Replaces a typename in a type with something else. Needed for templates.
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_typename_replace(SwigType *t, String *pat, String *rep) {
+ String *nt;
+ int i, ilen;
+ List *elem;
+
+ if (!Strstr(t, pat))
+ return;
+
+ if (Equal(t, pat)) {
+ Replace(t, pat, rep, DOH_REPLACE_ANY);
+ return;
+ }
+ nt = NewStringEmpty();
+ elem = SwigType_split(t);
+ ilen = Len(elem);
+ for (i = 0; i < ilen; i++) {
+ String *e = Getitem(elem, i);
+ if (SwigType_issimple(e)) {
+ if (Equal(e, pat)) {
+ /* Replaces a type of the form 'pat' with 'rep<args>' */
+ Replace(e, pat, rep, DOH_REPLACE_ANY);
+ } else if (SwigType_istemplate(e)) {
+ /* Replaces a type of the form 'pat<args>' with 'rep' */
+ {
+ /* To match "e=TemplateTemplateT<(float)>"
+ * with "pat=TemplateTemplateT"
+ * we need to compare only the first part of the string e.
+ */
+ int len = Len(pat);
+
+ /* Len(e) > len, not >= (because we expect at least a
+ * character '<' following the template typename)
+ */
+ if (Len(e) > len) {
+ String *firstPartOfType = NewStringWithSize(e, len);
+ const char* e_as_char = Char(e);
+
+ if (Equal(firstPartOfType, pat) && e_as_char[len] == '<') {
+ String *repbase = SwigType_templateprefix(rep);
+ Replace(e, pat, repbase, DOH_REPLACE_ID | DOH_REPLACE_FIRST);
+ Delete(repbase);
+ }
+ Delete(firstPartOfType);
+ }
+ }
+
+ {
+ String *tsuffix;
+ List *tparms = SwigType_parmlist(e);
+ int j, jlen;
+ String *nt = SwigType_templateprefix(e);
+ Append(nt, "<(");
+ jlen = Len(tparms);
+ for (j = 0; j < jlen; j++) {
+ SwigType_typename_replace(Getitem(tparms, j), pat, rep);
+ Append(nt, Getitem(tparms, j));
+ if (j < (jlen - 1))
+ Putc(',', nt);
+ }
+ tsuffix = SwigType_templatesuffix(e);
+ SwigType_typename_replace(tsuffix, pat, rep);
+ Printf(nt, ")>%s", tsuffix);
+ Delete(tsuffix);
+ Clear(e);
+ Append(e, nt);
+ Delete(nt);
+ Delete(tparms);
+ }
+ } else if (Swig_scopename_check(e)) {
+ String *first = 0;
+ String *rest = 0;
+ Swig_scopename_split(e, &first, &rest);
+
+ /* Swig_scopename_split doesn't handle :: prefix very well ... could do with a rework */
+ if (Strncmp(rest, "::", 2) == 0) {
+ String *tmp = NewString(Char(rest) + 2);
+ Clear(rest);
+ Printv(rest, tmp, NIL);
+ Delete(tmp);
+ assert(!first);
+ }
+
+ Clear(e);
+ if (first)
+ SwigType_typename_replace(first, pat, rep);
+ SwigType_typename_replace(rest, pat, rep);
+ Printv(e, first ? first : "", "::", rest, NIL);
+ Delete(first);
+ Delete(rest);
+ }
+ } else if (SwigType_isfunction(e)) {
+ int j, jlen;
+ List *fparms = SwigType_parmlist(e);
+ Clear(e);
+ Append(e, "f(");
+ jlen = Len(fparms);
+ for (j = 0; j < jlen; j++) {
+ SwigType_typename_replace(Getitem(fparms, j), pat, rep);
+ Append(e, Getitem(fparms, j));
+ if (j < (jlen - 1))
+ Putc(',', e);
+ }
+ Append(e, ").");
+ Delete(fparms);
+ } else if (SwigType_isarray(e)) {
+ Replace(e, pat, rep, DOH_REPLACE_ID);
+ }
+ Append(nt, e);
+ }
+ Clear(t);
+ Append(t, nt);
+ Delete(nt);
+ Delete(elem);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_remove_global_scope_prefix()
+ *
+ * Removes the unary scope operator (::) prefix indicating global scope in all
+ * components of the type
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_remove_global_scope_prefix(const SwigType *t) {
+ SwigType *result;
+ const char *type = Char(t);
+ if (strncmp(type, "::", 2) == 0)
+ type += 2;
+ result = NewString(type);
+ Replaceall(result, ".::", ".");
+ Replaceall(result, "(::", "(");
+ Replaceall(result, "enum ::", "enum ");
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_check_decl()
+ *
+ * Checks type declarators for a match
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_check_decl(const SwigType *ty, const SwigType *decl) {
+ SwigType *t, *t1, *t2;
+ int r;
+ t = SwigType_typedef_resolve_all(ty);
+ t1 = SwigType_strip_qualifiers(t);
+ t2 = SwigType_prefix(t1);
+ r = Equal(t2, decl);
+ Delete(t);
+ Delete(t1);
+ Delete(t2);
+ return r == 1;
+}
diff --git a/contrib/tools/swig/Source/Swig/swig.h b/contrib/tools/swig/Source/Swig/swig.h
new file mode 100644
index 0000000000..19e61b4558
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swig.h
@@ -0,0 +1,451 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * swig.h
+ *
+ * Header file for the SWIG core.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_SWIG_H
+#define SWIG_SWIG_H
+
+#include "swigconfig.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "doh.h"
+
+/* Status codes */
+
+#define SWIG_OK 1
+#define SWIG_ERROR 0
+#define SWIG_NOWRAP 0
+
+/* Global macros */
+#define NSPACE_SEPARATOR "." /* Namespace separator for the nspace feature - this should be changed to a target language configurable variable */
+#define NSPACE_TODO 0 /* Languages that still need to implement and test the nspace feature use this */
+
+/* Short names for common data types */
+
+ typedef DOH String;
+ typedef DOH Hash;
+ typedef DOH List;
+ typedef DOH String_or_char;
+ typedef DOH File;
+ typedef DOH Parm;
+ typedef DOH ParmList;
+ typedef DOH Node;
+ typedef DOH Symtab;
+ typedef DOH Typetab;
+ typedef DOH SwigType;
+
+/* --- Legacy DataType interface. These type codes are provided solely
+ for backwards compatibility with older modules --- */
+
+/* --- The ordering of type values is used to determine type-promotion
+ in the parser. Do not change */
+
+/* Numeric types */
+
+#define T_BOOL 1
+#define T_SCHAR 2
+#define T_UCHAR 3
+#define T_SHORT 4
+#define T_USHORT 5
+#define T_ENUM 6
+#define T_INT 7
+#define T_UINT 8
+#define T_LONG 9
+#define T_ULONG 10
+#define T_LONGLONG 11
+#define T_ULONGLONG 12
+#define T_FLOAT 20
+#define T_DOUBLE 21
+#define T_LONGDOUBLE 22
+#define T_FLTCPLX 23
+#define T_DBLCPLX 24
+#define T_NUMERIC 25
+#define T_AUTO 26
+
+#define T_COMPLEX T_DBLCPLX
+
+/* non-numeric */
+
+#define T_CHAR 29
+#define T_WCHAR 30
+#define T_USER 31
+#define T_VOID 32
+#define T_STRING 33
+#define T_POINTER 34
+#define T_REFERENCE 35
+#define T_ARRAY 36
+#define T_FUNCTION 37
+#define T_MPOINTER 38
+#define T_VARARGS 39
+#define T_RVALUE_REFERENCE 40
+#define T_WSTRING 41
+
+#define T_SYMBOL 98
+#define T_ERROR 99
+
+
+
+/* --- File interface --- */
+
+#include "swigfile.h"
+
+/* --- Command line parsing --- */
+
+#include "swigopt.h"
+
+/* --- Scanner Interface --- */
+
+#include "swigscan.h"
+
+/* --- Functions for manipulating the string-based type encoding --- */
+
+ extern SwigType *NewSwigType(int typecode);
+ extern SwigType *SwigType_del_element(SwigType *t);
+ extern SwigType *SwigType_add_pointer(SwigType *t);
+ extern SwigType *SwigType_add_memberpointer(SwigType *t, const_String_or_char_ptr qual);
+ extern SwigType *SwigType_del_memberpointer(SwigType *t);
+ extern SwigType *SwigType_del_pointer(SwigType *t);
+ extern SwigType *SwigType_add_array(SwigType *t, const_String_or_char_ptr size);
+ extern SwigType *SwigType_del_array(SwigType *t);
+ extern SwigType *SwigType_pop_arrays(SwigType *t);
+ extern SwigType *SwigType_add_reference(SwigType *t);
+ extern SwigType *SwigType_del_reference(SwigType *t);
+ extern SwigType *SwigType_add_rvalue_reference(SwigType *t);
+ extern SwigType *SwigType_del_rvalue_reference(SwigType *t);
+ extern SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual);
+ extern SwigType *SwigType_del_qualifier(SwigType *t);
+ extern SwigType *SwigType_add_function(SwigType *t, ParmList *parms);
+ extern SwigType *SwigType_add_template(SwigType *t, ParmList *parms);
+ extern SwigType *SwigType_pop_function(SwigType *t);
+ extern SwigType *SwigType_pop_function_qualifiers(SwigType *t);
+ extern ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node);
+ extern List *SwigType_split(const SwigType *t);
+ extern String *SwigType_pop(SwigType *t);
+ extern void SwigType_push(SwigType *t, String *s);
+ extern SwigType *SwigType_last(SwigType *t);
+ extern List *SwigType_parmlist(const SwigType *p);
+ extern String *SwigType_parm(const SwigType *p);
+ extern String *SwigType_str(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_lstr(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_lcaststr(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_manglestr(const SwigType *t);
+ extern SwigType *SwigType_ltype(const SwigType *t);
+ extern int SwigType_ispointer(const SwigType *t);
+ extern int SwigType_ispointer_return(const SwigType *t);
+ extern int SwigType_isfunctionpointer(const SwigType *t);
+ extern int SwigType_ismemberpointer(const SwigType *t);
+ extern int SwigType_isreference(const SwigType *t);
+ extern int SwigType_isreference_return(const SwigType *t);
+ extern int SwigType_isrvalue_reference(const SwigType *t);
+ extern int SwigType_isarray(const SwigType *t);
+ extern int SwigType_prefix_is_simple_1D_array(const SwigType *t);
+ extern int SwigType_isfunction(const SwigType *t);
+ extern int SwigType_isqualifier(const SwigType *t);
+ extern int SwigType_isconst(const SwigType *t);
+ extern int SwigType_issimple(const SwigType *t);
+ extern int SwigType_ismutable(const SwigType *t);
+ extern int SwigType_isvarargs(const SwigType *t);
+ extern int SwigType_istemplate(const SwigType *t);
+ extern int SwigType_isenum(const SwigType *t);
+ extern int SwigType_check_decl(const SwigType *t, const_String_or_char_ptr decl);
+ extern SwigType *SwigType_strip_qualifiers(const SwigType *t);
+ extern SwigType *SwigType_strip_single_qualifier(const SwigType *t);
+ extern SwigType *SwigType_functionpointer_decompose(SwigType *t);
+ extern String *SwigType_base(const SwigType *t);
+ extern String *SwigType_namestr(const SwigType *t);
+ extern String *SwigType_templateprefix(const SwigType *t);
+ extern String *SwigType_templatesuffix(const SwigType *t);
+ extern String *SwigType_istemplate_templateprefix(const SwigType *t);
+ extern String *SwigType_istemplate_only_templateprefix(const SwigType *t);
+ extern String *SwigType_templateargs(const SwigType *t);
+ extern String *SwigType_prefix(const SwigType *t);
+ extern int SwigType_array_ndim(const SwigType *t);
+ extern String *SwigType_array_getdim(const SwigType *t, int n);
+ extern void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep);
+ extern SwigType *SwigType_array_type(const SwigType *t);
+ extern SwigType *SwigType_default_create(const SwigType *ty);
+ extern SwigType *SwigType_default_deduce(const SwigType *t);
+ extern void SwigType_typename_replace(SwigType *t, String *pat, String *rep);
+ extern SwigType *SwigType_remove_global_scope_prefix(const SwigType *t);
+ extern SwigType *SwigType_alttype(const SwigType *t, int ltmap);
+
+/* --- Type-system management --- */
+ extern void SwigType_typesystem_init(void);
+ extern int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name);
+ extern int SwigType_typedef_class(const_String_or_char_ptr name);
+ extern int SwigType_typedef_using(const_String_or_char_ptr qname);
+ extern void SwigType_inherit(String *subclass, String *baseclass, String *cast, String *conversioncode);
+ extern int SwigType_issubtype(const SwigType *subtype, const SwigType *basetype);
+ extern void SwigType_scope_alias(String *aliasname, Typetab *t);
+ extern void SwigType_using_scope(Typetab *t);
+ extern void SwigType_new_scope(const_String_or_char_ptr name);
+ extern void SwigType_inherit_scope(Typetab *scope);
+ extern Typetab *SwigType_pop_scope(void);
+ extern Typetab *SwigType_set_scope(Typetab *h);
+ extern void SwigType_print_scope(void);
+ extern SwigType *SwigType_typedef_resolve(const SwigType *t);
+ extern SwigType *SwigType_typedef_resolve_all(const SwigType *t);
+ extern SwigType *SwigType_typedef_qualified(const SwigType *t);
+ extern int SwigType_istypedef(const SwigType *t);
+ extern int SwigType_isclass(const SwigType *t);
+ extern void SwigType_attach_symtab(Symtab *syms);
+ extern void SwigType_remember(const SwigType *t);
+ extern void SwigType_remember_clientdata(const SwigType *t, const_String_or_char_ptr clientdata);
+ extern void SwigType_remember_mangleddata(String *mangled, const_String_or_char_ptr clientdata);
+ extern void (*SwigType_remember_trace(void (*tf) (const SwigType *, String *, String *))) (const SwigType *, String *, String *);
+ extern void SwigType_emit_type_table(File *f_headers, File *f_table);
+ extern int SwigType_type(const SwigType *t);
+
+/* --- Symbol table module --- */
+
+ extern void Swig_symbol_print_tables(Symtab *symtab);
+ extern void Swig_symbol_print_tables_summary(void);
+ extern void Swig_symbol_print_symbols(void);
+ extern void Swig_symbol_print_csymbols(void);
+ extern void Swig_symbol_init(void);
+ extern void Swig_symbol_setscopename(const_String_or_char_ptr name);
+ extern String *Swig_symbol_getscopename(void);
+ extern String *Swig_symbol_qualifiedscopename(Symtab *symtab);
+ extern String *Swig_symbol_qualified_language_scopename(Symtab *symtab);
+ extern Symtab *Swig_symbol_newscope(void);
+ extern Symtab *Swig_symbol_setscope(Symtab *);
+ extern Symtab *Swig_symbol_getscope(const_String_or_char_ptr symname);
+ extern Symtab *Swig_symbol_global_scope(void);
+ extern Symtab *Swig_symbol_current(void);
+ extern Symtab *Swig_symbol_popscope(void);
+ extern Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *node);
+ extern void Swig_symbol_cadd(const_String_or_char_ptr symname, Node *node);
+ extern Node *Swig_symbol_clookup(const_String_or_char_ptr symname, Symtab *tab);
+ extern Node *Swig_symbol_clookup_check(const_String_or_char_ptr symname, Symtab *tab, int (*check) (Node *));
+ extern Node *Swig_symbol_clookup_no_inherit(const_String_or_char_ptr name, Symtab *n);
+ extern Symtab *Swig_symbol_cscope(const_String_or_char_ptr symname, Symtab *tab);
+ extern Node *Swig_symbol_clookup_local(const_String_or_char_ptr symname, Symtab *tab);
+ extern Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr symname, Symtab *tab, int (*check) (Node *));
+ extern String *Swig_symbol_qualified(Node *node);
+ extern Node *Swig_symbol_isoverloaded(Node *node);
+ extern void Swig_symbol_remove(Node *node);
+ extern void Swig_symbol_alias(const_String_or_char_ptr aliasname, Symtab *tab);
+ extern void Swig_symbol_inherit(Symtab *tab);
+ extern SwigType *Swig_symbol_type_qualify(const SwigType *ty, Symtab *tab);
+ extern String *Swig_symbol_string_qualify(String *s, Symtab *tab);
+ extern SwigType *Swig_symbol_typedef_reduce(const SwigType *ty, Symtab *tab);
+
+ extern ParmList *Swig_symbol_template_defargs(Parm *parms, Parm *targs, Symtab *tscope, Symtab *tsdecl);
+ extern SwigType *Swig_symbol_template_deftype(const SwigType *type, Symtab *tscope);
+ extern SwigType *Swig_symbol_template_param_eval(const SwigType *p, Symtab *symtab);
+
+/* --- Parameters and Parameter Lists --- */
+
+#include "swigparm.h"
+
+extern String *ParmList_errorstr(ParmList *);
+extern int ParmList_is_compactdefargs(ParmList *p);
+
+/* --- Parse tree support --- */
+
+#include "swigtree.h"
+
+/* -- Wrapper function Object */
+
+#include "swigwrap.h"
+
+/* --- Naming functions --- */
+
+ extern void Swig_name_register(const_String_or_char_ptr method, const_String_or_char_ptr format);
+ extern void Swig_name_unregister(const_String_or_char_ptr method);
+ extern String *Swig_name_mangle(const_String_or_char_ptr s);
+ extern String *Swig_name_wrapper(const_String_or_char_ptr fname);
+ extern String *Swig_name_member(const_String_or_char_ptr nspace, const_String_or_char_ptr classname, const_String_or_char_ptr membername);
+ extern String *Swig_name_get(const_String_or_char_ptr nspace, const_String_or_char_ptr vname);
+ extern String *Swig_name_set(const_String_or_char_ptr nspace, const_String_or_char_ptr vname);
+ extern String *Swig_name_construct(const_String_or_char_ptr nspace, const_String_or_char_ptr classname);
+ extern String *Swig_name_copyconstructor(const_String_or_char_ptr nspace, const_String_or_char_ptr classname);
+ extern String *Swig_name_destroy(const_String_or_char_ptr nspace, const_String_or_char_ptr classname);
+ extern String *Swig_name_disown(const_String_or_char_ptr nspace, const_String_or_char_ptr classname);
+
+ extern void Swig_naming_init(void);
+ extern void Swig_name_namewarn_add(String *prefix, String *name, SwigType *decl, Hash *namewrn);
+ extern void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *namewrn, ParmList *declaratorparms);
+ extern void Swig_name_inherit(String *base, String *derived);
+ extern List *Swig_make_inherit_list(String *clsname, List *names, String *Namespaceprefix);
+ extern void Swig_inherit_base_symbols(List *bases);
+ extern int Swig_need_protected(Node *n);
+ extern int Swig_need_redefined_warn(Node *a, Node *b, int InClass);
+
+ extern String *Swig_name_make(Node *n, String *prefix, const_String_or_char_ptr cname, SwigType *decl, String *oldname);
+ extern String *Swig_name_warning(Node *n, String *prefix, String *name, SwigType *decl);
+ extern String *Swig_name_str(Node *n);
+ extern String *Swig_name_decl(Node *n);
+ extern String *Swig_name_fulldecl(Node *n);
+
+/* --- parameterized rename functions --- */
+
+ extern void Swig_name_object_set(Hash *namehash, String *name, SwigType *decl, DOH *object);
+ extern DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType *decl);
+ extern void Swig_name_object_inherit(Hash *namehash, String *base, String *derived);
+ extern void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *decl, Node *n);
+ extern void Swig_feature_set(Hash *features, const_String_or_char_ptr name, SwigType *decl, const_String_or_char_ptr featurename, const_String_or_char_ptr value, Hash *featureattribs);
+
+/* --- Misc --- */
+ extern char *Swig_copy_string(const char *c);
+ extern void Swig_set_fakeversion(const char *version);
+ extern const char *Swig_package_version(void);
+ extern String *Swig_package_version_hex(void);
+ extern void Swig_obligatory_macros(String *f_runtime, const char *language);
+ extern void Swig_banner(File *f);
+ extern void Swig_banner_target_lang(File *f, const_String_or_char_ptr commentchar);
+ extern String *Swig_strip_c_comments(const String *s);
+ extern String *Swig_new_subdirectory(String *basedirectory, String *subdirectory);
+ extern void Swig_filename_correct(String *filename);
+ extern String *Swig_filename_escape(String *filename);
+ extern String *Swig_filename_escape_space(String *filename);
+ extern void Swig_filename_unescape(String *filename);
+ extern int Swig_storage_isextern(Node *n);
+ extern int Swig_storage_isexternc(Node *n);
+ extern int Swig_storage_isstatic_custom(Node *n, const_String_or_char_ptr storage);
+ extern int Swig_storage_isstatic(Node *n);
+ extern String *Swig_string_escape(String *s);
+ extern String *Swig_string_mangle(const String *s);
+ extern void Swig_scopename_split(const String *s, String **prefix, String **last);
+ extern String *Swig_scopename_prefix(const String *s);
+ extern String *Swig_scopename_last(const String *s);
+ extern String *Swig_scopename_first(const String *s);
+ extern String *Swig_scopename_suffix(const String *s);
+ extern List *Swig_scopename_tolist(const String *s);
+ extern int Swig_scopename_check(const String *s);
+ extern String *Swig_string_lower(String *s);
+ extern String *Swig_string_upper(String *s);
+ extern String *Swig_string_title(String *s);
+ extern void Swig_offset_string(String *s, int number);
+ extern String *Swig_pcre_version(void);
+ extern void Swig_init(void);
+
+ extern int Swig_value_wrapper_mode(int mode);
+ extern int Swig_is_generated_overload(Node *n);
+
+ typedef enum { EMF_STANDARD, EMF_MICROSOFT } ErrorMessageFormat;
+
+ extern void Swig_warning(int num, const_String_or_char_ptr filename, int line, const char *fmt, ...);
+ extern void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, ...);
+ extern int Swig_error_count(void);
+ extern void Swig_error_silent(int s);
+ extern void Swig_warnfilter(const_String_or_char_ptr wlist, int val);
+ extern void Swig_warnall(void);
+ extern int Swig_warn_count(void);
+ extern void Swig_error_msg_format(ErrorMessageFormat format);
+ extern void Swig_diagnostic(const_String_or_char_ptr filename, int line, const char *fmt, ...);
+ extern String *Swig_stringify_with_location(DOH *object);
+
+/* --- C Wrappers --- */
+ extern void Swig_cresult_name_set(const char *new_name);
+ extern const char *Swig_cresult_name(void);
+ extern String *Swig_cparm_name(Parm *p, int i);
+ extern String *Swig_wrapped_var_type(SwigType *t, int varcref);
+ extern int Swig_cargs(Wrapper *w, ParmList *l);
+ extern String *Swig_cresult(SwigType *t, const_String_or_char_ptr name, const_String_or_char_ptr decl);
+
+ extern String *Swig_cfunction_call(const_String_or_char_ptr name, ParmList *parms);
+ extern String *Swig_cconstructor_call(const_String_or_char_ptr name);
+ extern String *Swig_cppconstructor_call(const_String_or_char_ptr name, ParmList *parms);
+ extern String *Swig_unref_call(Node *n);
+ extern String *Swig_ref_call(Node *n, const String *lname);
+ extern String *Swig_cdestructor_call(Node *n);
+ extern String *Swig_cppdestructor_call(Node *n);
+ extern String *Swig_cmemberset_call(const_String_or_char_ptr name, SwigType *type, String *self, int varcref);
+ extern String *Swig_cmemberget_call(const_String_or_char_ptr name, SwigType *t, String *self, int varcref);
+
+ extern int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self);
+ extern void Swig_replace_special_variables(Node *n, Node *parentnode, String *code);
+
+/* --- Transformations --- */
+
+ extern int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int flags, SwigType *director_type, int is_director);
+ extern int Swig_ConstructorToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, String *none_comparison, String *director_ctor, int cplus, int flags, String *directorname);
+ extern int Swig_DestructorToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int cplus, int flags);
+ extern int Swig_MembersetToFunction(Node *n, String *classname, int flags);
+ extern int Swig_MembergetToFunction(Node *n, String *classname, int flags);
+ extern int Swig_VargetToFunction(Node *n, int flags);
+ extern int Swig_VarsetToFunction(Node *n, int flags);
+
+#define CWRAP_EXTEND 0x01
+#define CWRAP_SMART_POINTER 0x02
+#define CWRAP_NATURAL_VAR 0x04
+#define CWRAP_DIRECTOR_ONE_CALL 0x08
+#define CWRAP_DIRECTOR_TWO_CALLS 0x10
+#define CWRAP_ALL_PROTECTED_ACCESS 0x20
+#define CWRAP_SMART_POINTER_OVERLOAD 0x40
+
+/* --- Director Helpers --- */
+ extern Node *Swig_methodclass(Node *n);
+ extern int Swig_directorclass(Node *n);
+ extern Node *Swig_directormap(Node *n, String *type);
+
+/* --- Legacy Typemap API (somewhat simplified, ha!) --- */
+
+ extern void Swig_typemap_init(void);
+ extern void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *pattern, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs);
+ extern int Swig_typemap_copy(const_String_or_char_ptr tmap_method, ParmList *srcpattern, ParmList *pattern);
+ extern void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *pattern);
+ extern int Swig_typemap_apply(ParmList *srcpat, ParmList *destpat);
+ extern void Swig_typemap_clear_apply(ParmList *pattern);
+ extern void Swig_typemap_replace_embedded_typemap(String *s, Node *file_line_node);
+ extern void Swig_typemap_debug(void);
+ extern void Swig_typemap_search_debug_set(void);
+ extern void Swig_typemap_used_debug_set(void);
+ extern void Swig_typemap_register_debug_set(void);
+
+ extern String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f);
+ extern String *Swig_typemap_lookup_out(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f, String *actioncode);
+
+ extern void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f);
+
+/* --- Code fragment support --- */
+
+ extern void Swig_fragment_register(Node *fragment);
+ extern void Swig_fragment_emit(String *name);
+ extern void Swig_fragment_clear(String *section);
+
+/* --- Extension support --- */
+
+ extern Hash *Swig_extend_hash(void);
+ extern void Swig_extend_merge(Node *cls, Node *am);
+ extern void Swig_extend_append_previous(Node *cls, Node *am);
+ extern void Swig_extend_unused_check(void);
+
+/* hacks defined in C++ ! */
+ extern int Swig_director_mode(void);
+ extern int Swig_director_protected_mode(void);
+ extern int Swig_all_protected_mode(void);
+ extern void Wrapper_director_mode_set(int);
+ extern void Wrapper_director_protected_mode_set(int);
+ extern void Wrapper_all_protected_mode_set(int);
+ extern void Language_replace_special_variables(String *method, String *tm, Parm *parm);
+ extern void Swig_print(DOH *object, int count);
+ extern void Swig_print_with_location(DOH *object, int count);
+
+/* -- template init -- */
+ extern void SwigType_template_init(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/contrib/tools/swig/Source/Swig/swigfile.h b/contrib/tools/swig/Source/Swig/swigfile.h
new file mode 100644
index 0000000000..009599a112
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigfile.h
@@ -0,0 +1,41 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * swigfile.h
+ *
+ * File handling functions in the SWIG core
+ * ----------------------------------------------------------------------------- */
+
+extern List *Swig_add_directory(const_String_or_char_ptr dirname);
+extern void Swig_push_directory(const_String_or_char_ptr dirname);
+extern void Swig_pop_directory(void);
+extern String *Swig_last_file(void);
+extern List *Swig_search_path(void);
+extern FILE *Swig_include_open(const_String_or_char_ptr name);
+extern FILE *Swig_open(const_String_or_char_ptr name);
+extern String *Swig_read_file(FILE *f);
+extern String *Swig_include(const_String_or_char_ptr name);
+extern String *Swig_include_sys(const_String_or_char_ptr name);
+extern int Swig_insert_file(const_String_or_char_ptr name, File *outfile);
+extern void Swig_set_push_dir(int dopush);
+extern int Swig_get_push_dir(void);
+extern void Swig_register_filebyname(const_String_or_char_ptr filename, File *outfile);
+extern File *Swig_filebyname(const_String_or_char_ptr filename);
+extern String *Swig_file_extension(const_String_or_char_ptr filename);
+extern String *Swig_file_basename(const_String_or_char_ptr filename);
+extern String *Swig_file_filename(const_String_or_char_ptr filename);
+extern String *Swig_file_dirname(const_String_or_char_ptr filename);
+extern void Swig_file_debug_set(void);
+
+/* Delimiter used in accessing files and directories */
+
+#if defined(_WIN32)
+# define SWIG_FILE_DELIMITER "\\"
+#else
+# define SWIG_FILE_DELIMITER "/"
+#endif
diff --git a/contrib/tools/swig/Source/Swig/swigopt.h b/contrib/tools/swig/Source/Swig/swigopt.h
new file mode 100644
index 0000000000..86a477b8f7
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigopt.h
@@ -0,0 +1,18 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * swigopt.h
+ *
+ * Header file for the SWIG command line processing functions
+ * ----------------------------------------------------------------------------- */
+
+ extern void Swig_init_args(int argc, char **argv);
+ extern void Swig_mark_arg(int n);
+ extern int Swig_check_marked(int n);
+ extern void Swig_check_options(int check_input);
+ extern void Swig_arg_error(void);
diff --git a/contrib/tools/swig/Source/Swig/swigparm.h b/contrib/tools/swig/Source/Swig/swigparm.h
new file mode 100644
index 0000000000..7b63546ec0
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigparm.h
@@ -0,0 +1,35 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * swigparm.h
+ *
+ * Functions related to the handling of function/method parameters and
+ * parameter lists.
+ * ----------------------------------------------------------------------------- */
+
+/* Individual parameters */
+extern Parm *NewParm(SwigType *type, const_String_or_char_ptr name, Node *from_node);
+extern Parm *NewParmWithoutFileLineInfo(SwigType *type, const_String_or_char_ptr name);
+extern Parm *NewParmNode(SwigType *type, Node *from_node);
+extern Parm *CopyParm(Parm *p);
+
+/* Parameter lists */
+extern ParmList *CopyParmList(ParmList *);
+extern ParmList *CopyParmListMax(ParmList *, int count);
+extern int ParmList_len(ParmList *);
+extern int ParmList_numrequired(ParmList *);
+extern int ParmList_has_defaultargs(ParmList *p);
+extern int ParmList_has_varargs(ParmList *p);
+
+/* Output functions */
+extern String *ParmList_str(ParmList *);
+extern String *ParmList_str_defaultargs(ParmList *);
+extern String *ParmList_str_multibrackets(ParmList *);
+extern String *ParmList_protostr(ParmList *);
+
+
diff --git a/contrib/tools/swig/Source/Swig/swigscan.h b/contrib/tools/swig/Source/Swig/swigscan.h
new file mode 100644
index 0000000000..6c9d1ff7fc
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigscan.h
@@ -0,0 +1,119 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * swigscan.h
+ *
+ * C/C++ scanner.
+ * ----------------------------------------------------------------------------- */
+
+typedef struct Scanner Scanner;
+
+extern Scanner *NewScanner(void);
+extern void DelScanner(Scanner *);
+extern void Scanner_clear(Scanner *);
+extern void Scanner_push(Scanner *, String *);
+extern void Scanner_pushtoken(Scanner *, int, const_String_or_char_ptr value);
+extern int Scanner_token(Scanner *);
+extern String *Scanner_text(Scanner *);
+extern void Scanner_skip_line(Scanner *);
+extern int Scanner_skip_balanced(Scanner *, int startchar, int endchar);
+extern String *Scanner_get_raw_text_balanced(Scanner *, int startchar, int endchar);
+extern void Scanner_set_location(Scanner *, String *file, int line);
+extern String *Scanner_file(Scanner *);
+extern int Scanner_line(Scanner *);
+extern int Scanner_start_line(Scanner *);
+extern void Scanner_idstart(Scanner *, const char *idchar);
+extern String *Scanner_errmsg(Scanner *);
+extern int Scanner_errline(Scanner *);
+extern int Scanner_isoperator(int tokval);
+extern void Scanner_locator(Scanner *, String *loc);
+
+/* Note: Tokens in range 100+ are for C/C++ operators */
+
+#define SWIG_MAXTOKENS 200
+#define SWIG_TOKEN_LPAREN 1 /* ( */
+#define SWIG_TOKEN_RPAREN 2 /* ) */
+#define SWIG_TOKEN_SEMI 3 /* ; */
+#define SWIG_TOKEN_LBRACE 4 /* { */
+#define SWIG_TOKEN_RBRACE 5 /* } */
+#define SWIG_TOKEN_LBRACKET 6 /* [ */
+#define SWIG_TOKEN_RBRACKET 7 /* ] */
+#define SWIG_TOKEN_BACKSLASH 8 /* \ */
+#define SWIG_TOKEN_ENDLINE 9 /* \n */
+#define SWIG_TOKEN_STRING 10 /* "str" */
+#define SWIG_TOKEN_POUND 11 /* # */
+#define SWIG_TOKEN_COLON 12 /* : */
+#define SWIG_TOKEN_DCOLON 13 /* :: */
+#define SWIG_TOKEN_DCOLONSTAR 14 /* ::* */
+#define SWIG_TOKEN_ID 15 /* identifier */
+#define SWIG_TOKEN_FLOAT 16 /* 3.1415F */
+#define SWIG_TOKEN_DOUBLE 17 /* 3.1415 */
+#define SWIG_TOKEN_INT 18 /* 314 */
+#define SWIG_TOKEN_UINT 19 /* 314U */
+#define SWIG_TOKEN_LONG 20 /* 314L */
+#define SWIG_TOKEN_ULONG 21 /* 314UL */
+#define SWIG_TOKEN_CHAR 22 /* 'charconst' */
+#define SWIG_TOKEN_PERIOD 23 /* . */
+#define SWIG_TOKEN_AT 24 /* @ */
+#define SWIG_TOKEN_DOLLAR 25 /* $ */
+#define SWIG_TOKEN_CODEBLOCK 26 /* %{ ... %} ... */
+#define SWIG_TOKEN_RSTRING 27 /* `charconst` */
+#define SWIG_TOKEN_LONGLONG 28 /* 314LL */
+#define SWIG_TOKEN_ULONGLONG 29 /* 314ULL */
+#define SWIG_TOKEN_QUESTION 30 /* ? */
+#define SWIG_TOKEN_COMMENT 31 /* C or C++ comment */
+#define SWIG_TOKEN_BOOL 32 /* true or false */
+#define SWIG_TOKEN_WSTRING 33 /* L"str" */
+#define SWIG_TOKEN_WCHAR 34 /* L'c' */
+#define SWIG_TOKEN_ELLIPSIS 35 /* ... */
+#define SWIG_TOKEN_LLBRACKET 36 /* [[ */
+#define SWIG_TOKEN_RRBRACKET 37 /* ]] */
+
+#define SWIG_TOKEN_ILLEGAL 99
+#define SWIG_TOKEN_ERROR -1
+
+#define SWIG_TOKEN_COMMA 101 /* , */
+#define SWIG_TOKEN_STAR 102 /* * */
+#define SWIG_TOKEN_TIMES 102 /* * */
+#define SWIG_TOKEN_EQUAL 103 /* = */
+#define SWIG_TOKEN_EQUALTO 104 /* == */
+#define SWIG_TOKEN_NOTEQUAL 105 /* != */
+#define SWIG_TOKEN_PLUS 106 /* + */
+#define SWIG_TOKEN_MINUS 107 /* - */
+#define SWIG_TOKEN_AND 108 /* & */
+#define SWIG_TOKEN_LAND 109 /* && */
+#define SWIG_TOKEN_OR 110 /* | */
+#define SWIG_TOKEN_LOR 111 /* || */
+#define SWIG_TOKEN_XOR 112 /* ^ */
+#define SWIG_TOKEN_LESSTHAN 113 /* < */
+#define SWIG_TOKEN_GREATERTHAN 114 /* > */
+#define SWIG_TOKEN_LTEQUAL 115 /* <= */
+#define SWIG_TOKEN_GTEQUAL 116 /* >= */
+#define SWIG_TOKEN_NOT 117 /* ~ */
+#define SWIG_TOKEN_LNOT 118 /* ! */
+#define SWIG_TOKEN_SLASH 119 /* / */
+#define SWIG_TOKEN_DIVIDE 119 /* / */
+#define SWIG_TOKEN_PERCENT 120 /* % */
+#define SWIG_TOKEN_MODULO 120 /* % */
+#define SWIG_TOKEN_LSHIFT 121 /* << */
+#define SWIG_TOKEN_RSHIFT 122 /* >> */
+#define SWIG_TOKEN_PLUSPLUS 123 /* ++ */
+#define SWIG_TOKEN_MINUSMINUS 124 /* -- */
+#define SWIG_TOKEN_PLUSEQUAL 125 /* += */
+#define SWIG_TOKEN_MINUSEQUAL 126 /* -= */
+#define SWIG_TOKEN_TIMESEQUAL 127 /* *= */
+#define SWIG_TOKEN_DIVEQUAL 128 /* /= */
+#define SWIG_TOKEN_ANDEQUAL 129 /* &= */
+#define SWIG_TOKEN_OREQUAL 130 /* |= */
+#define SWIG_TOKEN_XOREQUAL 131 /* ^= */
+#define SWIG_TOKEN_LSEQUAL 132 /* <<= */
+#define SWIG_TOKEN_RSEQUAL 133 /* >>= */
+#define SWIG_TOKEN_MODEQUAL 134 /* %= */
+#define SWIG_TOKEN_ARROW 135 /* -> */
+#define SWIG_TOKEN_ARROWSTAR 136 /* ->* */
+#define SWIG_TOKEN_LTEQUALGT 137 /* <=> */
diff --git a/contrib/tools/swig/Source/Swig/swigtree.h b/contrib/tools/swig/Source/Swig/swigtree.h
new file mode 100644
index 0000000000..8d63d8fd33
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigtree.h
@@ -0,0 +1,54 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * swigtree.h
+ *
+ * These functions are used to access and manipulate the SWIG parse tree.
+ * The structure of this tree is modeled directly after XML-DOM. The attribute
+ * and function names are meant to be similar.
+ * ----------------------------------------------------------------------------- */
+
+/* Macros to traverse the DOM tree */
+
+#define nodeType(x) Getattr(x,"nodeType")
+#define parentNode(x) Getattr(x,"parentNode")
+#define previousSibling(x) Getattr(x,"previousSibling")
+#define nextSibling(x) Getattr(x,"nextSibling")
+#define firstChild(x) Getattr(x,"firstChild")
+#define lastChild(x) Getattr(x,"lastChild")
+
+/* Macros to set up the DOM tree (mostly used by the parser) */
+
+#define set_nodeType(x,v) Setattr(x,"nodeType",v)
+#define set_parentNode(x,v) Setattr(x,"parentNode",v)
+#define set_previousSibling(x,v) Setattr(x,"previousSibling",v)
+#define set_nextSibling(x,v) Setattr(x,"nextSibling",v)
+#define set_firstChild(x,v) Setattr(x,"firstChild",v)
+#define set_lastChild(x,v) Setattr(x,"lastChild",v)
+
+/* Utility functions */
+
+extern int checkAttribute(Node *obj, const_String_or_char_ptr name, const_String_or_char_ptr value);
+extern void appendChild(Node *node, Node *child);
+extern void prependChild(Node *node, Node *child);
+extern void removeNode(Node *node);
+extern Node *copyNode(Node *node);
+extern void appendSibling(Node *node, Node *child);
+
+/* Node restoration/restore functions */
+
+extern void Swig_require(const char *ns, Node *node, ...);
+extern void Swig_save(const char *ns, Node *node, ...);
+extern void Swig_restore(Node *node);
+
+/* Debugging of parse trees */
+
+extern void Swig_print_tags(File *obj, Node *root);
+extern void Swig_print_tree(Node *obj);
+extern void Swig_print_node(Node *obj);
+extern int Swig_print_quiet(int quiet);
diff --git a/contrib/tools/swig/Source/Swig/swigwrap.h b/contrib/tools/swig/Source/Swig/swigwrap.h
new file mode 100644
index 0000000000..b584ca495b
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigwrap.h
@@ -0,0 +1,31 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * swigwrap.h
+ *
+ * Functions related to wrapper objects.
+ * ----------------------------------------------------------------------------- */
+
+typedef struct Wrapper {
+ Hash *localh;
+ String *def;
+ String *locals;
+ String *code;
+} Wrapper;
+
+extern Wrapper *NewWrapper(void);
+extern void DelWrapper(Wrapper *w);
+extern void Wrapper_compact_print_mode_set(int flag);
+extern void Wrapper_pretty_print(String *str, File *f);
+extern void Wrapper_compact_print(String *str, File *f);
+extern void Wrapper_print(Wrapper *w, File *f);
+extern int Wrapper_add_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl);
+extern int Wrapper_add_localv(Wrapper *w, const_String_or_char_ptr name, ...);
+extern int Wrapper_check_local(Wrapper *w, const_String_or_char_ptr name);
+extern char *Wrapper_new_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl);
+extern char *Wrapper_new_localv(Wrapper *w, const_String_or_char_ptr name, ...);
diff --git a/contrib/tools/swig/Source/Swig/symbol.c b/contrib/tools/swig/Source/Swig/symbol.c
new file mode 100644
index 0000000000..107b1caef9
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/symbol.c
@@ -0,0 +1,2128 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * symbol.c
+ *
+ * This file implements the SWIG symbol table. See details below.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+#include <ctype.h>
+
+/* #define SWIG_DEBUG*/
+/* -----------------------------------------------------------------------------
+ * Synopsis
+ *
+ * This module provides symbol table management for all of SWIG. In previous
+ * releases, the management of symbols was rather haphazard. This module tries
+ * to correct that.
+ *
+ * All symbols are associated with simple identifiers. For example, here are some
+ * declarations that generate symbol table entries:
+ *
+ * decl symbol
+ * -------------- ------------
+ * void foo(int); foo
+ * int x; x
+ * typedef int *blah; blah
+ *
+ * Associated with each symbol is a Hash table that can contain any set of
+ * attributes that make sense for that object. For example:
+ *
+ * typedef int *blah; ----> "name" : 'blah'
+ * "type" : 'int'
+ * "decl" : 'p.'
+ * "storage" : 'typedef'
+ *
+ * In some cases, the symbol table needs to manage overloaded entries. For instance,
+ * overloaded functions. In this case, a linked list is built. The "sym:nextSibling"
+ * attribute is reserved to hold a link to the next entry. For example:
+ *
+ * int foo(int); --> "name" : "foo" "name" : "foo"
+ * int foo(int,double); "type" : "int" "type" : "int"
+ * "decl" : "f(int)." "decl" : "f(int,double)."
+ * ... ...
+ * "sym:nextSibling" : --------> "sym:nextSibling": --------> ...
+ *
+ * When more than one symbol has the same name, the symbol declarator is
+ * used to detect duplicates. For example, in the above case, foo(int) and
+ * foo(int,double) are different because their "decl" attribute is different.
+ * However, if a third declaration "foo(int)" was made, it would generate a
+ * conflict (due to having a declarator that matches a previous entry).
+ *
+ * Structures and classes:
+ *
+ * C/C++ symbol tables are normally managed in a few different spaces. The
+ * most visible namespace is reserved for functions, variables, typedef, enum values
+ * and such. In C, a separate tag-space is reserved for 'struct name', 'class name',
+ * and 'union name' declarations. In SWIG, a single namespace is used for everything
+ * this means that certain incompatibilities will arise with some C programs. For instance:
+ *
+ * struct Foo {
+ * ...
+ * }
+ *
+ * int Foo(); // Error. Name clash. Works in C though
+ *
+ * Due to the unified namespace for structures, special handling is performed for
+ * the following:
+ *
+ * typedef struct Foo {
+ *
+ * } Foo;
+ *
+ * In this case, the symbol table contains an entry for the structure itself. The
+ * typedef is left out of the symbol table.
+ *
+ * Target language vs C:
+ *
+ * The symbol tables are normally managed *in the namespace of the target language*.
+ * This means that name-collisions can be resolved using %rename and related
+ * directives. A quirk of this is that sometimes the symbol tables need to
+ * be used for C type resolution as well. To handle this, each symbol table
+ * also has a C-symbol table lurking behind the scenes. This is used to locate
+ * symbols in the C namespace. However, this symbol table is not used for error
+ * reporting nor is it used for anything else during code generation.
+ *
+ * Symbol table structure:
+ *
+ * Symbol tables themselves are a special kind of node that is organized just like
+ * a normal parse tree node. Symbol tables are organized in a tree that can be
+ * traversed using the SWIG-DOM API. The following attributes names are reserved.
+ *
+ * name -- Name of the scope defined by the symbol table (if any)
+ * This name is the C-scope name and is not affected by
+ * %renaming operations
+ * symtab -- Hash table mapping identifiers to nodes.
+ * csymtab -- Hash table mapping C identifiers to nodes.
+ *
+ * Reserved attributes on symbol objects:
+ *
+ * When a symbol is placed in the symbol table, the following attributes
+ * are set:
+ *
+ * sym:name -- Symbol name
+ * sym:nextSibling -- Next symbol (if overloaded)
+ * sym:previousSibling -- Previous symbol (if overloaded)
+ * sym:symtab -- Symbol table object holding the symbol
+ * sym:overloaded -- Set to the first symbol if overloaded
+ *
+ * These names are modeled after XML namespaces. In particular, every attribute
+ * pertaining to symbol table management is prefaced by the "sym:" prefix.
+ *
+ * An example dump of the parse tree showing symbol table entries for the
+ * following code should clarify this:
+ *
+ * namespace OuterNamespace {
+ * namespace InnerNamespace {
+ * class Class {
+ * };
+ * struct Struct {
+ * int Var;
+ * };
+ * }
+ * }
+ *
+ * +++ namespace ----------------------------------------
+ * | sym:name - "OuterNamespace"
+ * | symtab - 0xa064bf0
+ * | sym:symtab - 0xa041690
+ * | sym:overname - "__SWIG_0"
+ *
+ * +++ namespace ----------------------------------------
+ * | sym:name - "InnerNamespace"
+ * | symtab - 0xa064cc0
+ * | sym:symtab - 0xa064bf0
+ * | sym:overname - "__SWIG_0"
+ *
+ * +++ class ----------------------------------------
+ * | sym:name - "Class"
+ * | symtab - 0xa064d80
+ * | sym:symtab - 0xa064cc0
+ * | sym:overname - "__SWIG_0"
+ * |
+ * +++ class ----------------------------------------
+ * | sym:name - "Struct"
+ * | symtab - 0xa064f00
+ * | sym:symtab - 0xa064cc0
+ * | sym:overname - "__SWIG_0"
+ *
+ * +++ cdecl ----------------------------------------
+ * | sym:name - "Var"
+ * | sym:symtab - 0xa064f00
+ * | sym:overname - "__SWIG_0"
+ * |
+ *
+ *
+ * Each class and namespace has its own scope and thus a new symbol table (sym)
+ * is created. The sym attribute is only set for the first entry in the symbol
+ * table. The sym:symtab entry points to the symbol table in which the symbol
+ * exists, so for example, Struct is in the scope OuterNamespace::InnerNamespace
+ * so sym:symtab points to this symbol table (0xa064cc0).
+ *
+ * ----------------------------------------------------------------------------- */
+
+static Hash *current = 0; /* The current symbol table hash */
+static Hash *ccurrent = 0; /* The current c symbol table hash */
+static Hash *current_symtab = 0; /* Current symbol table node */
+static Hash *symtabs = 0; /* Hash of all symbol tables by fully-qualified name */
+static Hash *global_scope = 0; /* Global scope */
+
+static int use_inherit = 1;
+
+/* common attribute keys, to avoid calling find_key all the times */
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_tables()
+ *
+ * Debug display of symbol tables
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_tables(Symtab *symtab) {
+ if (!symtab)
+ symtab = current_symtab;
+
+ Printf(stdout, "SYMBOL TABLES start =======================================\n");
+ Swig_print_tree(symtab);
+ Printf(stdout, "SYMBOL TABLES finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_tables_summary()
+ *
+ * Debug summary display of all symbol tables by fully-qualified name
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_tables_summary(void) {
+ Printf(stdout, "SYMBOL TABLES SUMMARY start =======================================\n");
+ Swig_print_node(symtabs);
+ Printf(stdout, "SYMBOL TABLES SUMMARY finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * symbol_print_symbols()
+ * ----------------------------------------------------------------------------- */
+
+static void symbol_print_symbols(const char *symboltabletype, const char *nextSibling) {
+ Node *table = symtabs;
+ Iterator ki = First(table);
+ int show_pointers = 0;
+ while (ki.key) {
+ String *k = ki.key;
+ Printf(stdout, "===================================================\n");
+ Printf(stdout, "%s -\n", k);
+ {
+ Symtab *symtab = Getattr(Getattr(table, k), symboltabletype);
+ Iterator it = First(symtab);
+ while (it.key) {
+ String *symname = it.key;
+ Printf(stdout, " %s (%s)", symname, nodeType(it.item));
+ if (show_pointers)
+ Printf(stdout, " %p", it.item);
+ Printf(stdout, "\n");
+ {
+ Node *sibling = Getattr(it.item, nextSibling);
+ while (sibling) {
+ Printf(stdout, " %s (%s)", symname, nodeType(sibling));
+ if (show_pointers)
+ Printf(stdout, " %p", sibling);
+ Printf(stdout, "\n");
+ sibling = Getattr(sibling, nextSibling);
+ }
+ }
+ it = Next(it);
+ }
+ }
+ ki = Next(ki);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_symbols()
+ *
+ * Debug display of all the target language symbols
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_symbols(void) {
+ Printf(stdout, "SYMBOLS start =======================================\n");
+ symbol_print_symbols("symtab", "sym:nextSibling");
+ Printf(stdout, "SYMBOLS finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_csymbols()
+ *
+ * Debug display of all the C symbols
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_csymbols(void) {
+ Printf(stdout, "CSYMBOLS start =======================================\n");
+ symbol_print_symbols("csymtab", "csym:nextSibling");
+ Printf(stdout, "CSYMBOLS finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_init()
+ *
+ * Create a new symbol table object
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_init(void) {
+
+ current = NewHash();
+ current_symtab = NewHash();
+ ccurrent = NewHash();
+ set_nodeType(current_symtab, "symboltable");
+ Setattr(current_symtab, "symtab", current);
+ Delete(current);
+ Setattr(current_symtab, "csymtab", ccurrent);
+ Delete(ccurrent);
+
+ /* Set the global scope */
+ symtabs = NewHash();
+ Setattr(symtabs, "", current_symtab);
+ Delete(current_symtab);
+ global_scope = current_symtab;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_setscopename()
+ *
+ * Set the C scopename of the current symbol table.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_setscopename(const_String_or_char_ptr name) {
+ String *qname;
+ /* assert(!Getattr(current_symtab,"name")); */
+ Setattr(current_symtab, "name", name);
+
+ /* Set nested scope in parent */
+
+ qname = Swig_symbol_qualifiedscopename(current_symtab);
+
+ /* Save a reference to this scope */
+ Setattr(symtabs, qname, current_symtab);
+ Delete(qname);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_getscopename()
+ *
+ * Get the C scopename of the current symbol table
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_getscopename(void) {
+ return Getattr(current_symtab, "name");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_getscope()
+ *
+ * Given a fully qualified C scopename, this function returns a symbol table
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_getscope(const_String_or_char_ptr name) {
+ if (!symtabs)
+ return 0;
+ if (Equal("::", (const_String_or_char_ptr ) name))
+ name = "";
+ return Getattr(symtabs, name);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_qualifiedscopename()
+ *
+ * Get the fully qualified C scopename of a symbol table. Note, this only pertains
+ * to the C/C++ scope name. It is not affected by renaming.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_qualifiedscopename(Symtab *symtab) {
+ String *result = 0;
+ Hash *parent;
+ String *name;
+ if (!symtab)
+ symtab = current_symtab;
+ parent = Getattr(symtab, "parentNode");
+ if (parent) {
+ result = Swig_symbol_qualifiedscopename(parent);
+ }
+ name = Getattr(symtab, "name");
+ if (name) {
+ if (!result) {
+ result = NewStringEmpty();
+ }
+ if (Len(result)) {
+ Printv(result, "::", name, NIL);
+ } else {
+ Append(result, name);
+ }
+ }
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_qualified_language_scopename()
+ *
+ * Get the fully qualified C scopename of a symbol table but using a language
+ * specific separator for the scopenames. Basically the same as
+ * Swig_symbol_qualifiedscopename() but using the different separator.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_qualified_language_scopename(Symtab *n) {
+ /* TODO: fix for %rename to work */
+ String *result = Swig_symbol_qualifiedscopename(n);
+ Replaceall(result, "::", NSPACE_SEPARATOR);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_newscope()
+ *
+ * Create a new scope. Returns the newly created scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_newscope(void) {
+ Hash *n;
+ Hash *hsyms, *h;
+
+ hsyms = NewHash();
+ h = NewHash();
+
+ set_nodeType(h, "symboltable");
+ Setattr(h, "symtab", hsyms);
+ Delete(hsyms);
+ set_parentNode(h, current_symtab);
+
+ n = lastChild(current_symtab);
+ if (!n) {
+ set_firstChild(current_symtab, h);
+ } else {
+ set_nextSibling(n, h);
+ Delete(h);
+ }
+ set_lastChild(current_symtab, h);
+ current = hsyms;
+ ccurrent = NewHash();
+ Setattr(h, "csymtab", ccurrent);
+ Delete(ccurrent);
+ current_symtab = h;
+ return h;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_setscope()
+ *
+ * Set the current scope. Returns the previous current scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_setscope(Symtab *sym) {
+ Symtab *ret = current_symtab;
+ current_symtab = sym;
+ current = Getattr(sym, "symtab");
+ assert(current);
+ ccurrent = Getattr(sym, "csymtab");
+ assert(ccurrent);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_popscope()
+ *
+ * Pop out of the current scope. Returns the popped scope and sets the
+ * scope to the parent scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_popscope(void) {
+ Hash *h = current_symtab;
+ current_symtab = Getattr(current_symtab, "parentNode");
+ assert(current_symtab);
+ current = Getattr(current_symtab, "symtab");
+ assert(current);
+ ccurrent = Getattr(current_symtab, "csymtab");
+ assert(ccurrent);
+ return h;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_global_scope()
+ *
+ * Return the symbol table for the global scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_global_scope(void) {
+ return global_scope;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_current()
+ *
+ * Return the current symbol table.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_current(void) {
+ return current_symtab;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_alias()
+ *
+ * Makes an alias for a symbol in the global symbol table.
+ * Primarily for namespace aliases such as 'namespace X = Y;'.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_alias(const_String_or_char_ptr aliasname, Symtab *s) {
+ String *qname = Swig_symbol_qualifiedscopename(current_symtab);
+ if (qname) {
+ Printf(qname, "::%s", aliasname);
+ } else {
+ qname = NewString(aliasname);
+ }
+ if (!Getattr(symtabs, qname)) {
+ Setattr(symtabs, qname, s);
+ }
+ Delete(qname);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_inherit()
+ *
+ * Inherit symbols from another scope. Primarily for C++ inheritance and
+ * for using directives, such as 'using namespace X;'
+ * but not for using declarations, such as 'using A;'.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_inherit(Symtab *s) {
+ int i, ilen;
+ List *inherit = Getattr(current_symtab, "inherit");
+ if (!inherit) {
+ inherit = NewList();
+ Setattr(current_symtab, "inherit", inherit);
+ Delete(inherit);
+ }
+
+ if (s == current_symtab) {
+ Swig_warning(WARN_PARSE_REC_INHERITANCE, Getfile(s), Getline(s), "Recursive scope inheritance of '%s'.\n", Getattr(s, "name"));
+ return;
+ }
+ assert(s != current_symtab);
+ ilen = Len(inherit);
+ for (i = 0; i < ilen; i++) {
+ Node *n = Getitem(inherit, i);
+ if (n == s)
+ return; /* Already inherited */
+ }
+ Append(inherit, s);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_cadd()
+ *
+ * Adds a node to the C symbol table only.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) {
+ Node *append = 0;
+ Node *cn;
+ /* There are a few options for weak symbols. A "weak" symbol
+ is any symbol that can be replaced by another symbol in the C symbol
+ table. An example would be a forward class declaration. A forward
+ class sits in the symbol table until a real class declaration comes along.
+
+ Certain symbols are marked as "sym:typename". These are important
+ symbols related to the C++ type-system and take precedence in the C
+ symbol table. An example might be code like this:
+
+ template<class T> T foo(T x);
+ int foo(int);
+
+ In this case, the template is marked with "sym:typename" so that it
+ stays in the C symbol table (so that it can be expanded using %template).
+ */
+
+ if (!name)
+ return;
+
+ if (SwigType_istemplate(name)) {
+ String *cname = NewString(name);
+ String *dname = Swig_symbol_template_deftype(cname, 0);
+ if (!Equal(dname, name)) {
+ Swig_symbol_cadd(dname, n);
+ }
+ Delete(dname);
+ Delete(cname);
+ }
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_cadd %s %p\n", name, n);
+#endif
+ cn = Getattr(ccurrent, name);
+
+ if (cn && (Getattr(cn, "sym:typename"))) {
+ /* The node in the C symbol table is a typename. Do nothing */
+ /* We might append the symbol at the end */
+ append = n;
+ } else if (cn && (Getattr(cn, "sym:weak"))) {
+ /* The node in the symbol table is weak. Replace it */
+ if (checkAttribute(cn, "nodeType", "template")
+ && checkAttribute(cn, "templatetype", "classforward")) {
+ /* The node is a template classforward declaration, and the
+ default template parameters here take precedence. */
+ ParmList *pc = Getattr(cn, "templateparms");
+ ParmList *pn = Getattr(n, "templateparms");
+#ifdef SWIG_DEBUG
+ Printf(stderr, "found template classforward %s\n", Getattr(cn, "name"));
+#endif
+ while (pc && pn) {
+ String *value = Getattr(pc, "value");
+ if (value) {
+#ifdef SWIG_DEBUG
+ Printf(stderr, "add default template value %s %s\n", Getattr(pc, "name"), value);
+#endif
+ Setattr(pn, "value", value);
+ }
+ pc = nextSibling(pc);
+ pn = nextSibling(pn);
+ }
+ Setattr(n, "templateparms", Getattr(cn, "templateparms"));
+ }
+ Setattr(ccurrent, name, n);
+
+ } else if (cn && (Getattr(n, "sym:weak"))) {
+ /* The node being added is weak. Don't worry about it */
+ } else if (cn && (Getattr(n, "sym:typename"))) {
+ /* The node being added is a typename. We definitely add it */
+ Setattr(ccurrent, name, n);
+ append = cn;
+ } else if (cn && (Checkattr(cn, "nodeType", "templateparm"))) {
+ Swig_error(Getfile(n), Getline(n), "Declaration of '%s' shadows template parameter,\n", name);
+ Swig_error(Getfile(cn), Getline(cn), "previous template parameter declaration '%s'.\n", name);
+ return;
+ } else if (cn) {
+ append = n;
+ } else if (!cn) {
+ /* No conflict. Add the symbol */
+ Setattr(ccurrent, name, n);
+ }
+
+ /* Multiple entries in the C symbol table. We append to the symbol table */
+ if (append) {
+ Node *fn, *pn = 0;
+ cn = Getattr(ccurrent, name);
+ fn = cn;
+ while (fn) {
+ pn = fn;
+ if (fn == append) {
+ /* already added. Bail */
+ return;
+ }
+ fn = Getattr(fn, "csym:nextSibling");
+ }
+ if (pn) {
+ Setattr(pn, "csym:nextSibling", append);
+ }
+ }
+
+ /* Special typedef handling. When a typedef node is added to the symbol table, we
+ might have to add a type alias. This would occur if the typedef mapped to another
+ scope in the system. For example:
+
+ class Foo {
+ };
+
+ typedef Foo OtherFoo;
+
+ In this case, OtherFoo becomes an alias for Foo. */
+
+ {
+ Node *td = n;
+ while (td && ((Equal(nodeType(td), "cdecl") && Checkattr(td, "storage", "typedef")) || (Equal(nodeType(td), "using") && !Getattr(n, "namespace")))) {
+ SwigType *type;
+ Node *td1;
+ int using_not_typedef = Equal(nodeType(td), "using");
+ type = Copy(Getattr(td, using_not_typedef ? "uname" : "type"));
+ SwigType_push(type, Getattr(td, "decl"));
+ td1 = Swig_symbol_clookup(type, 0);
+
+ /* Fix pathetic case #1214313:
+
+ class Foo
+ {
+ };
+
+ typedef Foo FooBar;
+
+ class CBaz
+ {
+ public:
+ typedef FooBar Foo;
+ };
+
+ ie, when Foo -> FooBar -> Foo, jump one scope up when possible.
+
+ */
+ if (td1) {
+ String *st = 0;
+ String *sn = Getattr(td, "name");
+ if (Equal(nodeType(td1), "cdecl") && Checkattr(td1, "storage", "typedef"))
+ st = Getattr(td1, "type");
+ else if (Equal(nodeType(td1), "using") && !Getattr(td1, "namespace"))
+ st = Getattr(td1, "uname");
+ if (st && sn && Equal(st, sn)) {
+ Symtab *sc = Getattr(current_symtab, "parentNode");
+ if (sc)
+ td1 = Swig_symbol_clookup(type, sc);
+ }
+ }
+
+ Delete(type);
+ if (td1 == td)
+ break;
+ td = td1;
+ if (td) {
+ Symtab *st = Getattr(td, "symtab");
+ if (st) {
+ Swig_symbol_alias(Getattr(n, "name"), st);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_add()
+ *
+ * Adds a node to the symbol table. Returns the node itself if successfully
+ * added. Otherwise, it returns the symbol table entry of the conflicting node.
+ *
+ * Also places the symbol in a behind-the-scenes C symbol table. This is needed
+ * for namespace support, type resolution, and other issues.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n) {
+ Hash *c, *cl = 0;
+ SwigType *decl, *ndecl;
+ String *cstorage, *nstorage;
+ int nt = 0, ct = 0;
+ int pn = 0;
+ int u1 = 0, u2 = 0;
+ String *name, *overname;
+
+ /* See if the node has a name. If so, we place in the C symbol table for this
+ scope. We don't worry about overloading here---the primary purpose of this
+ is to record information for type/name resolution for later. Conflicts
+ in C namespaces are errors, but these will be caught by the C++ compiler
+ when compiling the wrapper code */
+
+
+ /* There are a few options for weak symbols. A "weak" symbol
+ is any symbol that can be replaced by another symbol in the C symbol
+ table. An example would be a forward class declaration. A forward
+ class sits in the symbol table until a real class declaration comes along.
+
+ Certain symbols are marked as "sym:typename". These are important
+ symbols related to the C++ type-system and take precedence in the C
+ symbol table. An example might be code like this:
+
+ template<class T> T foo(T x);
+ int foo(int);
+
+ In this case, the template is marked with "sym:typename" so that it
+ stays in the C symbol table (so that it can be expanded using %template).
+ */
+
+ name = Getattr(n, "name");
+ if (name && Len(name)) {
+ Swig_symbol_cadd(name, n);
+ }
+
+ /* No symbol name defined. We return. */
+ if (!symname) {
+ Setattr(n, "sym:symtab", current_symtab);
+ return n;
+ }
+
+ /* If node is ignored. We don't proceed any further */
+ if (GetFlag(n, "feature:ignore"))
+ return n;
+
+ /* See if the symbol already exists in the table */
+ c = Getattr(current, symname);
+
+ /* Check for a weak symbol. A weak symbol is allowed to be in the
+ symbol table, but is silently overwritten by other symbols. An example
+ would be a forward class declaration. For instance:
+
+ class Foo;
+
+ In this case, "Foo" sits in the symbol table. However, the
+ definition of Foo would replace the entry if it appeared later. */
+
+ if (c && Getattr(c, "sym:weak")) {
+ c = 0;
+ }
+ if (c) {
+ /* There is a symbol table conflict. There are a few cases to consider here:
+ (1) A conflict between a class/enum and a typedef declaration is okay.
+ In this case, the symbol table entry is set to the class/enum declaration
+ itself, not the typedef.
+ (2) A conflict between namespaces is okay--namespaces are open
+ (3) Otherwise, overloading is only allowed for functions
+ (4) This special case is okay: a class template instantiated with same name as the template's name
+ */
+
+ /* Check for namespaces */
+ String *ntype = Getattr(n, "nodeType");
+ if ((Equal(ntype, Getattr(c, "nodeType"))) && ((Equal(ntype, "namespace")))) {
+ Node *cl, *pcl = 0;
+ cl = c;
+ while (cl) {
+ pcl = cl;
+ cl = Getattr(cl, "sym:nextSibling");
+ }
+ Setattr(pcl, "sym:nextSibling", n);
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ Setattr(n, "sym:previousSibling", pcl);
+ return n;
+ }
+
+ /* Special case: class template instantiated with same name as the template's name eg: %template(X) X<int>; */
+ if (Equal(nodeType(c), "template")) {
+ String *nt1 = Getattr(c, "templatetype");
+ String *nt2 = nodeType(n);
+ if (Equal(nt1, "class") && Equal(nt1, nt2)) {
+ if (Getattr(n, "template")) {
+ /* Finally check that another %template with same name doesn't already exist */
+ if (!Getattr(c, "sym:nextSibling")) {
+ Setattr(c, "sym:nextSibling", n);
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ Setattr(n, "sym:previousSibling", c);
+ return n;
+ }
+ }
+ }
+ }
+
+ if (Getattr(n, "allows_typedef"))
+ nt = 1;
+ if (Getattr(c, "allows_typedef"))
+ ct = 1;
+ if (nt || ct) {
+ Node *td, *other;
+ String *s;
+ /* At least one of the nodes allows typedef overloading. Make sure that
+ both don't--this would be a conflict */
+
+ if (nt && ct)
+ return c;
+
+ /* Figure out which node allows the typedef */
+ if (nt) {
+ td = n;
+ other = c;
+ } else {
+ td = c;
+ other = n;
+ }
+ /* Make sure the other node is a typedef */
+ s = Getattr(other, "storage");
+ if (!s || (!Equal(s, "typedef")))
+ return c; /* No. This is a conflict */
+
+ /* Hmmm. This appears to be okay. Make sure the symbol table refers to the allow_type node */
+
+ if (td != c) {
+ Setattr(current, symname, td);
+ Setattr(td, "sym:symtab", current_symtab);
+ Setattr(td, "sym:name", symname);
+ }
+ return n;
+ }
+
+ decl = Getattr(c, "decl");
+ ndecl = Getattr(n, "decl");
+
+ {
+ String *nt1, *nt2;
+ nt1 = Getattr(n, "nodeType");
+ if (Equal(nt1, "template"))
+ nt1 = Getattr(n, "templatetype");
+ nt2 = Getattr(c, "nodeType");
+ if (Equal(nt2, "template"))
+ nt2 = Getattr(c, "templatetype");
+ if (Equal(nt1, "using"))
+ u1 = 1;
+ if (Equal(nt2, "using"))
+ u2 = 1;
+
+ if ((!Equal(nt1, nt2)) && !(u1 || u2))
+ return c;
+ }
+ if (!(u1 || u2)) {
+ if ((!SwigType_isfunction(decl)) || (!SwigType_isfunction(ndecl))) {
+ /* Symbol table conflict */
+ return c;
+ }
+ }
+
+ /* Hmmm. Declarator seems to indicate that this is a function */
+ /* Look at storage class to see if compatible */
+ cstorage = Getattr(c, "storage");
+ nstorage = Getattr(n, "storage");
+
+ /* If either one is declared as typedef, forget it. We're hosed */
+ if (Cmp(cstorage, "typedef") == 0) {
+ return c;
+ }
+ if (Cmp(nstorage, "typedef") == 0) {
+ return c;
+ }
+
+ /* Okay. Walk down the list of symbols and see if we get a declarator match */
+ {
+ String *nt = Getattr(n, "nodeType");
+ int n_template = Equal(nt, "template") && Checkattr(n, "templatetype", "cdecl");
+ int n_plain_cdecl = Equal(nt, "cdecl");
+ Node *cn = c;
+ pn = 0;
+ while (cn) {
+ decl = Getattr(cn, "decl");
+ if (!(u1 || u2)) {
+ if (Cmp(ndecl, decl) == 0) {
+ /* Declarator conflict */
+ /* Now check we don't have a non-templated function overloaded by a templated function with same params,
+ * eg void foo(); template<typename> void foo(); */
+ String *cnt = Getattr(cn, "nodeType");
+ int cn_template = Equal(cnt, "template") && Checkattr(cn, "templatetype", "cdecl");
+ int cn_plain_cdecl = Equal(cnt, "cdecl");
+ if (!((n_template && cn_plain_cdecl) || (cn_template && n_plain_cdecl))) {
+ /* found a conflict */
+ return cn;
+ }
+ }
+ }
+ cl = cn;
+ cn = Getattr(cn, "sym:nextSibling");
+ pn++;
+ }
+ }
+ /* Well, we made it this far. Guess we can drop the symbol in place */
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ /* Printf(stdout,"%s %p\n", Getattr(n,"sym:overname"), current_symtab); */
+ assert(!Getattr(n, "sym:overname"));
+ overname = NewStringf("__SWIG_%d", pn);
+ Setattr(n, "sym:overname", overname);
+ /*Printf(stdout,"%s %s %s\n", symname, Getattr(n,"decl"), Getattr(n,"sym:overname")); */
+ Setattr(cl, "sym:nextSibling", n);
+ Setattr(n, "sym:previousSibling", cl);
+ Setattr(cl, "sym:overloaded", c);
+ Setattr(n, "sym:overloaded", c);
+ Delete(overname);
+ return n;
+ }
+
+ /* No conflict. Just add it */
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ /* Printf(stdout,"%s\n", Getattr(n,"sym:overname")); */
+ overname = NewStringf("__SWIG_%d", pn);
+ Setattr(n, "sym:overname", overname);
+ Delete(overname);
+ /* Printf(stdout,"%s %s %s\n", symname, Getattr(n,"decl"), Getattr(n,"sym:overname")); */
+ Setattr(current, symname, n);
+ return n;
+}
+
+/* -----------------------------------------------------------------------------
+ * symbol_lookup()
+ *
+ * Internal function to handle fully qualified symbol table lookups. This
+ * works from the symbol table supplied in symtab and unwinds its way out
+ * towards the global scope.
+ *
+ * This function operates in the C namespace, not the target namespace.
+ *
+ * The check function is an optional callback that can be used to verify a particular
+ * symbol match. This is only used in some of the more exotic parts of SWIG. For instance,
+ * verifying that a class hierarchy implements all pure virtual methods.
+ * ----------------------------------------------------------------------------- */
+
+static Node *_symbol_lookup(const String *name, Symtab *symtab, int (*check) (Node *n)) {
+ Node *n;
+ List *inherit;
+ Hash *sym = Getattr(symtab, "csymtab");
+ if (Getmark(symtab))
+ return 0;
+ Setmark(symtab, 1);
+
+ n = Getattr(sym, name);
+
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_look %s %p %p %s\n", name, n, symtab, Getattr(symtab, "name"));
+#endif
+
+ if (n) {
+ /* if a check-function is defined. Call it to determine a match */
+ if (check) {
+ int c = check(n);
+ if (c == 1) {
+ Setmark(symtab, 0);
+ return n;
+ }
+ if (c < 0) {
+ /* Terminate the search right away */
+ Setmark(symtab, 0);
+ return 0;
+ }
+ } else {
+ Setmark(symtab, 0);
+ return n;
+ }
+ }
+
+ if (!n && SwigType_istemplate(name)) {
+ String *dname = 0;
+ Setmark(symtab, 0);
+ dname = Swig_symbol_template_deftype(name, symtab);
+ if (!Equal(dname, name)) {
+ n = _symbol_lookup(dname, symtab, check);
+ }
+ Delete(dname);
+ if (n)
+ return n;
+ Setmark(symtab, 1);
+ }
+
+ inherit = Getattr(symtab, "inherit");
+ if (inherit && use_inherit) {
+ int i, len;
+ len = Len(inherit);
+ for (i = 0; i < len; i++) {
+ n = _symbol_lookup(name, Getitem(inherit, i), check);
+ if (n) {
+ Setmark(symtab, 0);
+ return n;
+ }
+ }
+ }
+
+ Setmark(symtab, 0);
+ return 0;
+}
+
+static Node *symbol_lookup(const_String_or_char_ptr name, Symtab *symtab, int (*check) (Node *n)) {
+ Node *n = 0;
+ if (DohCheck(name)) {
+ n = _symbol_lookup(name, symtab, check);
+ } else {
+ String *sname = NewString(name);
+ n = _symbol_lookup(sname, symtab, check);
+ Delete(sname);
+ }
+ return n;
+}
+
+
+
+/* -----------------------------------------------------------------------------
+ * symbol_lookup_qualified()
+ * ----------------------------------------------------------------------------- */
+
+static Node *symbol_lookup_qualified(const_String_or_char_ptr name, Symtab *symtab, const String *prefix, int local, int (*checkfunc) (Node *n)) {
+ /* This is a little funky, we search by fully qualified names */
+
+ if (!symtab)
+ return 0;
+ if (!prefix) {
+ Node *n;
+ String *bname = 0;
+ String *prefix = 0;
+ Swig_scopename_split(name, &prefix, &bname);
+ n = symbol_lookup_qualified(bname, symtab, prefix, local, checkfunc);
+ Delete(bname);
+ Delete(prefix);
+ return n;
+ } else {
+ Symtab *st;
+ Node *n = 0;
+ /* Make qualified name of current scope */
+ String *qalloc = 0;
+ String *qname = Swig_symbol_qualifiedscopename(symtab);
+ const String *cqname;
+ if (qname) {
+ if (Len(qname)) {
+ if (prefix && Len(prefix)) {
+ Printv(qname, "::", prefix, NIL);
+ }
+ } else {
+ Append(qname, prefix);
+ }
+ qalloc = qname;
+ cqname = qname;
+ } else {
+ cqname = prefix;
+ }
+ st = Getattr(symtabs, cqname);
+ /* Found a scope match */
+ if (st) {
+ if (!name) {
+ if (qalloc)
+ Delete(qalloc);
+ return st;
+ }
+ n = symbol_lookup(name, st, checkfunc);
+ }
+ if (qalloc)
+ Delete(qalloc);
+
+ if (!n) {
+ if (!local) {
+ Node *pn = Getattr(symtab, "parentNode");
+ if (pn)
+ n = symbol_lookup_qualified(name, pn, prefix, local, checkfunc);
+
+ /* Check inherited scopes */
+ if (!n) {
+ List *inherit = Getattr(symtab, "inherit");
+ if (inherit && use_inherit) {
+ int i, len;
+ len = Len(inherit);
+ for (i = 0; i < len; i++) {
+ Node *prefix_node = symbol_lookup(prefix, Getitem(inherit, i), checkfunc);
+ if (prefix_node) {
+ Node *prefix_symtab = Getattr(prefix_node, "symtab");
+ if (prefix_symtab) {
+ n = symbol_lookup(name, prefix_symtab, checkfunc);
+ break;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ n = 0;
+ }
+ }
+ return n;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup()
+ *
+ * Look up a symbol in the symbol table. This uses the C name, not scripting
+ * names. Note: If we come across a using declaration, we follow it to
+ * to get the real node. Any using directives are also followed (but this is
+ * implemented in symbol_lookup()).
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup(const_String_or_char_ptr name, Symtab *n) {
+ Hash *hsym = 0;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ if (n) {
+ hsym = n;
+ }
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, 0);
+ } else {
+ s = symbol_lookup(nname, global_scope, 0);
+ }
+ Delete(nname);
+ } else {
+ String *prefix = Swig_scopename_prefix(name);
+ if (prefix) {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, 0);
+ Delete(prefix);
+ if (!s) {
+ return 0;
+ }
+ }
+ }
+ }
+ if (!s) {
+ while (hsym) {
+ s = symbol_lookup(name, hsym, 0);
+ if (s)
+ break;
+ hsym = Getattr(hsym, "parentNode");
+ if (!hsym)
+ break;
+ }
+ }
+
+ if (!s) {
+ return 0;
+ }
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ String *uname = Getattr(s, "uname");
+ Symtab *un = Getattr(s, "sym:symtab");
+ Node *ss = (!Equal(name, uname) || (un != n)) ? Swig_symbol_clookup(uname, un) : 0; /* avoid infinity loop */
+ if (!ss) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(s, "uname")));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_check()
+ *
+ * This function is identical to Swig_symbol_clookup() except that it
+ * accepts a callback function that is invoked to determine a symbol match.
+ * The purpose of this function is to support complicated algorithms that need
+ * to examine multiple definitions of the same symbol that might appear in an
+ * inheritance hierarchy.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_check(const_String_or_char_ptr name, Symtab *n, int (*checkfunc) (Node *n)) {
+ Hash *hsym = 0;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ if (n) {
+ hsym = n;
+ }
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, checkfunc);
+ } else {
+ s = symbol_lookup(nname, global_scope, checkfunc);
+ }
+ Delete(nname);
+ } else {
+ String *prefix = Swig_scopename_prefix(name);
+ if (prefix) {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, checkfunc);
+ Delete(prefix);
+ if (!s) {
+ return 0;
+ }
+ }
+ }
+ }
+ if (!s) {
+ while (hsym) {
+ s = symbol_lookup(name, hsym, checkfunc);
+ if (s)
+ break;
+ hsym = Getattr(hsym, "parentNode");
+ if (!hsym)
+ break;
+ }
+ }
+ if (!s) {
+ return 0;
+ }
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ Node *ss;
+ ss = Swig_symbol_clookup(Getattr(s, "uname"), Getattr(s, "sym:symtab"));
+ if (!ss && !checkfunc) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(s, "uname")));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_local()
+ *
+ * Same as Swig_symbol_clookup but parent nodes are not searched, that is, just
+ * this symbol table is searched.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_local(const_String_or_char_ptr name, Symtab *n) {
+ Hash *hsym;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ hsym = n;
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, 0);
+ } else {
+ s = symbol_lookup(nname, global_scope, 0);
+ }
+ Delete(nname);
+ } else {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, 0);
+ }
+ }
+ if (!s) {
+ s = symbol_lookup(name, hsym, 0);
+ }
+ if (!s)
+ return 0;
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ Node *ss = Swig_symbol_clookup_local(Getattr(s, "uname"), Getattr(s, "sym:symtab"));
+ if (!ss) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(s, "uname")));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_local_check()
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr name, Symtab *n, int (*checkfunc) (Node *)) {
+ Hash *hsym;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ hsym = n;
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, checkfunc);
+ } else {
+ s = symbol_lookup(nname, global_scope, checkfunc);
+ }
+ Delete(nname);
+ } else {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, checkfunc);
+ }
+ }
+ if (!s) {
+ s = symbol_lookup(name, hsym, checkfunc);
+ }
+ if (!s)
+ return 0;
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ Node *ss = Swig_symbol_clookup_local_check(Getattr(s, "uname"), Getattr(s, "sym:symtab"), checkfunc);
+ if (!ss && !checkfunc) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(s, "uname")));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_no_inherit()
+ *
+ * Symbol lookup like Swig_symbol_clookup but does not follow using declarations.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_no_inherit(const_String_or_char_ptr name, Symtab *n) {
+ Node *s = 0;
+ assert(use_inherit==1);
+ use_inherit = 0;
+ s = Swig_symbol_clookup(name, n);
+ use_inherit = 1;
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_cscope()
+ *
+ * Look up a scope name.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_cscope(const_String_or_char_ptr name, Symtab *symtab) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0)
+ return symbol_lookup_qualified(0, global_scope, name, 0, 0);
+ return symbol_lookup_qualified(0, symtab, name, 0, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_remove()
+ *
+ * Remove a symbol. If the symbol is an overloaded function and the symbol removed
+ * is not the last in the list of overloaded functions, then the overloaded
+ * names (sym:overname attribute) are changed to start from zero, eg __SWIG_0.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_remove(Node *n) {
+ Symtab *symtab;
+ String *symname;
+ String *overname;
+ Node *symprev;
+ Node *symnext;
+ Node *fixovername = 0;
+ symtab = Getattr(n, "sym:symtab"); /* Get symbol table object */
+ symtab = Getattr(symtab, "symtab"); /* Get actual hash table of symbols */
+ symname = Getattr(n, "sym:name");
+ symprev = Getattr(n, "sym:previousSibling");
+ symnext = Getattr(n, "sym:nextSibling");
+
+ /* If previous symbol, just fix the links */
+ if (symprev) {
+ if (symnext) {
+ Setattr(symprev, "sym:nextSibling", symnext);
+ fixovername = symprev; /* fix as symbol to remove is somewhere in the middle of the linked list */
+ } else {
+ Delattr(symprev, "sym:nextSibling");
+ }
+ } else {
+ /* If no previous symbol, see if there is a next symbol */
+ if (symnext) {
+ Setattr(symtab, symname, symnext);
+ fixovername = symnext; /* fix as symbol to remove is at head of linked list */
+ } else {
+ if (symname)
+ Delattr(symtab, symname);
+ }
+ }
+ if (symnext) {
+ if (symprev) {
+ Setattr(symnext, "sym:previousSibling", symprev);
+ } else {
+ Delattr(symnext, "sym:previousSibling");
+ }
+ }
+ Delattr(n, "sym:symtab");
+ Delattr(n, "sym:previousSibling");
+ Delattr(n, "sym:nextSibling");
+ Delattr(n, "csym:nextSibling");
+ Delattr(n, "sym:overname");
+ Delattr(n, "csym:previousSibling");
+ Delattr(n, "sym:overloaded");
+ n = 0;
+
+ if (fixovername) {
+ Node *nn = fixovername;
+ Node *head = fixovername;
+ int pn = 0;
+
+ /* find head of linked list */
+ while (nn) {
+ head = nn;
+ nn = Getattr(nn, "sym:previousSibling");
+ }
+
+ /* adjust all the sym:overname strings to start from 0 and increment by one */
+ nn = head;
+ while (nn) {
+ assert(Getattr(nn, "sym:overname"));
+ Delattr(nn, "sym:overname");
+ overname = NewStringf("__SWIG_%d", pn);
+ Setattr(nn, "sym:overname", overname);
+ Delete(overname);
+ pn++;
+ nn = Getattr(nn, "sym:nextSibling");
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_qualified()
+ *
+ * Return the qualified name of a symbol
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_qualified(Node *n) {
+ Hash *symtab;
+ if (Checkattr(n, "nodeType", "symboltable")) {
+ symtab = n;
+ } else {
+ symtab = Getattr(n, "sym:symtab");
+ }
+ if (!symtab)
+ return NewStringEmpty();
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qscope %s %p %s\n", Getattr(n, "name"), symtab, Getattr(symtab, "name"));
+#endif
+ return Swig_symbol_qualifiedscopename(symtab);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_isoverloaded()
+ *
+ * Check if a symbol is overloaded. Returns the first symbol if so.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_isoverloaded(Node *n) {
+ return Getattr(n, "sym:overloaded");
+}
+
+/* -----------------------------------------------------------------------------
+ * symbol_template_qualify()
+ *
+ * Internal function to create a fully qualified type name for templates
+ * ----------------------------------------------------------------------------- */
+
+/* This cache produces problems with OSS, don't active it */
+/* #define SWIG_TEMPLATE_QUALIFY_CACHE */
+static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) {
+ String *tprefix, *tsuffix;
+ SwigType *qprefix;
+ String *targs;
+ List *targslist;
+ Node *tempn;
+ Symtab *tscope;
+ Iterator ti;
+#ifdef SWIG_TEMPLATE_QUALIFY_CACHE
+ static Hash *qualify_cache = 0;
+ String *scopetype = st ? NewStringf("%s::%s", Getattr(st, "name"), e)
+ : NewStringf("%s::%s", Swig_symbol_getscopename(), e);
+ if (!qualify_cache) {
+ qualify_cache = NewHash();
+ }
+ if (scopetype) {
+ String *cres = Getattr(qualify_cache, scopetype);
+ if (cres) {
+ Delete(scopetype);
+ return Copy(cres);
+ }
+ }
+#endif
+
+ tprefix = SwigType_templateprefix(e);
+ tsuffix = SwigType_templatesuffix(e);
+ qprefix = Swig_symbol_type_qualify(tprefix, st);
+ targs = SwigType_templateargs(e);
+ targslist = SwigType_parmlist(targs);
+ tempn = Swig_symbol_clookup_local(tprefix, st);
+ tscope = tempn ? Getattr(tempn, "sym:symtab") : 0;
+ Append(qprefix, "<(");
+ for (ti = First(targslist); ti.item;) {
+ String *vparm;
+ /* TODO: the logic here should be synchronised with that in SwigType_typedef_qualified() */
+ /* TODO: ti.item might be a non-type parameter possibly within (), eg: (std::is_integral_v<(A)>||std::is_same_v<(A,node_t)>) */
+ String *qparm = Swig_symbol_type_qualify(ti.item, st);
+ if (tscope && (tscope != st)) {
+ String *ty = Swig_symbol_type_qualify(qparm, tscope);
+ Delete(qparm);
+ qparm = ty;
+ }
+
+ vparm = Swig_symbol_template_param_eval(qparm, st);
+ Append(qprefix, vparm);
+ ti = Next(ti);
+ if (ti.item) {
+ Putc(',', qprefix);
+ }
+ Delete(qparm);
+ Delete(vparm);
+ }
+ Append(qprefix, ")>");
+ Append(qprefix, tsuffix);
+ Delete(tprefix);
+ Delete(tsuffix);
+ Delete(targs);
+ Delete(targslist);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_temp_qual %s %s\n", e, qprefix);
+#endif
+#ifdef SWIG_TEMPLATE_QUALIFY_CACHE
+ Setattr(qualify_cache, scopetype, qprefix);
+ Delete(scopetype);
+#endif
+
+ return qprefix;
+}
+
+
+static int symbol_no_constructor(Node *n) {
+ return !Checkattr(n, "nodeType", "constructor");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_type_qualify()
+ *
+ * Create a fully qualified type name
+ * Note: Does not resolve a constructor if passed in as the 'type'.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *Swig_symbol_type_qualify(const SwigType *t, Symtab *st) {
+ List *elements;
+ String *result = NewStringEmpty();
+ int i, len;
+ char *c = Char(t);
+ if (strncmp(c, "::", 2) == 0) {
+ Append(result, t);
+ return result;
+ }
+
+ elements = SwigType_split(t);
+
+ len = Len(elements);
+ for (i = 0; i < len; i++) {
+ String *e = Getitem(elements, i);
+ if (SwigType_issimple(e)) {
+ /* Note: the unary scope operator (::) is being removed from the template parameters here. */
+ Node *n = Swig_symbol_clookup_check(e, st, symbol_no_constructor);
+ if (n) {
+ String *name = Getattr(n, "name");
+ Clear(e);
+ Append(e, name);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qual_ei %d %s %s %p\n", i, name, e, st);
+#endif
+ if (!Swig_scopename_check(name)) {
+ String *qname = Swig_symbol_qualified(n);
+ if (qname && Len(qname)) {
+ Insert(e, 0, "::");
+ Insert(e, 0, qname);
+ }
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qual_sc %d %s %s %p\n", i, qname, e, st);
+#endif
+ Delete(qname);
+ }
+ } else if (SwigType_istemplate(e)) {
+ SwigType *ty = symbol_template_qualify(e, st);
+ Clear(e);
+ Append(e, ty);
+ Delete(ty);
+ }
+ if (strncmp(Char(e), "::", 2) == 0) {
+ Delitem(e, 0);
+ Delitem(e, 0);
+ }
+ Append(result, e);
+ } else if (SwigType_isfunction(e)) {
+ List *parms = SwigType_parmlist(e);
+ String *s = NewString("f(");
+ Iterator pi = First(parms);
+ while (pi.item) {
+ String *pf = Swig_symbol_type_qualify(pi.item, st);
+ Append(s, pf);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(s, ",");
+ }
+ Delete(pf);
+ }
+ Append(s, ").");
+ Append(result, s);
+ Delete(parms);
+ Delete(s);
+ } else {
+ Append(result, e);
+ }
+ }
+ Delete(elements);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qualify %s %s %p %s\n", t, result, st, st ? Getattr(st, "name") : 0);
+#endif
+
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_template_reduce()
+ * Resolves template parameter types
+ * For example:
+ * typedef int Int;
+ * typedef Int Integer;
+ * with input:
+ * Foo<(Int,Integer)>
+ * returns:
+ * Foo<(int,int)>
+ * ----------------------------------------------------------------------------- */
+
+static
+SwigType *Swig_symbol_template_reduce(SwigType *qt, Symtab *ntab) {
+ Parm *p;
+ String *templateargs = SwigType_templateargs(qt);
+ List *parms = SwigType_parmlist(templateargs);
+ Iterator pi = First(parms);
+ String *tprefix = SwigType_templateprefix(qt);
+ String *tsuffix = SwigType_templatesuffix(qt);
+ String *qprefix = SwigType_typedef_qualified(tprefix);
+ Append(qprefix, "<(");
+ while ((p = pi.item)) {
+ String *np;
+ String *tp = Swig_symbol_typedef_reduce(p, ntab);
+ String *qp = Swig_symbol_type_qualify(tp, ntab);
+ Node *n = Swig_symbol_clookup(qp, ntab);
+ if (n) {
+ String *qual = Swig_symbol_qualified(n);
+ np = Copy(Getattr(n, "name"));
+ Delete(tp);
+ tp = np;
+ if (qual && Len(qual)) {
+ Insert(np, 0, "::");
+ Insert(np, 0, qual);
+ }
+ Delete(qual);
+ } else {
+ np = qp;
+ }
+ Append(qprefix, np);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(qprefix, ",");
+ }
+ Delete(qp);
+ Delete(tp);
+ }
+ Append(qprefix, ")>");
+ Append(qprefix, tsuffix);
+ Delete(parms);
+ Delete(tprefix);
+ Delete(tsuffix);
+ Delete(templateargs);
+ return qprefix;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_typedef_reduce()
+ *
+ * Chase a typedef through symbol tables looking for a match.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *Swig_symbol_typedef_reduce(const SwigType *ty, Symtab *tab) {
+ SwigType *prefix, *base;
+ Node *n;
+ String *nt;
+
+ base = SwigType_base(ty);
+ prefix = SwigType_prefix(ty);
+
+ n = Swig_symbol_clookup(base, tab);
+ if (!n) {
+ if (SwigType_istemplate(ty)) {
+ SwigType *qt = Swig_symbol_template_reduce(base, tab);
+ Append(prefix, qt);
+ Delete(qt);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (a) %s %s\n", ty, prefix);
+#endif
+ Delete(base);
+ return prefix;
+ } else {
+ Delete(prefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (b) %s %s\n", ty, ty);
+#endif
+ return Copy(ty);
+ }
+ }
+ nt = Getattr(n, "nodeType");
+ if (Equal(nt, "using")) {
+ String *uname = Getattr(n, "uname");
+ if (uname) {
+ n = Swig_symbol_clookup(base, Getattr(n, "sym:symtab"));
+ if (!n) {
+ Delete(base);
+ Delete(prefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (c) %s %s\n", ty, ty);
+#endif
+ return Copy(ty);
+ }
+ }
+ }
+ if (Equal(nt, "cdecl")) {
+ String *storage = Getattr(n, "storage");
+ if (storage && (Equal(storage, "typedef"))) {
+ SwigType *decl;
+ SwigType *rt;
+ SwigType *qt;
+ Symtab *ntab;
+ SwigType *nt = Copy(Getattr(n, "type"));
+
+ /* Fix for case 'typedef struct Hello hello;' */
+ {
+ const char *dclass[3] = { "struct ", "union ", "class " };
+ int i;
+ char *c = Char(nt);
+ for (i = 0; i < 3; i++) {
+ if (strstr(c, dclass[i]) == c) {
+ Replace(nt, dclass[i], "", DOH_REPLACE_FIRST);
+ }
+ }
+ }
+ decl = Getattr(n, "decl");
+ if (decl) {
+ SwigType_push(nt, decl);
+ }
+ SwigType_push(nt, prefix);
+ Delete(base);
+ Delete(prefix);
+ ntab = Getattr(n, "sym:symtab");
+ rt = Swig_symbol_typedef_reduce(nt, ntab);
+ qt = Swig_symbol_type_qualify(rt, ntab);
+ if (SwigType_istemplate(qt)) {
+ SwigType *qtr = Swig_symbol_template_reduce(qt, ntab);
+ Delete(qt);
+ qt = qtr;
+ }
+ Delete(nt);
+ Delete(rt);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (d) %s %s\n", qt, ty);
+#endif
+ return qt;
+ }
+ }
+ Delete(base);
+ Delete(prefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (e) %s %s\n", ty, ty);
+#endif
+ return Copy(ty);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_string_qualify()
+ *
+ * This function takes a string and looks for identifiers. Identifiers are
+ * then qualified according to scope rules. This function is used in a number
+ * of settings including expression evaluation, scoping of conversion operators,
+ * and so forth.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_string_qualify(String *s, Symtab *st) {
+ int have_id = 0;
+ String *id = NewStringEmpty();
+ String *r = NewStringEmpty();
+ char *c = Char(s);
+ int first_char = 1;
+ while (*c) {
+ if (isalpha((int) *c) || (*c == '_') || (*c == ':') || (*c == '~' && first_char) || (isdigit((int) *c) && !first_char)) {
+ Putc(*c, id);
+ have_id = 1;
+ } else {
+ if (have_id) {
+ String *qid = Swig_symbol_type_qualify(id, st);
+ Append(r, qid);
+ Clear(id);
+ Delete(qid);
+ have_id = 0;
+ }
+ Putc(*c, r);
+ }
+ first_char = (*c == ':');
+ c++;
+ }
+ if (have_id) {
+ String *qid = Swig_symbol_type_qualify(id, st);
+ Append(r, qid);
+ Delete(qid);
+ }
+ Delete(id);
+ return r;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_template_defargs()
+ *
+ * Apply default arg from generic template default args
+ * Returns a parameter list which contains missing default arguments (if any)
+ * Note side effects: parms will also contain the extra parameters in its list
+ * (but only if non-zero).
+ * ----------------------------------------------------------------------------- */
+
+
+ParmList *Swig_symbol_template_defargs(Parm *parms, Parm *targs, Symtab *tscope, Symtab *tsdecl) {
+ ParmList *expandedparms = parms;
+ if (Len(parms) < Len(targs)) {
+ Parm *lp = parms;
+ Parm *p = lp;
+ Parm *tp = targs;
+ while (p && tp) {
+ p = nextSibling(p);
+ tp = nextSibling(tp);
+ if (p)
+ lp = p;
+ }
+ while (tp) {
+ String *value = Getattr(tp, "value");
+ if (value) {
+ Parm *cp;
+ Parm *ta = targs;
+ Parm *p = parms;
+ SwigType *nt = Swig_symbol_string_qualify(value, tsdecl);
+ SwigType *ntq = 0;
+#ifdef SWIG_DEBUG
+ Printf(stderr, "value %s %s %s\n", value, nt, tsdecl ? Getattr(tsdecl, "name") : tsdecl);
+#endif
+ while (p && ta) {
+ String *name = Getattr(ta, "name");
+ String *pvalue = Getattr(p, "value");
+ String *value = pvalue ? pvalue : Getattr(p, "type");
+ String *ttq = Swig_symbol_type_qualify(value, tscope);
+ /* value = SwigType_typedef_resolve_all(value); */
+ Replaceid(nt, name, ttq);
+ p = nextSibling(p);
+ ta = nextSibling(ta);
+ Delete(ttq);
+ }
+ ntq = Swig_symbol_type_qualify(nt, tsdecl);
+ if (SwigType_istemplate(ntq)) {
+ String *ty = Swig_symbol_template_deftype(ntq, tscope);
+ Delete(ntq);
+ ntq = ty;
+ }
+ cp = NewParmWithoutFileLineInfo(ntq, 0);
+ if (lp) {
+ set_nextSibling(lp, cp);
+ Delete(cp);
+ } else {
+ expandedparms = cp;
+ }
+ lp = cp;
+ tp = nextSibling(tp);
+ Delete(nt);
+ Delete(ntq);
+ } else {
+ tp = 0;
+ }
+ }
+ }
+ return expandedparms;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_template_deftype()
+ *
+ * Apply default args to generic template type
+ * ----------------------------------------------------------------------------- */
+
+#define SWIG_TEMPLATE_DEFTYPE_CACHE
+SwigType *Swig_symbol_template_deftype(const SwigType *type, Symtab *tscope) {
+ String *result = NewStringEmpty();
+ List *elements = SwigType_split(type);
+ int len = Len(elements);
+ int i;
+#ifdef SWIG_TEMPLATE_DEFTYPE_CACHE
+ static Hash *s_cache = 0;
+ Hash *scope_cache;
+ /* The lookup depends on the current scope and potential namespace qualification.
+ Looking up x in namespace y is not the same as looking up x::y in outer scope.
+ -> we use a 2-level hash: first scope and then symbol. */
+ String *scope_name = tscope
+ ? Swig_symbol_qualifiedscopename(tscope)
+ : Swig_symbol_qualifiedscopename(current_symtab);
+ String *type_name = tscope
+ ? NewStringf("%s::%s", Getattr(tscope, "name"), type)
+ : NewStringf("%s::%s", Swig_symbol_getscopename(), type);
+ if (!scope_name) scope_name = NewString("::");
+ if (!s_cache) {
+ s_cache = NewHash();
+ }
+ scope_cache = Getattr(s_cache, scope_name);
+ if (scope_cache) {
+ String *cres = Getattr(scope_cache, type_name);
+ if (cres) {
+ Append(result, cres);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "cached deftype %s(%s) -> %s\n", type, scope_name, result);
+#endif
+ Delete(type_name);
+ Delete(scope_name);
+ return result;
+ }
+ } else {
+ scope_cache = NewHash();
+ Setattr(s_cache, scope_name, scope_cache);
+ Delete(scope_name);
+ }
+#endif
+
+#ifdef SWIG_DEBUG
+ Printf(stderr, "finding deftype %s\n", type);
+#endif
+
+ for (i = 0; i < len; i++) {
+ String *e = Getitem(elements, i);
+ if (SwigType_isfunction(e)) {
+ String *s = NewString("f(");
+ List *parms = SwigType_parmlist(e);
+ Iterator pi = First(parms);
+ while (pi.item) {
+ String *pf = SwigType_istemplate(e) ? Swig_symbol_template_deftype(pi.item, tscope)
+ : Swig_symbol_type_qualify(pi.item, tscope);
+ Append(s, pf);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(s, ",");
+ }
+ Delete(pf);
+ }
+ Append(s, ").");
+ Append(result, s);
+ Delete(s);
+ Delete(parms);
+ } else if (SwigType_istemplate(e)) {
+ String *prefix = SwigType_prefix(e);
+ String *base = SwigType_base(e);
+ String *tprefix = SwigType_templateprefix(base);
+ String *targs = SwigType_templateargs(base);
+ String *tsuffix = SwigType_templatesuffix(base);
+ ParmList *tparms = SwigType_function_parms(targs, 0);
+ Node *tempn = Swig_symbol_clookup_local(tprefix, tscope);
+ if (!tempn && tsuffix && Len(tsuffix)) {
+ tempn = Swig_symbol_clookup(tprefix, 0);
+ }
+#ifdef SWIG_DEBUG
+ Printf(stderr, "deftype type %s %s %d\n", e, tprefix, (long) tempn);
+#endif
+ if (tempn) {
+ ParmList *tnargs = Getattr(tempn, "templateparms");
+ ParmList *expandedparms;
+ Parm *p;
+ Symtab *tsdecl = Getattr(tempn, "sym:symtab");
+
+#ifdef SWIG_DEBUG
+ Printf(stderr, "deftype type %s %s %s\n", tprefix, targs, tsuffix);
+#endif
+ Append(tprefix, "<(");
+ expandedparms = Swig_symbol_template_defargs(tparms, tnargs, tscope, tsdecl);
+ p = expandedparms;
+ tscope = tsdecl;
+ while (p) {
+ SwigType *ptype = Getattr(p, "type");
+ SwigType *ttr = ptype ? ptype : Getattr(p, "value");
+ SwigType *ttf = Swig_symbol_type_qualify(ttr, tscope);
+ SwigType *ttq = Swig_symbol_template_param_eval(ttf, tscope);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "arg type %s\n", ttq);
+#endif
+ if (SwigType_istemplate(ttq)) {
+ SwigType *ttd = Swig_symbol_template_deftype(ttq, tscope);
+ Delete(ttq);
+ ttq = ttd;
+#ifdef SWIG_DEBUG
+ Printf(stderr, "arg deftype %s\n", ttq);
+#endif
+ }
+ Append(tprefix, ttq);
+ p = nextSibling(p);
+ if (p)
+ Putc(',', tprefix);
+ Delete(ttf);
+ Delete(ttq);
+ }
+ Append(tprefix, ")>");
+ Append(tprefix, tsuffix);
+ Append(prefix, tprefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "deftype %s %s \n", type, tprefix);
+#endif
+ Append(result, prefix);
+ } else {
+ Append(result, e);
+ }
+ Delete(prefix);
+ Delete(base);
+ Delete(tprefix);
+ Delete(tsuffix);
+ Delete(targs);
+ Delete(tparms);
+ } else {
+ Append(result, e);
+ }
+ }
+ Delete(elements);
+#ifdef SWIG_TEMPLATE_DEFTYPE_CACHE
+ Setattr(scope_cache, type_name, result);
+ Delete(type_name);
+#endif
+
+ return result;
+}
+
+SwigType *Swig_symbol_template_param_eval(const SwigType *p, Symtab *symtab) {
+ String *value = Copy(p);
+ Node *lastnode = 0;
+ while (1) {
+ Node *n = Swig_symbol_clookup(value, symtab);
+ if (n == lastnode)
+ break;
+ lastnode = n;
+ if (n) {
+ String *nt = Getattr(n, "nodeType");
+ if (Equal(nt, "enumitem")) {
+ /* An enum item. Generate a fully qualified name */
+ String *qn = Swig_symbol_qualified(n);
+ if (qn && Len(qn)) {
+ Append(qn, "::");
+ Append(qn, Getattr(n, "name"));
+ Delete(value);
+ value = qn;
+ continue;
+ } else {
+ Delete(qn);
+ break;
+ }
+ } else if ((Equal(nt, "cdecl"))) {
+ String *nv = Getattr(n, "value");
+ if (nv) {
+ Delete(value);
+ value = Copy(nv);
+ continue;
+ }
+ }
+ }
+ break;
+ }
+ return value;
+}
diff --git a/contrib/tools/swig/Source/Swig/tree.c b/contrib/tools/swig/Source/Swig/tree.c
new file mode 100644
index 0000000000..438e8b73dc
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/tree.c
@@ -0,0 +1,426 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * tree.c
+ *
+ * This file provides some general purpose functions for manipulating
+ * parse trees.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <stdarg.h>
+#include <assert.h>
+
+static int debug_quiet = 0;
+
+/* -----------------------------------------------------------------------------
+ * Swig_print_quiet()
+ *
+ * Set quiet mode when printing a parse tree node
+ * ----------------------------------------------------------------------------- */
+
+int Swig_print_quiet(int quiet) {
+ int previous_quiet = debug_quiet;
+ debug_quiet = quiet;
+ return previous_quiet;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_print_tags()
+ *
+ * Dump the tag structure of a parse tree to standard output
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print_tags(DOH *obj, DOH *root) {
+ DOH *croot, *newroot;
+ DOH *cobj;
+
+ if (!root)
+ croot = NewStringEmpty();
+ else
+ croot = root;
+
+ while (obj) {
+ Swig_diagnostic(Getfile(obj), Getline(obj), "%s . %s\n", croot, nodeType(obj));
+ cobj = firstChild(obj);
+ if (cobj) {
+ newroot = NewStringf("%s . %s", croot, nodeType(obj));
+ Swig_print_tags(cobj, newroot);
+ Delete(newroot);
+ }
+ obj = nextSibling(obj);
+ }
+ if (!root)
+ Delete(croot);
+}
+
+static int indent_level = 0;
+
+static void print_indent(int l) {
+ int i;
+ for (i = 0; i < indent_level; i++) {
+ fputc(' ', stdout);
+ }
+ if (l) {
+ fputc('|', stdout);
+ fputc(' ', stdout);
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_print_node(Node *n)
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print_node(Node *obj) {
+ Iterator ki;
+ Node *cobj;
+ List *keys = Keys(obj);
+
+ print_indent(0);
+ if (debug_quiet)
+ Printf(stdout, "+++ %s ----------------------------------------\n", nodeType(obj));
+ else
+ Printf(stdout, "+++ %s - %p ----------------------------------------\n", nodeType(obj), obj);
+
+ SortList(keys, 0);
+ ki = First(keys);
+ while (ki.item) {
+ String *k = ki.item;
+ DOH *value = Getattr(obj, k);
+ if (Equal(k, "nodeType") || (*(Char(k)) == '$')) {
+ /* Do nothing */
+ } else if (debug_quiet && (Equal(k, "firstChild") || Equal(k, "lastChild") || Equal(k, "parentNode") || Equal(k, "nextSibling") ||
+ Equal(k, "previousSibling") || Equal(k, "symtab") || Equal(k, "csymtab") || Equal(k, "sym:symtab") || Equal(k, "sym:nextSibling") ||
+ Equal(k, "sym:previousSibling") || Equal(k, "csym:nextSibling") || Equal(k, "csym:previousSibling"))) {
+ /* Do nothing */
+ } else if (Equal(k, "kwargs") || Equal(k, "parms") || Equal(k, "wrap:parms") || Equal(k, "pattern") || Equal(k, "templateparms") || Equal(k, "throws")) {
+ print_indent(2);
+ /* Differentiate parameter lists by displaying within single quotes */
+ Printf(stdout, "%-12s - \'%s\'\n", k, ParmList_str_defaultargs(value));
+ } else {
+ DOH *o;
+ const char *trunc = "";
+ print_indent(2);
+ if (DohIsString(value)) {
+ o = Str(value);
+ if (Len(o) > 80) {
+ trunc = "...";
+ }
+ Printf(stdout, "%-12s - \"%(escape)-0.80s%s\"\n", k, o, trunc);
+ Delete(o);
+ } else {
+ Printf(stdout, "%-12s - %p\n", k, value);
+ }
+ }
+ ki = Next(ki);
+ }
+ cobj = firstChild(obj);
+ if (cobj) {
+ indent_level += 6;
+ Printf(stdout, "\n");
+ Swig_print_tree(cobj);
+ indent_level -= 6;
+ } else {
+ print_indent(1);
+ Printf(stdout, "\n");
+ }
+ Delete(keys);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_print_tree()
+ *
+ * Dump the tree structure of a parse tree to standard output
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print_tree(DOH *obj) {
+ while (obj) {
+ Swig_print_node(obj);
+ obj = nextSibling(obj);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * appendChild()
+ *
+ * Appends a new child to a node
+ * ----------------------------------------------------------------------------- */
+
+void appendChild(Node *node, Node *chd) {
+ Node *lc;
+
+ if (!chd)
+ return;
+
+ lc = lastChild(node);
+ if (!lc) {
+ set_firstChild(node, chd);
+ } else {
+ set_nextSibling(lc, chd);
+ set_previousSibling(chd, lc);
+ }
+ while (chd) {
+ lc = chd;
+ set_parentNode(chd, node);
+ chd = nextSibling(chd);
+ }
+ set_lastChild(node, lc);
+}
+
+/* -----------------------------------------------------------------------------
+ * prependChild()
+ *
+ * Prepends a new child to a node
+ * ----------------------------------------------------------------------------- */
+
+void prependChild(Node *node, Node *chd) {
+ Node *fc;
+
+ if (!chd)
+ return;
+
+ fc = firstChild(node);
+ if (fc) {
+ set_nextSibling(chd, fc);
+ set_previousSibling(fc, chd);
+ }
+ set_firstChild(node, chd);
+ while (chd) {
+ set_parentNode(chd, node);
+ chd = nextSibling(chd);
+ }
+}
+
+void appendSibling(Node *node, Node *chd) {
+ Node *parent;
+ Node *lc = node;
+ while (nextSibling(lc))
+ lc = nextSibling(lc);
+ set_nextSibling(lc, chd);
+ set_previousSibling(chd, lc);
+ parent = parentNode(node);
+ if (parent) {
+ while (chd) {
+ lc = chd;
+ set_parentNode(chd, parent);
+ chd = nextSibling(chd);
+ }
+ set_lastChild(parent, lc);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * removeNode()
+ *
+ * Removes a node from the parse tree. Detaches it from its parent's child list.
+ * ----------------------------------------------------------------------------- */
+
+void removeNode(Node *n) {
+ Node *parent;
+ Node *prev;
+ Node *next;
+
+ parent = parentNode(n);
+ if (!parent) return;
+
+ prev = previousSibling(n);
+ next = nextSibling(n);
+ if (prev) {
+ set_nextSibling(prev, next);
+ } else {
+ if (parent) {
+ set_firstChild(parent, next);
+ }
+ }
+ if (next) {
+ set_previousSibling(next, prev);
+ } else {
+ if (parent) {
+ set_lastChild(parent, prev);
+ }
+ }
+
+ /* Delete attributes */
+ Delattr(n,"parentNode");
+ Delattr(n,"nextSibling");
+ Delattr(n,"previousSibling");
+}
+
+/* -----------------------------------------------------------------------------
+ * copyNode()
+ *
+ * Copies a node, but only copies simple attributes (no lists, hashes).
+ * ----------------------------------------------------------------------------- */
+
+Node *copyNode(Node *n) {
+ Iterator ki;
+ Node *c = NewHash();
+ for (ki = First(n); ki.key; ki = Next(ki)) {
+ if (DohIsString(ki.item)) {
+ Setattr(c, ki.key, Copy(ki.item));
+ }
+ }
+ Setfile(c, Getfile(n));
+ Setline(c, Getline(n));
+ return c;
+}
+
+/* -----------------------------------------------------------------------------
+ * checkAttribute()
+ * ----------------------------------------------------------------------------- */
+
+int checkAttribute(Node *n, const_String_or_char_ptr name, const_String_or_char_ptr value) {
+ String *v = Getattr(n, name);
+ return v ? Equal(v, value) : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_require()
+ * ns - namespace for the view name for saving any attributes under
+ * n - node
+ * ... - list of attribute names of type char*
+ *
+ * An attribute is optional if it is prefixed by ?, eg "?value". All
+ * non-optional attributes are checked for on node n and if any do not exist
+ * SWIG exits with a fatal error.
+ *
+ * If the attribute name is prefixed by * or ?, eg "*value" then a copy of the
+ * attribute is saved. The saved attributes will be restored on a subsequent
+ * call to Swig_restore(). All the saved attributes are saved in the view
+ * namespace (prefixed by ns).
+ *
+ * This function can be called more than once with different namespaces.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_require(const char *ns, Node *n, ...) {
+ va_list ap;
+ char *name;
+ DOH *obj;
+
+ va_start(ap, n);
+ name = va_arg(ap, char *);
+ while (name) {
+ int newref = 0;
+ int opt = 0;
+ if (*name == '*') {
+ newref = 1;
+ name++;
+ } else if (*name == '?') {
+ newref = 1;
+ opt = 1;
+ name++;
+ }
+ obj = Getattr(n, name);
+ if (!opt && !obj) {
+ Swig_error(Getfile(n), Getline(n), "Fatal error (Swig_require). Missing attribute '%s' in node '%s'.\n", name, nodeType(n));
+ Exit(EXIT_FAILURE);
+ }
+ if (!obj)
+ obj = DohNone;
+ if (newref) {
+ /* Save a copy of the attribute */
+ Setattr(n, NewStringf("%s:%s", ns, name), obj);
+ }
+ name = va_arg(ap, char *);
+ }
+ va_end(ap);
+
+ /* Save the view */
+ {
+ String *view = Getattr(n, "view");
+ if (view) {
+ if (Strcmp(view, ns) != 0) {
+ Setattr(n, NewStringf("%s:view", ns), view);
+ Setattr(n, "view", NewString(ns));
+ }
+ } else {
+ Setattr(n, "view", NewString(ns));
+ }
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_save()
+ * Same as Swig_require(), but all attribute names are optional and all attributes
+ * are saved, ie behaves as if all the attribute names were prefixed by ?.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_save(const char *ns, Node *n, ...) {
+ va_list ap;
+ char *name;
+ DOH *obj;
+
+ va_start(ap, n);
+ name = va_arg(ap, char *);
+ while (name) {
+ if (*name == '*') {
+ name++;
+ } else if (*name == '?') {
+ name++;
+ }
+ obj = Getattr(n, name);
+ if (!obj)
+ obj = DohNone;
+
+ /* Save a copy of the attribute */
+ if (Setattr(n, NewStringf("%s:%s", ns, name), obj)) {
+ Printf(stderr, "Swig_save('%s','%s'): Warning, attribute '%s' was already saved.\n", ns, nodeType(n), name);
+ }
+ name = va_arg(ap, char *);
+ }
+ va_end(ap);
+
+ /* Save the view */
+ {
+ String *view = Getattr(n, "view");
+ if (view) {
+ if (Strcmp(view, ns) != 0) {
+ Setattr(n, NewStringf("%s:view", ns), view);
+ Setattr(n, "view", NewString(ns));
+ }
+ } else {
+ Setattr(n, "view", NewString(ns));
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_restore()
+ * Restores attributes saved by a previous call to Swig_require() or Swig_save().
+ * ----------------------------------------------------------------------------- */
+
+void Swig_restore(Node *n) {
+ String *temp;
+ int len;
+ List *l;
+ String *ns;
+ Iterator ki;
+
+ ns = Getattr(n, "view");
+ assert(ns);
+
+ l = NewList();
+
+ temp = NewStringf("%s:", ns);
+ len = Len(temp);
+
+ for (ki = First(n); ki.key; ki = Next(ki)) {
+ if (Strncmp(temp, ki.key, len) == 0) {
+ Append(l, ki.key);
+ }
+ }
+ for (ki = First(l); ki.item; ki = Next(ki)) {
+ DOH *obj = Getattr(n, ki.item);
+ Setattr(n, Char(ki.item) + len, obj);
+ Delattr(n, ki.item);
+ }
+ Delete(l);
+ Delete(temp);
+}
diff --git a/contrib/tools/swig/Source/Swig/typemap.c b/contrib/tools/swig/Source/Swig/typemap.c
new file mode 100644
index 0000000000..f0dee59d9e
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/typemap.c
@@ -0,0 +1,2210 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * typemap.c
+ *
+ * A somewhat generalized implementation of SWIG1.1 typemaps.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+#include <ctype.h>
+
+#if 0
+#define SWIG_DEBUG
+#endif
+
+static int typemap_search_debug = 0;
+static int typemaps_used_debug = 0;
+static int typemap_register_debug = 0;
+static int in_typemap_search_multi = 0;
+
+static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f, Node *file_line_node);
+
+/* -----------------------------------------------------------------------------
+ * Typemaps are stored in a collection of nested hash tables. Something like
+ * this:
+ *
+ * [ type ]
+ * +-------- [ name ]
+ * +-------- [ name ]
+ *
+ * Each hash table [ type ] or [ name ] then contains references to the
+ * different typemap methods. These are referenced by names such as
+ * "tmap:in", "tmap:out", "tmap:argout", and so forth.
+ *
+ * The object corresponding to a specific typemap method has the following attributes:
+ *
+ * "type" - Typemap type
+ * "pname" - Parameter name
+ * "code" - Typemap code
+ * "source" - Source directive (%apply or %typemap) for the typemap
+ * "locals" - Local variables (if any)
+ * "kwargs" - Typemap attributes
+ *
+ * Example for a typemap method named "in":
+ * %typemap(in, warning="987:my warning", noblock=1) int &my_int (int tmp) "$1 = $input;"
+ *
+ * "type" - r.int
+ * "pname" - my_int
+ * "code" - $1 = $input;
+ * "source" - typemap(in) int &my_int
+ * "locals" - int tmp
+ * "kwargs" - warning="987:my typemap warning", foo=123
+ *
+ * ----------------------------------------------------------------------------- */
+
+static Hash *typemaps;
+
+/* -----------------------------------------------------------------------------
+ * typemap_identifier_fix()
+ *
+ * Create a type that can be used as a hash key lookup independent of the various
+ * ways a template parameter list can be defined. This is achieved by fully
+ * resolving the template parameters.
+ *
+ * This is a copy and modification of feature_identifier_fix in parser.y.
+ * ----------------------------------------------------------------------------- */
+
+static SwigType *typemap_identifier_fix(const SwigType *s) {
+ String *tp = SwigType_istemplate_templateprefix(s);
+ if (tp) {
+ String *ts, *ta, *tq, *tr;
+ ts = SwigType_templatesuffix(s);
+ ta = SwigType_templateargs(s);
+ tq = Swig_symbol_type_qualify(ta, 0);
+ tr = SwigType_typedef_resolve_all(ta);
+ Append(tp,tr);
+ Append(tp,ts);
+ Delete(ts);
+ Delete(ta);
+ Delete(tq);
+ Delete(tr);
+ return tp;
+ } else {
+ return NewString(s);
+ }
+}
+
+static Hash *get_typemap(const SwigType *type) {
+ Hash *tm = 0;
+ SwigType *dtype = 0;
+ SwigType *hashtype;
+
+ if (SwigType_istemplate(type)) {
+ SwigType *rty = typemap_identifier_fix(type);
+ String *ty = Swig_symbol_template_deftype(rty, 0);
+ dtype = Swig_symbol_type_qualify(ty, 0);
+ type = dtype;
+ Delete(ty);
+ }
+
+ /* remove unary scope operator (::) prefix indicating global scope for looking up in the hashmap */
+ hashtype = SwigType_remove_global_scope_prefix(type);
+ tm = Getattr(typemaps, hashtype);
+
+ Delete(dtype);
+ Delete(hashtype);
+
+ return tm;
+}
+
+static void set_typemap(const SwigType *type, Hash **tmhash) {
+ SwigType *hashtype = 0;
+ Hash *new_tm = 0;
+ assert(*tmhash == 0);
+ if (SwigType_istemplate(type)) {
+ SwigType *rty = typemap_identifier_fix(type);
+ String *ty = Swig_symbol_template_deftype(rty, 0);
+ String *tyq = Swig_symbol_type_qualify(ty, 0);
+ hashtype = SwigType_remove_global_scope_prefix(tyq);
+ *tmhash = Getattr(typemaps, hashtype);
+ Delete(rty);
+ Delete(tyq);
+ Delete(ty);
+ } else {
+ hashtype = SwigType_remove_global_scope_prefix(type);
+ }
+
+ if (!*tmhash) {
+ /* this type has not been seen before even after resolving template parameter types */
+ new_tm = NewHash();
+ *tmhash = new_tm;
+ }
+
+ /* note that the unary scope operator (::) prefix indicating global scope has been removed from the type */
+ Setattr(typemaps, hashtype, *tmhash);
+
+ Delete(hashtype);
+ Delete(new_tm);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_init()
+ *
+ * Initialize the typemap system
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_init(void) {
+ typemaps = NewHash();
+}
+
+static String *typemap_method_name(const_String_or_char_ptr tmap_method) {
+ static Hash *names = 0;
+ String *s;
+ /* Due to "interesting" object-identity semantics of DOH,
+ we have to make sure that we only intern strings without object
+ identity into the hash table.
+
+ (typemap_attach_kwargs calls typemap_method_name several times with
+ the "same" String *tmap_method (i.e., same object identity) but differing
+ string values.)
+
+ Most other callers work around this by using char* rather than
+ String *.
+ -- mkoeppe, Jun 17, 2003
+ */
+ const char *method_without_object_identity = Char(tmap_method);
+ if (!names)
+ names = NewHash();
+ s = Getattr(names, method_without_object_identity);
+ if (s)
+ return s;
+ s = NewStringf("tmap:%s", tmap_method);
+ Setattr(names, method_without_object_identity, s);
+ Delete(s);
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_register()
+ *
+ * Internal implementation for Swig_typemap_register()
+ * ----------------------------------------------------------------------------- */
+
+static void typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs, String *source_directive) {
+ Hash *tm;
+ Hash *tm1;
+ Hash *tm2;
+ Parm *np;
+ String *tm_method;
+ SwigType *type;
+ String *pname;
+ if (!parms)
+ return;
+
+ if (typemap_register_debug) {
+ Printf(stdout, "Registering - %s\n", tmap_method);
+ Swig_print_node(parms);
+ }
+
+ tm_method = typemap_method_name(tmap_method);
+
+ /* Register the first type in the parameter list */
+
+ type = Getattr(parms, "type");
+ pname = Getattr(parms, "name");
+
+ /* See if this type has been seen before */
+ tm = get_typemap(type);
+ if (!tm) {
+ set_typemap(type, &tm);
+ }
+ if (pname) {
+ /* See if parameter has been seen before */
+ tm1 = Getattr(tm, pname);
+ if (!tm1) {
+ tm1 = NewHash();
+ Setattr(tm, pname, tm1);
+ Delete(tm1);
+ }
+ tm = tm1;
+ }
+
+ /* Now see if this typemap method has been seen before */
+ tm2 = Getattr(tm, tm_method);
+ if (!tm2) {
+ tm2 = NewHash();
+ Setattr(tm, tm_method, tm2);
+ Delete(tm2);
+ }
+
+ /* For a multi-argument typemap, the typemap code and information
+ is really only stored in the last argument. However, to
+ make this work, we perform a really neat trick using
+ the typemap method name.
+
+ For example, consider this typemap
+
+ %typemap(in) (int foo, int *bar, char *blah[]) {
+ ...
+ }
+
+ To store it, we look at typemaps for the following:
+
+ typemap method type-name
+ ----------------------------------------------
+ "in" int foo
+ "in-int+foo:" int *bar
+ "in-int+foo:-p.int+bar: char *blah[]
+
+ Notice how the typemap method name expands to encode information about
+ previous arguments.
+
+ */
+
+ np = nextSibling(parms);
+ if (np) {
+ /* Make an entirely new typemap method key */
+ String *multi_tmap_method = NewStringf("%s-%s+%s:", tmap_method, type, pname);
+
+ /* Now reregister on the remaining arguments */
+ typemap_register(multi_tmap_method, np, code, locals, kwargs, source_directive);
+
+ Delete(multi_tmap_method);
+ } else {
+ ParmList *clocals = CopyParmList(locals);
+ ParmList *ckwargs = CopyParmList(kwargs);
+
+ Setfile(tm2, Getfile(code));
+ Setline(tm2, Getline(code));
+ Setattr(tm2, "code", code);
+ Setattr(tm2, "type", type);
+ Setattr(tm2, "source", source_directive);
+ if (pname) {
+ Setattr(tm2, "pname", pname);
+ }
+ Setattr(tm2, "locals", clocals);
+ Setattr(tm2, "kwargs", ckwargs);
+
+ Delete(clocals);
+ Delete(ckwargs);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_register()
+ *
+ * Add a new, possibly multi-argument, typemap
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs) {
+ String *parms_str = ParmList_str_multibrackets(parms);
+ String *source_directive = NewStringf("typemap(%s) %s", tmap_method, parms_str);
+
+ typemap_register(tmap_method, parms, code, locals, kwargs, source_directive);
+
+ Delete(source_directive);
+ Delete(parms_str);
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_get()
+ *
+ * Retrieve typemap information.
+ * ----------------------------------------------------------------------------- */
+
+static Hash *typemap_get(SwigType *type, const_String_or_char_ptr name) {
+ Hash *tm, *tm1;
+ tm = get_typemap(type);
+ if (!tm) {
+ return 0;
+ }
+ if ((name) && Len(name)) {
+ tm1 = Getattr(tm, name);
+ return tm1;
+ }
+ return tm;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_copy()
+ *
+ * Copy a typemap
+ * ----------------------------------------------------------------------------- */
+
+int Swig_typemap_copy(const_String_or_char_ptr tmap_method, ParmList *srcparms, ParmList *parms) {
+ Hash *tm = 0;
+ String *tm_method;
+ Parm *p;
+ String *pname;
+ SwigType *ptype;
+ String *tm_methods, *multi_tmap_method;
+ if (ParmList_len(parms) != ParmList_len(srcparms))
+ return -1;
+
+ tm_method = typemap_method_name(tmap_method);
+ p = srcparms;
+ tm_methods = NewString(tm_method);
+ while (p) {
+ ptype = Getattr(p, "type");
+ pname = Getattr(p, "name");
+
+ /* Lookup the type */
+ tm = typemap_get(ptype, pname);
+ if (!tm)
+ break;
+
+ tm = Getattr(tm, tm_methods);
+ if (!tm)
+ break;
+
+ /* Got a match. Look for next typemap */
+ multi_tmap_method = NewStringf("%s-%s+%s:", tm_methods, ptype, pname);
+ Delete(tm_methods);
+ tm_methods = multi_tmap_method;
+ p = nextSibling(p);
+ }
+ Delete(tm_methods);
+
+ if (!p && tm) {
+ /* Got some kind of match */
+ String *parms_str = ParmList_str_multibrackets(parms);
+ String *srcparms_str = ParmList_str_multibrackets(srcparms);
+ String *source_directive = NewStringf("typemap(%s) %s = %s", tmap_method, parms_str, srcparms_str);
+
+ typemap_register(tmap_method, parms, Getattr(tm, "code"), Getattr(tm, "locals"), Getattr(tm, "kwargs"), source_directive);
+
+ Delete(source_directive);
+ Delete(srcparms_str);
+ Delete(parms_str);
+ return 0;
+ }
+
+ /* Not found */
+ return -1;
+
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_clear()
+ *
+ * Delete a multi-argument typemap
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *parms) {
+ SwigType *type;
+ String *name;
+ Parm *p;
+ String *multi_tmap_method;
+ Hash *tm = 0;
+
+ /* This might not work */
+ multi_tmap_method = NewString(tmap_method);
+ p = parms;
+ while (p) {
+ type = Getattr(p, "type");
+ name = Getattr(p, "name");
+ tm = typemap_get(type, name);
+ if (!tm)
+ return;
+ p = nextSibling(p);
+ if (p)
+ Printf(multi_tmap_method, "-%s+%s:", type, name);
+ }
+ if (tm) {
+ tm = Getattr(tm, typemap_method_name(multi_tmap_method));
+ if (tm) {
+ Delattr(tm, "code");
+ Delattr(tm, "locals");
+ Delattr(tm, "kwargs");
+ }
+ }
+ Delete(multi_tmap_method);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_apply()
+ *
+ * Multi-argument %apply directive. This is pretty horrible so I sure hope
+ * it works.
+ * ----------------------------------------------------------------------------- */
+
+static int count_args(String *s) {
+ /* Count up number of arguments */
+ int na = 0;
+ char *c = Char(s);
+ while (*c) {
+ if (*c == '+')
+ na++;
+ c++;
+ }
+ return na;
+}
+
+int Swig_typemap_apply(ParmList *src, ParmList *dest) {
+ String *ssig, *dsig;
+ Parm *p, *np, *lastp, *dp, *lastdp = 0;
+ int narg = 0;
+ SwigType *type = 0, *name;
+ Hash *tm, *sm;
+ int match = 0;
+
+ /* Printf(stdout,"apply : %s --> %s\n", ParmList_str(src), ParmList_str(dest)); */
+
+ /* Create type signature of source */
+ ssig = NewStringEmpty();
+ dsig = NewStringEmpty();
+ p = src;
+ dp = dest;
+ lastp = 0;
+ while (p) {
+ lastp = p;
+ lastdp = dp;
+ np = nextSibling(p);
+ if (np) {
+ Printf(ssig, "-%s+%s:", Getattr(p, "type"), Getattr(p, "name"));
+ Printf(dsig, "-%s+%s:", Getattr(dp, "type"), Getattr(dp, "name"));
+ narg++;
+ }
+ p = np;
+ dp = nextSibling(dp);
+ }
+
+ /* make sure a typemap node exists for the last destination node */
+ type = Getattr(lastdp, "type");
+ tm = get_typemap(type);
+ if (!tm) {
+ set_typemap(type, &tm);
+ }
+ name = Getattr(lastdp, "name");
+ if (name) {
+ Hash *tm1 = Getattr(tm, name);
+ if (!tm1) {
+ tm1 = NewHash();
+ Setattr(tm, NewString(name), tm1);
+ Delete(tm1);
+ }
+ tm = tm1;
+ }
+
+ /* This is a little nasty. We need to go searching for all possible typemaps in the
+ source and apply them to the target */
+
+ type = Getattr(lastp, "type");
+ name = Getattr(lastp, "name");
+
+ /* See if there is a matching typemap in this scope */
+ sm = typemap_get(type, name);
+
+ /* if there is not matching, look for a typemap in the
+ original typedef, if any, like in:
+
+ typedef unsigned long size_t;
+ ...
+ %apply(size_t) {my_size}; ==> %apply(unsigned long) {my_size};
+ */
+ if (!sm) {
+ SwigType *ntype = SwigType_typedef_resolve(type);
+ if (ntype && (Cmp(ntype, type) != 0)) {
+ sm = typemap_get(ntype, name);
+ }
+ Delete(ntype);
+ }
+
+ if (sm) {
+ /* Got a typemap. Need to only merge attributes for methods that match our signature */
+ Iterator ki;
+ Hash *deferred_add;
+ match = 1;
+
+ /* Since typemap_register can modify the `sm` hash, we *cannot* call typemap_register while iterating over sm.
+ * Create a temporary hash of typemaps to add immediately after. */
+ deferred_add = NewHash();
+ for (ki = First(sm); ki.key; ki = Next(ki)) {
+ /* Check for a signature match with the source signature */
+ if ((count_args(ki.key) == narg) && (Strstr(ki.key, ssig))) {
+ String *oldm;
+ /* A typemap we have to copy */
+ String *nkey = Copy(ki.key);
+ Replace(nkey, ssig, dsig, DOH_REPLACE_ANY);
+
+ /* Make sure the typemap doesn't already exist in the target map */
+ oldm = Getattr(tm, nkey);
+ if (!oldm || (!Getattr(tm, "code"))) {
+ String *code;
+ Hash *sm1 = ki.item;
+
+ code = Getattr(sm1, "code");
+ if (code) {
+ Replace(nkey, dsig, "", DOH_REPLACE_ANY);
+ Replace(nkey, "tmap:", "", DOH_REPLACE_ANY);
+ Setattr(deferred_add, nkey, sm1);
+ }
+ }
+ Delete(nkey);
+ }
+ }
+
+ /* After assembling the key/item pairs, add the resulting typemaps */
+ for (ki = First(deferred_add); ki.key; ki = Next(ki)) {
+ Hash *sm1 = ki.item;
+ String *src_str = ParmList_str_multibrackets(src);
+ String *dest_str = ParmList_str_multibrackets(dest);
+ String *source_directive = NewStringf("apply %s { %s }", src_str, dest_str);
+
+ typemap_register(ki.key, dest, Getattr(sm1, "code"), Getattr(sm1, "locals"), Getattr(sm1, "kwargs"), source_directive);
+
+ Delete(source_directive);
+ Delete(dest_str);
+ Delete(src_str);
+ }
+ Delete(deferred_add);
+ }
+ Delete(ssig);
+ Delete(dsig);
+ return match;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_clear_apply()
+ *
+ * %clear directive. Clears all typemaps for a type (in the current scope only).
+ * ----------------------------------------------------------------------------- */
+
+/* Multi-argument %clear directive */
+void Swig_typemap_clear_apply(Parm *parms) {
+ String *tsig;
+ Parm *p, *np, *lastp;
+ int narg = 0;
+ Hash *tm;
+ String *name;
+
+ /* Create a type signature of the parameters */
+ tsig = NewStringEmpty();
+ p = parms;
+ lastp = 0;
+ while (p) {
+ lastp = p;
+ np = nextSibling(p);
+ if (np) {
+ Printf(tsig, "-%s+%s:", Getattr(p, "type"), Getattr(p, "name"));
+ narg++;
+ }
+ p = np;
+ }
+ tm = get_typemap(Getattr(lastp, "type"));
+ if (!tm) {
+ Delete(tsig);
+ return;
+ }
+ name = Getattr(lastp, "name");
+ if (name) {
+ tm = Getattr(tm, name);
+ }
+ if (tm) {
+ /* Clear typemaps that match our signature */
+ Iterator ki, ki2;
+ char *ctsig = Char(tsig);
+ for (ki = First(tm); ki.key; ki = Next(ki)) {
+ char *ckey = Char(ki.key);
+ if (strncmp(ckey, "tmap:", 5) == 0) {
+ int na = count_args(ki.key);
+ if ((na == narg) && strstr(ckey, ctsig)) {
+ Hash *h = ki.item;
+ for (ki2 = First(h); ki2.key; ki2 = Next(ki2)) {
+ Delattr(h, ki2.key);
+ }
+ }
+ }
+ }
+ }
+ Delete(tsig);
+}
+
+/* Internal function to strip array dimensions. */
+static SwigType *strip_arrays(SwigType *type) {
+ SwigType *t;
+ int ndim;
+ int i;
+ t = Copy(type);
+ ndim = SwigType_array_ndim(t);
+ for (i = 0; i < ndim; i++) {
+ SwigType_array_setdim(t, i, "ANY");
+ }
+ return t;
+}
+
+static void debug_search_result_display(Node *tm) {
+ if (tm)
+ Printf(stdout, " Using: %%%s\n", Getattr(tm, "source"));
+ else
+ Printf(stdout, " None found\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_search_helper()
+ *
+ * Helper function for typemap_search to see if there is a type match in the typemap
+ * tm. A match is sought in this order:
+ * %typemap(tm_method) ctype cqualifiedname
+ * %typemap(tm_method) ctype cname
+ * %typemap(tm_method) ctype
+ * ----------------------------------------------------------------------------- */
+
+static Hash *typemap_search_helper(int debug_display, Hash *tm, const String *tm_method, SwigType *ctype, const String *cqualifiedname, const String *cname, Hash **backup) {
+ Hash *result = 0;
+ Hash *tm1;
+ if (debug_display && cqualifiedname)
+ Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, cqualifiedname));
+ if (tm && cqualifiedname) {
+ tm1 = Getattr(tm, cqualifiedname);
+ if (tm1) {
+ result = Getattr(tm1, tm_method); /* See if there is a type - qualified name match */
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+ if (result)
+ *backup = result;
+ }
+ }
+ if (debug_display && cname)
+ Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, cname));
+ if (tm && cname) {
+ tm1 = Getattr(tm, cname);
+ if (tm1) {
+ result = Getattr(tm1, tm_method); /* See if there is a type - name match */
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+ if (result)
+ *backup = result;
+ }
+ }
+ if (debug_display)
+ Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, 0));
+ if (tm) {
+ result = Getattr(tm, tm_method); /* See if there is simply a type without name match */
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+ if (result)
+ *backup = result;
+ }
+ret_result:
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_search()
+ *
+ * Search for a typemap match. This is where the typemap pattern matching rules
+ * are implemented... tries to find the most specific typemap that includes a
+ * 'code' attribute.
+ * ----------------------------------------------------------------------------- */
+
+static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type, const_String_or_char_ptr name, const_String_or_char_ptr qualifiedname, SwigType **matchtype, Node *node) {
+ Hash *result = 0;
+ Hash *tm;
+ Hash *backup = 0;
+ SwigType *primitive = 0;
+ SwigType *ctype = 0;
+ SwigType *ctype_unstripped = 0;
+ int isarray;
+ const String *cname = 0;
+ const String *cqualifiedname = 0;
+ String *tm_method = typemap_method_name(tmap_method);
+ int debug_display = (in_typemap_search_multi == 0) && typemap_search_debug;
+
+ if ((name) && Len(name))
+ cname = name;
+ if ((qualifiedname) && Len(qualifiedname))
+ cqualifiedname = qualifiedname;
+
+ if (debug_display) {
+ String *typestr = SwigType_str(type, cqualifiedname ? cqualifiedname : cname);
+ Swig_diagnostic(Getfile(node), Getline(node), "Searching for a suitable '%s' typemap for: %s\n", tmap_method, typestr);
+ Delete(typestr);
+ }
+ ctype = Copy(type);
+ ctype_unstripped = Copy(ctype);
+ while (ctype) {
+ /* Try to get an exact type-match */
+ tm = get_typemap(ctype);
+ result = typemap_search_helper(debug_display, tm, tm_method, ctype, cqualifiedname, cname, &backup);
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+
+ {
+ /* Look for the type reduced to just the template prefix - for templated types without the template parameter list being specified */
+ SwigType *template_prefix = SwigType_istemplate_only_templateprefix(ctype);
+ if (template_prefix) {
+ tm = get_typemap(template_prefix);
+ result = typemap_search_helper(debug_display, tm, tm_method, template_prefix, cqualifiedname, cname, &backup);
+ Delete(template_prefix);
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+ }
+ }
+
+ /* look for [ANY] arrays */
+ isarray = SwigType_isarray(ctype);
+ if (isarray) {
+ /* If working with arrays, strip away all of the dimensions and replace with "ANY".
+ See if that generates a match */
+ SwigType *noarrays = strip_arrays(ctype);
+ tm = get_typemap(noarrays);
+ result = typemap_search_helper(debug_display, tm, tm_method, noarrays, cqualifiedname, cname, &backup);
+ Delete(noarrays);
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+ }
+
+ /* No match so far - try with a qualifier stripped (strip one qualifier at a time until none remain)
+ * The order of stripping in SwigType_strip_single_qualifier is used to provide some sort of consistency
+ * with the default (SWIGTYPE) typemap matching rules for the first qualifier to be stripped. */
+ {
+ SwigType *oldctype = ctype;
+ ctype = SwigType_strip_single_qualifier(oldctype);
+ if (!Equal(ctype, oldctype)) {
+ Delete(oldctype);
+ continue;
+ }
+ Delete(oldctype);
+ }
+
+ /* Once all qualifiers are stripped try resolve a typedef */
+ {
+ SwigType *oldctype = ctype;
+ ctype = SwigType_typedef_resolve(ctype_unstripped);
+ Delete(oldctype);
+ Delete(ctype_unstripped);
+ ctype_unstripped = Copy(ctype);
+ }
+ }
+
+ /* Hmmm. Well, no match seems to be found at all. See if there is some kind of default (SWIGTYPE) mapping */
+
+ primitive = SwigType_default_create(type);
+ while (primitive) {
+ tm = get_typemap(primitive);
+ result = typemap_search_helper(debug_display, tm, tm_method, primitive, cqualifiedname, cname, &backup);
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+
+ {
+ SwigType *nprim = SwigType_default_deduce(primitive);
+ Delete(primitive);
+ primitive = nprim;
+ }
+ }
+ if (ctype != type) {
+ Delete(ctype);
+ ctype = 0;
+ }
+ result = backup;
+
+ret_result:
+ Delete(primitive);
+ if (matchtype)
+ *matchtype = Copy(ctype);
+ Delete(ctype);
+ Delete(ctype_unstripped);
+ return result;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * typemap_search_multi()
+ *
+ * Search for a multi-argument typemap.
+ * ----------------------------------------------------------------------------- */
+
+static Hash *typemap_search_multi(const_String_or_char_ptr tmap_method, ParmList *parms, int *nmatch) {
+ SwigType *type;
+ SwigType *mtype = 0;
+ String *name;
+ String *multi_tmap_method;
+ Hash *tm;
+ Hash *tm1 = 0;
+
+ if (!parms) {
+ *nmatch = 0;
+ return 0;
+ }
+ type = Getattr(parms, "type");
+ name = Getattr(parms, "name");
+
+ /* Try to find a match on the first type */
+ tm = typemap_search(tmap_method, type, name, 0, &mtype, parms);
+ if (tm) {
+ if (mtype && SwigType_isarray(mtype)) {
+ Setattr(parms, "tmap:match", mtype);
+ }
+ Delete(mtype);
+ multi_tmap_method = NewStringf("%s-%s+%s:", tmap_method, type, name);
+ in_typemap_search_multi++;
+ tm1 = typemap_search_multi(multi_tmap_method, nextSibling(parms), nmatch);
+ in_typemap_search_multi--;
+ if (tm1)
+ tm = tm1;
+ if (Getattr(tm, "code")) {
+ *(nmatch) = *nmatch + 1;
+ if (typemap_search_debug && tm1 && (in_typemap_search_multi == 0)) {
+ Printf(stdout, " Multi-argument typemap found...\n");
+ }
+ } else {
+ tm = 0;
+ }
+ Delete(multi_tmap_method);
+ }
+
+ if (typemap_search_debug && (in_typemap_search_multi == 0))
+ debug_search_result_display(tm);
+ if (typemaps_used_debug && (in_typemap_search_multi == 0) && tm) {
+ String *typestr = SwigType_str(type, name);
+ Swig_diagnostic(Getfile(parms), Getline(parms), "Typemap for %s (%s) : %%%s\n", typestr, tmap_method, Getattr(tm, "source"));
+ assert(Getfile(parms) && Len(Getfile(parms)) > 0); /* Missing file and line numbering information */
+ Delete(typestr);
+ }
+
+ return tm;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * typemap_replace_vars()
+ *
+ * Replaces typemap variables on a string. index is the $n variable.
+ * type and pname are the type and parameter name.
+ * ----------------------------------------------------------------------------- */
+
+static void replace_local_types(ParmList *p, const String *name, const String *rep) {
+ SwigType *t;
+ while (p) {
+ t = Getattr(p, "type");
+ Replace(t, name, rep, DOH_REPLACE_ANY);
+ p = nextSibling(p);
+ }
+}
+
+static int check_locals(ParmList *p, const char *s) {
+ while (p) {
+ char *c = GetChar(p, "type");
+ if (strstr(c, s))
+ return 1;
+ p = nextSibling(p);
+ }
+ return 0;
+}
+
+static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index) {
+ char var[512];
+ char *varname;
+ SwigType *ftype;
+ int bare_substitution_count = 0;
+
+ Replaceall(s, "$typemap", "$TYPEMAP"); /* workaround for $type substitution below */
+
+ ftype = SwigType_typedef_resolve_all(type);
+
+ if (!pname)
+ pname = lname;
+ {
+ Parm *p;
+ int rep = 0;
+ p = locals;
+ while (p) {
+ if (Strchr(Getattr(p, "type"), '$'))
+ rep = 1;
+ p = nextSibling(p);
+ }
+ if (!rep)
+ locals = 0;
+ }
+
+ sprintf(var, "$%d_", index);
+ varname = &var[strlen(var)];
+
+ /* If the original datatype was an array. We're going to go through and substitute
+ its array dimensions */
+
+ if (SwigType_isarray(type) || SwigType_isarray(ftype)) {
+ String *size;
+ int ndim;
+ int i;
+ if (SwigType_array_ndim(type) != SwigType_array_ndim(ftype))
+ type = ftype;
+ ndim = SwigType_array_ndim(type);
+ size = NewStringEmpty();
+ for (i = 0; i < ndim; i++) {
+ String *dim = SwigType_array_getdim(type, i);
+ if (index == 1) {
+ char t[32];
+ sprintf(t, "$dim%d", i);
+ Replace(s, t, dim, DOH_REPLACE_ANY);
+ replace_local_types(locals, t, dim);
+ }
+ sprintf(varname, "dim%d", i);
+ Replace(s, var, dim, DOH_REPLACE_ANY);
+ replace_local_types(locals, var, dim);
+ if (Len(size))
+ Putc('*', size);
+ Append(size, dim);
+ Delete(dim);
+ }
+ sprintf(varname, "size");
+ Replace(s, var, size, DOH_REPLACE_ANY);
+ replace_local_types(locals, var, size);
+ Delete(size);
+ }
+
+ /* Parameter name substitution */
+ if (index == 1) {
+ Replace(s, "$parmname", pname, DOH_REPLACE_ANY);
+ }
+ strcpy(varname, "name");
+ Replace(s, var, pname, DOH_REPLACE_ANY);
+
+ /* Type-related stuff */
+ {
+ SwigType *star_type, *amp_type, *base_type, *lex_type;
+ SwigType *ltype, *star_ltype, *amp_ltype;
+ String *mangle, *star_mangle, *amp_mangle, *base_mangle, *base_name, *base_type_str;
+ String *descriptor, *star_descriptor, *amp_descriptor;
+ String *ts;
+ char *sc;
+
+ sc = Char(s);
+
+ if (strstr(sc, "type") || check_locals(locals, "type")) {
+ /* Given type : $type */
+ ts = SwigType_str(type, 0);
+ if (index == 1) {
+ Replace(s, "$type", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$type", type);
+ }
+ strcpy(varname, "type");
+ Replace(s, var, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, var, type);
+ Delete(ts);
+ sc = Char(s);
+ }
+ if (strstr(sc, "ltype") || check_locals(locals, "ltype")) {
+ /* Local type: $ltype */
+ ltype = SwigType_ltype(type);
+ ts = SwigType_str(ltype, 0);
+ if (index == 1) {
+ Replace(s, "$ltype", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$ltype", ltype);
+ }
+ strcpy(varname, "ltype");
+ Replace(s, var, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, var, ltype);
+ Delete(ts);
+ Delete(ltype);
+ sc = Char(s);
+ }
+ if (strstr(sc, "mangle") || strstr(sc, "descriptor")) {
+ /* Mangled type */
+
+ mangle = SwigType_manglestr(type);
+ if (index == 1)
+ Replace(s, "$mangle", mangle, DOH_REPLACE_ANY);
+ strcpy(varname, "mangle");
+ Replace(s, var, mangle, DOH_REPLACE_ANY);
+
+ descriptor = NewStringf("SWIGTYPE%s", mangle);
+
+ if (index == 1)
+ if (Replace(s, "$descriptor", descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(type);
+
+ strcpy(varname, "descriptor");
+ if (Replace(s, var, descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(type);
+
+ Delete(descriptor);
+ Delete(mangle);
+ }
+
+ /* One pointer level removed */
+ /* This creates variables of the form
+ $*n_type
+ $*n_ltype
+ */
+
+ if (SwigType_ispointer(ftype) || (SwigType_isarray(ftype)) || (SwigType_isreference(ftype)) || (SwigType_isrvalue_reference(ftype))) {
+ if (!(SwigType_isarray(type) || SwigType_ispointer(type) || SwigType_isreference(type) || SwigType_isrvalue_reference(type))) {
+ star_type = Copy(ftype);
+ } else {
+ star_type = Copy(type);
+ }
+ if (!(SwigType_isreference(star_type) || SwigType_isrvalue_reference(star_type))) {
+ if (SwigType_isarray(star_type)) {
+ SwigType_del_element(star_type);
+ } else {
+ SwigType_del_pointer(star_type);
+ }
+ ts = SwigType_str(star_type, 0);
+ if (index == 1) {
+ Replace(s, "$*type", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$*type", star_type);
+ }
+ sprintf(varname, "$*%d_type", index);
+ Replace(s, varname, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, varname, star_type);
+ Delete(ts);
+ } else {
+ SwigType_del_element(star_type);
+ }
+ star_ltype = SwigType_ltype(star_type);
+ ts = SwigType_str(star_ltype, 0);
+ if (index == 1) {
+ Replace(s, "$*ltype", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$*ltype", star_ltype);
+ }
+ sprintf(varname, "$*%d_ltype", index);
+ Replace(s, varname, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, varname, star_ltype);
+ Delete(ts);
+ Delete(star_ltype);
+
+ star_mangle = SwigType_manglestr(star_type);
+ if (index == 1)
+ Replace(s, "$*mangle", star_mangle, DOH_REPLACE_ANY);
+
+ sprintf(varname, "$*%d_mangle", index);
+ Replace(s, varname, star_mangle, DOH_REPLACE_ANY);
+
+ star_descriptor = NewStringf("SWIGTYPE%s", star_mangle);
+ if (index == 1)
+ if (Replace(s, "$*descriptor", star_descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(star_type);
+ sprintf(varname, "$*%d_descriptor", index);
+ if (Replace(s, varname, star_descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(star_type);
+
+ Delete(star_descriptor);
+ Delete(star_mangle);
+ Delete(star_type);
+ } else {
+ /* TODO: Signal error if one of the $* substitutions is
+ requested */
+ }
+ /* One pointer level added */
+ amp_type = Copy(type);
+ SwigType_add_pointer(amp_type);
+ ts = SwigType_str(amp_type, 0);
+ if (index == 1) {
+ Replace(s, "$&type", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$&type", amp_type);
+ }
+ sprintf(varname, "$&%d_type", index);
+ Replace(s, varname, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, varname, amp_type);
+ Delete(ts);
+
+ amp_ltype = SwigType_ltype(type);
+ SwigType_add_pointer(amp_ltype);
+ ts = SwigType_str(amp_ltype, 0);
+
+ if (index == 1) {
+ Replace(s, "$&ltype", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$&ltype", amp_ltype);
+ }
+ sprintf(varname, "$&%d_ltype", index);
+ Replace(s, varname, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, varname, amp_ltype);
+ Delete(ts);
+ Delete(amp_ltype);
+
+ amp_mangle = SwigType_manglestr(amp_type);
+ if (index == 1)
+ Replace(s, "$&mangle", amp_mangle, DOH_REPLACE_ANY);
+ sprintf(varname, "$&%d_mangle", index);
+ Replace(s, varname, amp_mangle, DOH_REPLACE_ANY);
+
+ amp_descriptor = NewStringf("SWIGTYPE%s", amp_mangle);
+ if (index == 1)
+ if (Replace(s, "$&descriptor", amp_descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(amp_type);
+ sprintf(varname, "$&%d_descriptor", index);
+ if (Replace(s, varname, amp_descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(amp_type);
+
+ Delete(amp_descriptor);
+ Delete(amp_mangle);
+ Delete(amp_type);
+
+ /* Base type */
+ if (SwigType_isarray(type)) {
+ base_type = Copy(type);
+ Delete(SwigType_pop_arrays(base_type));
+ } else {
+ base_type = SwigType_base(type);
+ }
+
+ base_type_str = SwigType_str(base_type, 0);
+ base_name = SwigType_namestr(base_type_str);
+ if (index == 1) {
+ Replace(s, "$basetype", base_name, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$basetype", base_name);
+ }
+ strcpy(varname, "basetype");
+ Replace(s, var, base_type_str, DOH_REPLACE_ANY);
+ replace_local_types(locals, var, base_name);
+
+ base_mangle = SwigType_manglestr(base_type);
+ if (index == 1)
+ Replace(s, "$basemangle", base_mangle, DOH_REPLACE_ANY);
+ strcpy(varname, "basemangle");
+ Replace(s, var, base_mangle, DOH_REPLACE_ANY);
+ Delete(base_mangle);
+ Delete(base_name);
+ Delete(base_type_str);
+ Delete(base_type);
+
+ lex_type = SwigType_base(rtype);
+ if (index == 1)
+ Replace(s, "$lextype", lex_type, DOH_REPLACE_ANY);
+ strcpy(varname, "lextype");
+ Replace(s, var, lex_type, DOH_REPLACE_ANY);
+ Delete(lex_type);
+ }
+
+ /* Replace any $n. with (&n)-> */
+ {
+ char temp[64];
+ sprintf(var, "$%d.", index);
+ sprintf(temp, "(&$%d)->", index);
+ Replace(s, var, temp, DOH_REPLACE_ANY);
+ }
+
+ /* Replace the bare $n variable */
+ sprintf(var, "$%d", index);
+ bare_substitution_count = Replace(s, var, lname, DOH_REPLACE_NUMBER_END);
+ Delete(ftype);
+ return bare_substitution_count;
+}
+
+/* ------------------------------------------------------------------------
+ * static typemap_locals()
+ *
+ * Takes a string, a parameter list and a wrapper function argument and
+ * creates the local variables.
+ * ------------------------------------------------------------------------ */
+
+static void typemap_locals(String *s, ParmList *l, Wrapper *f, int argnum) {
+ Parm *p;
+ char *new_name;
+
+ p = l;
+ while (p) {
+ SwigType *pt = Getattr(p, "type");
+ SwigType *at = SwigType_alttype(pt, 1);
+ String *pn = Getattr(p, "name");
+ String *value = Getattr(p, "value");
+ if (at)
+ pt = at;
+ if (pn) {
+ if (Len(pn) > 0) {
+ String *str;
+ int isglobal = 0;
+
+ str = NewStringEmpty();
+
+ if (strncmp(Char(pn), "_global_", 8) == 0) {
+ isglobal = 1;
+ }
+
+ /* If the user gave us $type as the name of the local variable, we'll use
+ the passed datatype instead */
+
+ if ((argnum >= 0) && (!isglobal)) {
+ Printf(str, "%s%d", pn, argnum);
+ } else {
+ Append(str, pn);
+ }
+ if (isglobal && Wrapper_check_local(f, str)) {
+ p = nextSibling(p);
+ Delete(str);
+ if (at)
+ Delete(at);
+ continue;
+ }
+ if (value) {
+ String *pstr = SwigType_str(pt, str);
+ new_name = Wrapper_new_localv(f, str, pstr, "=", value, NIL);
+ Delete(pstr);
+ } else {
+ String *pstr = SwigType_str(pt, str);
+ new_name = Wrapper_new_localv(f, str, pstr, NIL);
+ Delete(pstr);
+ }
+ if (!isglobal) {
+ /* Substitute */
+ Replace(s, pn, new_name, DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE);
+ }
+ Delete(str);
+ }
+ }
+ p = nextSibling(p);
+ if (at)
+ Delete(at);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_warn()
+ *
+ * If any warning message is attached to this parameter's "tmap:<method>:warning"
+ * attribute, return the warning message (special variables will need expanding
+ * before displaying the warning).
+ * ----------------------------------------------------------------------------- */
+
+static String *typemap_warn(const_String_or_char_ptr tmap_method, Parm *p) {
+ String *temp = NewStringf("%s:warning", tmap_method);
+ String *w = Getattr(p, typemap_method_name(temp));
+ Delete(temp);
+ return w ? Copy(w) : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_merge_fragment_kwargs()
+ *
+ * If multiple 'fragment' attributes are provided to a typemap, combine them by
+ * concatenating with commas.
+ * ----------------------------------------------------------------------------- */
+
+static void typemap_merge_fragment_kwargs(Parm *kw) {
+ Parm *reattach_kw = NULL;
+ Parm *prev_kw = NULL;
+ Parm *next_kw = NULL;
+ String *fragment = NULL;
+ while (kw) {
+ next_kw = nextSibling(kw);
+ if (Strcmp(Getattr(kw, "name"), "fragment") == 0) {
+ String *thisfragment = Getattr(kw, "value");
+ String *kwtype = Getattr(kw, "type");
+ if (!fragment) {
+ /* First fragment found; it should remain in the list */
+ fragment = thisfragment;
+ prev_kw = kw;
+ } else {
+ /* Concatenate to previously found fragment */
+ Printv(fragment, ",", thisfragment, NULL);
+ reattach_kw = prev_kw;
+ }
+ if (kwtype) {
+ String *mangle = Swig_string_mangle(kwtype);
+ Append(fragment, mangle);
+ Delete(mangle);
+ /* Remove 'type' from kwargs so it's not duplicated later */
+ Setattr(kw, "type", NULL);
+ }
+ } else {
+ /* Not a fragment */
+ if (reattach_kw) {
+ /* Update linked list to remove duplicate fragment */
+ DohIncref(kw);
+ set_nextSibling(reattach_kw, kw);
+ set_previousSibling(kw, reattach_kw);
+ Delete(reattach_kw);
+ reattach_kw = NULL;
+ }
+ prev_kw = kw;
+ }
+ kw = next_kw;
+ }
+ if (reattach_kw) {
+ /* Update linked list to remove duplicate fragment */
+ set_nextSibling(reattach_kw, kw);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_lookup()
+ *
+ * Attach one or more typemaps to a node and optionally generate the typemap contents
+ * into the wrapper.
+ *
+ * Looks for a typemap matching the given type and name and attaches the typemap code
+ * and any typemap attributes to the provided node.
+ *
+ * The node should contain the "type" and "name" attributes for the typemap match on.
+ * input. The typemap code and typemap attribute values are attached onto the node
+ * prefixed with "tmap:". For example with tmap_method="in", the typemap code can be retrieved
+ * with a call to Getattr(node, "tmap:in") (this is also the string returned) and the
+ * "noblock" attribute can be retrieved with a call to Getattr(node, "tmap:in:noblock").
+ *
+ * tmap_method - typemap method, eg "in", "out", "newfree"
+ * node - the node to attach the typemap and typemap attributes to
+ * lname - name of variable to substitute $1, $2 etc for
+ * f - wrapper code to generate into if non null
+ * actioncode - code to generate into f before the out typemap code, unless
+ * the optimal attribute is set in the out typemap in which case
+ * $1 in the out typemap will be replaced by the code in actioncode.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) {
+ SwigType *type;
+ SwigType *mtype = 0;
+ String *pname;
+ String *qpname = 0;
+ String *noscope_pname = 0;
+ Hash *tm = 0;
+ String *s = 0;
+ String *sdef = 0;
+ String *warning = 0;
+ ParmList *locals;
+ ParmList *kw;
+ char temp[256];
+ String *symname;
+ String *cname = 0;
+ String *clname = 0;
+ char *cmethod = Char(tmap_method);
+ int optimal_attribute = 0;
+ int optimal_substitution = 0;
+ int delete_optimal_attribute = 0;
+ int num_substitutions = 0;
+ SwigType *matchtype = 0;
+
+ type = Getattr(node, "type");
+ if (!type)
+ return sdef;
+
+ /* Special hook (hack!). Check for the 'ref' feature and add code it contains to any 'newfree' typemap code.
+ * We could choose to put this hook into a number of different typemaps, not necessarily 'newfree'...
+ * Rather confusingly 'newfree' is used to release memory and the 'ref' feature is used to add in memory references - yuck! */
+ if (Cmp(tmap_method, "newfree") == 0) {
+ String *base = SwigType_base(type);
+ Node *typenode = Swig_symbol_clookup(base, 0);
+ if (typenode)
+ sdef = Swig_ref_call(typenode, lname);
+ Delete(base);
+ }
+
+ pname = Getattr(node, "name");
+ noscope_pname = Copy(pname);
+
+ if (pname && Getattr(node, "sym:symtab")) {
+ /* Add on a qualified name search for any symbol in the symbol table, for example:
+ * struct Foo {
+ * int *foo(int bar) -> Foo::foo
+ * };
+ * Note that if node is a parameter (Parm *) then there will be no symbol table attached to the Parm *.
+ */
+ String *qsn;
+ if (Swig_scopename_check(pname)) {
+ /* sometimes pname is qualified, so we remove all the scope for the lookup */
+ Delete(noscope_pname);
+ noscope_pname = Swig_scopename_last(pname);
+ /*
+ Printf(stdout, "Removed scope: %s => %s\n", pname, noscope_pname);
+ */
+ }
+ qsn = Swig_symbol_qualified(node);
+ if (qsn && Len(qsn)) {
+ qpname = NewStringf("%s::%s", qsn, noscope_pname);
+ Delete(qsn);
+ }
+ }
+
+ tm = typemap_search(tmap_method, type, noscope_pname, qpname, &mtype, node);
+ if (typemap_search_debug)
+ debug_search_result_display(tm);
+ if (typemaps_used_debug && tm) {
+ String *typestr = SwigType_str(type, qpname ? qpname : pname);
+ Swig_diagnostic(Getfile(node), Getline(node), "Typemap for %s (%s) : %%%s\n", typestr, tmap_method, Getattr(tm, "source"));
+ assert(Getfile(node) && Len(Getfile(node)) > 0); /* Missing file and line numbering information */
+ Delete(typestr);
+ }
+
+ Delete(qpname);
+ qpname = 0;
+ Delete(noscope_pname);
+ noscope_pname = 0;
+
+ if (!tm)
+ return sdef;
+
+ s = Getattr(tm, "code");
+ if (!s)
+ return sdef;
+
+ /* Empty typemap. No match */
+ if (Cmp(s, "pass") == 0)
+ return sdef;
+
+ s = Copy(s); /* Make a local copy of the typemap code */
+
+ /* Look in the "out" typemap for the "optimal" attribute */
+ if (Cmp(cmethod, "out") == 0) {
+ kw = Getattr(tm, "kwargs");
+ while (kw) {
+ if (Cmp(Getattr(kw, "name"), "optimal") == 0) {
+ optimal_attribute = GetFlag(kw, "value");
+ break;
+ }
+ kw = nextSibling(kw);
+ }
+ }
+
+ if (optimal_attribute) {
+ /* Note: "out" typemap is the only typemap that will have the "optimal" attribute set.
+ * If f and actioncode are NULL, then the caller is just looking to attach the "out" attributes
+ * ie, not use the typemap code, otherwise both f and actioncode must be non null. */
+ if (actioncode) {
+ const String *result_equals = NewStringf("%s = ", Swig_cresult_name());
+ /* check that the code in the typemap can be used in this optimal way.
+ * The code should be in the form "result = ...;\n". We need to extract
+ * the "..." part. This may not be possible for various reasons, eg
+ * code added by %exception. This optimal code generation is bit of a
+ * hack and circumvents the normal requirement for a temporary variable
+ * to hold the result returned from a wrapped function call.
+ */
+ if (Strncmp(actioncode, result_equals, Len(result_equals)) == 0 &&
+ Strchr(actioncode, ';') == Char(actioncode) + Len(actioncode) - 2 &&
+ Char(actioncode)[Len(actioncode) - 1] == '\n') {
+ clname = NewStringWithSize(Char(actioncode) + Len(result_equals),
+ Len(actioncode) - Len(result_equals) - 2);
+ lname = clname;
+ actioncode = 0;
+ optimal_substitution = 1;
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(node), Getline(node), "Method %s usage of the optimal attribute ignored\n", Swig_name_decl(node));
+ Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(s), Getline(s), "in the out typemap as the following cannot be used to generate optimal code: %s\n", actioncode);
+ delete_optimal_attribute = 1;
+ }
+ } else {
+ assert(!f);
+ }
+ }
+
+ if (actioncode) {
+ assert(f);
+ Append(f->code, actioncode);
+ }
+
+ /* emit local variables declared in typemap, eg emit declarations for aa and bb in:
+ * %typemap(in) foo (int aa, int bb) "..." */
+ locals = Getattr(tm, "locals");
+ if (locals)
+ locals = CopyParmList(locals);
+
+ if (pname) {
+ if (SwigType_istemplate(pname)) {
+ cname = SwigType_namestr(pname);
+ pname = cname;
+ }
+ }
+ if (SwigType_istemplate((char *) lname)) {
+ clname = SwigType_namestr((char *) lname);
+ lname = clname;
+ }
+
+ matchtype = mtype && SwigType_isarray(mtype) ? mtype : type;
+ num_substitutions = typemap_replace_vars(s, locals, matchtype, type, pname, (char *) lname, 1);
+ if (optimal_substitution && num_substitutions > 1) {
+ Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(node), Getline(node), "Multiple calls to %s might be generated due to\n", Swig_name_decl(node));
+ Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(s), Getline(s), "optimal attribute usage in the out typemap.\n");
+ }
+
+ if (locals && f) {
+ typemap_locals(s, locals, f, -1);
+ }
+
+ {
+ ParmList *parm_sublist = NewParmWithoutFileLineInfo(type, pname);
+ Setattr(parm_sublist, "lname", lname);
+ replace_embedded_typemap(s, parm_sublist, f, tm);
+ Delete(parm_sublist);
+ }
+
+ /* Attach kwargs - ie the typemap attributes */
+ kw = Getattr(tm, "kwargs");
+ typemap_merge_fragment_kwargs(kw);
+ while (kw) {
+ String *value = Copy(Getattr(kw, "value"));
+ String *kwtype = Getattr(kw, "type");
+ char *ckwname = Char(Getattr(kw, "name"));
+ {
+ /* Expand special variables in typemap attributes. */
+ SwigType *ptype = Getattr(node, "type");
+ String *pname = Getattr(node, "name");
+ SwigType *mtype = Getattr(node, "tmap:match");
+ SwigType *matchtype = mtype ? mtype : ptype;
+ ParmList *parm_sublist;
+ typemap_replace_vars(value, NULL, matchtype, ptype, pname, (char *)lname, 1);
+
+ /* Expand special variable macros (embedded typemaps) in typemap attributes. */
+ parm_sublist = NewParmWithoutFileLineInfo(ptype, pname);
+ Setattr(parm_sublist, "lname", lname);
+ replace_embedded_typemap(value, parm_sublist, NULL, tm);
+ Delete(parm_sublist);
+ }
+ if (kwtype) {
+ String *mangle = Swig_string_mangle(kwtype);
+ Append(value, mangle);
+ Delete(mangle);
+ }
+ sprintf(temp, "%s:%s", cmethod, ckwname);
+ Setattr(node, typemap_method_name(temp), value);
+ Delete(value);
+ kw = nextSibling(kw);
+ }
+
+ if (delete_optimal_attribute)
+ Delattr(node, "tmap:out:optimal");
+
+ Replace(s, "$name", pname, DOH_REPLACE_ANY);
+
+ symname = Getattr(node, "sym:name");
+ if (symname)
+ Replace(s, "$symname", symname, DOH_REPLACE_ANY);
+
+ Setattr(node, typemap_method_name(tmap_method), s);
+ if (locals) {
+ sprintf(temp, "%s:locals", cmethod);
+ Setattr(node, typemap_method_name(temp), locals);
+ Delete(locals);
+ }
+
+ if (Checkattr(tm, "type", "SWIGTYPE")) {
+ sprintf(temp, "%s:SWIGTYPE", cmethod);
+ Setattr(node, typemap_method_name(temp), "1");
+ }
+
+ /* Print warnings, if any */
+ warning = typemap_warn(cmethod, node);
+ if (warning) {
+ typemap_replace_vars(warning, 0, matchtype, type, pname, (char *) lname, 1);
+ Replace(warning, "$name", pname, DOH_REPLACE_ANY);
+ if (symname)
+ Replace(warning, "$symname", symname, DOH_REPLACE_ANY);
+ Swig_warning(0, Getfile(node), Getline(node), "%s\n", warning);
+ Delete(warning);
+ }
+
+ /* Look for code fragments */
+ {
+ String *fragment;
+ sprintf(temp, "%s:fragment", cmethod);
+ fragment = Getattr(node, typemap_method_name(temp));
+ if (fragment) {
+ String *fname = Copy(fragment);
+ Setfile(fname, Getfile(node));
+ Setline(fname, Getline(node));
+ Swig_fragment_emit(fname);
+ Delete(fname);
+ }
+ }
+
+ Delete(cname);
+ Delete(clname);
+ Delete(mtype);
+ if (sdef) { /* put 'ref' and 'newfree' codes together */
+ String *p = NewStringf("%s\n%s", sdef, s);
+ Delete(s);
+ Delete(sdef);
+ s = p;
+ }
+ Delete(actioncode);
+ return s;
+}
+
+String *Swig_typemap_lookup_out(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) {
+ assert(actioncode);
+ assert(Cmp(tmap_method, "out") == 0);
+ return Swig_typemap_lookup_impl(tmap_method, node, lname, f, actioncode);
+}
+
+String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f) {
+ return Swig_typemap_lookup_impl(tmap_method, node, lname, f, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_attach_kwargs()
+ *
+ * If this hash (tm) contains a linked list of parameters under its "kwargs"
+ * attribute, add keys for each of those named keyword arguments to this
+ * parameter for later use.
+ * For example, attach the typemap attributes to firstp (first parameter in parameter list):
+ * %typemap(in, foo="xyz") ...
+ * A new attribute called "tmap:in:foo" with value "xyz" is attached to firstp.
+ * Also expands special variables and special variable macros in the typemap attributes.
+ * ----------------------------------------------------------------------------- */
+
+static void typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr tmap_method, Parm *firstp, int nmatch) {
+ String *temp = NewStringEmpty();
+ Parm *kw = Getattr(tm, "kwargs");
+ typemap_merge_fragment_kwargs(kw);
+ while (kw) {
+ String *value = Copy(Getattr(kw, "value"));
+ String *type = Getattr(kw, "type");
+ int i;
+ Parm *p = firstp;
+ /* Expand special variables */
+ for (i = 0; i < nmatch; i++) {
+ SwigType *type = Getattr(p, "type");
+ String *pname = Getattr(p, "name");
+ String *lname = Getattr(p, "lname");
+ SwigType *mtype = Getattr(p, "tmap:match");
+ SwigType *matchtype = mtype ? mtype : type;
+ typemap_replace_vars(value, NULL, matchtype, type, pname, lname, i + 1);
+ p = nextSibling(p);
+ }
+
+ /* Expand special variable macros (embedded typemaps).
+ * Special variable are expanded first above as they might be used in the special variable macros.
+ * For example: $typemap(imtype, $2_type). */
+ p = firstp;
+ for (i = 0; i < nmatch; i++) {
+ SwigType *type = Getattr(p, "type");
+ String *pname = Getattr(p, "name");
+ String *lname = Getattr(p, "lname");
+ ParmList *parm_sublist = NewParmWithoutFileLineInfo(type, pname);
+ Setattr(parm_sublist, "lname", lname);
+ replace_embedded_typemap(value, parm_sublist, NULL, tm);
+ p = nextSibling(p);
+ }
+ if (type) {
+ Hash *v = NewHash();
+ Setattr(v, "type", type);
+ Setattr(v, "value", value);
+ Delete(value);
+ value = v;
+ }
+ Clear(temp);
+ Printf(temp, "%s:%s", tmap_method, Getattr(kw, "name"));
+ Setattr(firstp, typemap_method_name(temp), value);
+ Delete(value);
+ kw = nextSibling(kw);
+ }
+ Clear(temp);
+ Printf(temp, "%s:match_type", tmap_method);
+ Setattr(firstp, typemap_method_name(temp), Getattr(tm, "type"));
+ Delete(temp);
+}
+
+static void typemap_emit_code_fragments(const_String_or_char_ptr tmap_method, Parm *p) {
+ String *temp = NewStringf("%s:fragment", tmap_method);
+ String *f = Getattr(p, typemap_method_name(temp));
+ if (f) {
+ String *fname = Copy(f);
+ Setfile(fname, Getfile(p));
+ Setline(fname, Getline(p));
+ Swig_fragment_emit(fname);
+ Delete(fname);
+ }
+ Delete(temp);
+}
+
+static String *typemap_get_option(Hash *tm, const_String_or_char_ptr name) {
+ Parm *kw = Getattr(tm, "kwargs");
+ while (kw) {
+ String *kname = Getattr(kw, "name");
+ if (Equal(kname, name)) {
+ return Getattr(kw, "value");
+ }
+ kw = nextSibling(kw);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_attach_parms()
+ *
+ * Given a parameter list, this function attaches all of the typemaps and typemap
+ * attributes to the parameter for each type in the parameter list.
+ *
+ * This function basically provides the typemap code and typemap attribute values as
+ * attributes on each parameter prefixed with "tmap:". For example with tmap_method="in", the typemap
+ * code can be retrieved for the first parameter with a call to Getattr(parm, "tmap:in")
+ * and the "numinputs" attribute can be retrieved with a call to Getattr(parm, "tmap:in:numinputs").
+ *
+ * tmap_method - typemap method, eg "in", "out", "newfree"
+ * parms - parameter list to attach each typemap and all typemap attributes
+ * f - wrapper code to generate into if non null
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f) {
+ Parm *p, *firstp;
+ Hash *tm;
+ int nmatch = 0;
+ int i;
+ String *s;
+ String *warning = 0;
+ ParmList *locals;
+ int argnum = 0;
+ char temp[256];
+ char *cmethod = Char(tmap_method);
+ String *kwmatch = 0;
+ p = parms;
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_typemap_attach_parms: %s\n", tmap_method);
+#endif
+
+ while (p) {
+ argnum++;
+ nmatch = 0;
+#ifdef SWIG_DEBUG
+ Printf(stdout, "parms: %s %s %s\n", tmap_method, Getattr(p, "name"), Getattr(p, "type"));
+#endif
+ tm = typemap_search_multi(tmap_method, p, &nmatch);
+#ifdef SWIG_DEBUG
+ if (tm)
+ Printf(stdout, "found: %s\n", tm);
+#endif
+ if (!tm) {
+ p = nextSibling(p);
+ continue;
+ }
+ /*
+ Check if the typemap requires to match the type of another
+ typemap, for example:
+
+ %typemap(in) SWIGTYPE * (int var) {...}
+ %typemap(freearg,match="in") SWIGTYPE * {if (var$argnum) ...}
+
+ here, the freearg typemap requires the "in" typemap to match,
+ or the 'var$argnum' variable will not exist.
+ */
+ kwmatch = typemap_get_option(tm, "match");
+ if (kwmatch) {
+ String *tmname = NewStringf("tmap:%s", kwmatch);
+ String *tmin = Getattr(p, tmname);
+ Delete(tmname);
+#ifdef SWIG_DEBUG
+ if (tm)
+ Printf(stdout, "matching: %s\n", kwmatch);
+#endif
+ if (tmin) {
+ String *tmninp = NewStringf("tmap:%s:numinputs", kwmatch);
+ String *ninp = Getattr(p, tmninp);
+ Delete(tmninp);
+ if (ninp && Equal(ninp, "0")) {
+ p = nextSibling(p);
+ continue;
+ } else {
+ SwigType *typetm = Getattr(tm, "type");
+ String *temp = NewStringf("tmap:%s:match_type", kwmatch);
+ SwigType *typein = Getattr(p, temp);
+ Delete(temp);
+ if (!Equal(typein, typetm)) {
+ p = nextSibling(p);
+ continue;
+ } else {
+ int nnmatch;
+ Hash *tmapin = typemap_search_multi(kwmatch, p, &nnmatch);
+ String *tmname = Getattr(tm, "pname");
+ String *tnname = Getattr(tmapin, "pname");
+ if (!(tmname && tnname && Equal(tmname, tnname)) && !(!tmname && !tnname)) {
+ p = nextSibling(p);
+ continue;
+ }
+ }
+
+ }
+ } else {
+ p = nextSibling(p);
+ continue;
+ }
+ }
+
+ s = Getattr(tm, "code");
+ if (!s) {
+ p = nextSibling(p);
+ continue;
+ }
+#ifdef SWIG_DEBUG
+ if (s)
+ Printf(stdout, "code: %s\n", s);
+#endif
+
+ /* Empty typemap. No match */
+ if (Cmp(s, "pass") == 0) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ s = Copy(s);
+ locals = Getattr(tm, "locals");
+ if (locals)
+ locals = CopyParmList(locals);
+ firstp = p;
+#ifdef SWIG_DEBUG
+ Printf(stdout, "nmatch: %d\n", nmatch);
+#endif
+ for (i = 0; i < nmatch; i++) {
+ SwigType *type = Getattr(p, "type");
+ String *pname = Getattr(p, "name");
+ String *lname = Getattr(p, "lname");
+ SwigType *mtype = Getattr(p, "tmap:match");
+ SwigType *matchtype = mtype ? mtype : type;
+
+ typemap_replace_vars(s, locals, matchtype, type, pname, lname, i + 1);
+ if (mtype)
+ Delattr(p, "tmap:match");
+
+ if (Checkattr(tm, "type", "SWIGTYPE")) {
+ sprintf(temp, "%s:SWIGTYPE", cmethod);
+ Setattr(p, typemap_method_name(temp), "1");
+ }
+ p = nextSibling(p);
+ }
+
+ if (locals && f) {
+ typemap_locals(s, locals, f, argnum);
+ }
+
+ replace_embedded_typemap(s, firstp, f, tm);
+
+ /* Attach attributes to object */
+#ifdef SWIG_DEBUG
+ Printf(stdout, "attach: %s %s %s\n", Getattr(firstp, "name"), typemap_method_name(tmap_method), s);
+#endif
+ Setattr(firstp, typemap_method_name(tmap_method), s); /* Code object */
+
+ if (locals) {
+ sprintf(temp, "%s:locals", cmethod);
+ Setattr(firstp, typemap_method_name(temp), locals);
+ Delete(locals);
+ }
+
+ /* Attach a link to the next parameter. Needed for multimaps */
+ sprintf(temp, "%s:next", cmethod);
+ Setattr(firstp, typemap_method_name(temp), p);
+
+ /* Attach kwargs */
+ typemap_attach_kwargs(tm, tmap_method, firstp, nmatch);
+
+ /* Replace the argument number */
+ sprintf(temp, "%d", argnum);
+ Replace(s, "$argnum", temp, DOH_REPLACE_ANY);
+
+ /* Print warnings, if any */
+ warning = typemap_warn(tmap_method, firstp);
+ if (warning) {
+ SwigType *type = Getattr(firstp, "type");
+ String *pname = Getattr(firstp, "name");
+ String *lname = Getattr(firstp, "lname");
+ SwigType *mtype = Getattr(firstp, "tmap:match");
+ SwigType *matchtype = mtype ? mtype : type;
+ typemap_replace_vars(warning, 0, matchtype, type, pname, lname, 1);
+ Replace(warning, "$argnum", temp, DOH_REPLACE_ANY);
+ Swig_warning(0, Getfile(firstp), Getline(firstp), "%s\n", warning);
+ Delete(warning);
+ }
+
+ /* Look for code fragments */
+ typemap_emit_code_fragments(tmap_method, firstp);
+
+ /* increase argnum to consider numinputs */
+ argnum += nmatch - 1;
+ Delete(s);
+#ifdef SWIG_DEBUG
+ Printf(stdout, "res: %s %s %s\n", Getattr(firstp, "name"), typemap_method_name(tmap_method), Getattr(firstp, typemap_method_name(tmap_method)));
+#endif
+
+ }
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_typemap_attach_parms: end\n");
+#endif
+
+}
+
+/* Splits the arguments of an embedded typemap */
+static List *split_embedded_typemap(String *s) {
+ List *args = 0;
+ char *c, *start;
+ int level = 0;
+ int angle_level = 0;
+ int leading = 1;
+
+ args = NewList();
+ c = strchr(Char(s), '(');
+ assert(c);
+ c++;
+
+ start = c;
+ while (*c) {
+ if (*c == '\"') {
+ c++;
+ while (*c) {
+ if (*c == '\\') {
+ c++;
+ } else {
+ if (*c == '\"')
+ break;
+ }
+ c++;
+ }
+ }
+ if ((level == 0) && angle_level == 0 && ((*c == ',') || (*c == ')'))) {
+ String *tmp = NewStringWithSize(start, (int)(c - start));
+ Append(args, tmp);
+ Delete(tmp);
+ start = c + 1;
+ leading = 1;
+ if (*c == ')')
+ break;
+ c++;
+ continue;
+ }
+ if (*c == '(')
+ level++;
+ if (*c == ')')
+ level--;
+ if (*c == '<')
+ angle_level++;
+ if (*c == '>')
+ angle_level--;
+ if (isspace((int) *c) && leading)
+ start++;
+ if (!isspace((int) *c))
+ leading = 0;
+ c++;
+ }
+ return args;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_replace_embedded_typemap()
+ *
+ * For special variable macro $typemap(...) expansion outside of typemaps.
+ * Only limited usage works as most typemap special variables ($1, $input etc)
+ * are not expanded correctly outside of typemaps.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_replace_embedded_typemap(String *s, Node *file_line_node) {
+ Setfile(s, Getfile(file_line_node));
+ Setline(s, Getline(file_line_node));
+ Replaceall(s, "$typemap", "$TYPEMAP");
+ replace_embedded_typemap(s, 0, 0, file_line_node);
+}
+
+/* -----------------------------------------------------------------------------
+ * replace_embedded_typemap()
+ *
+ * This function replaces the special variable macro $typemap(...) with typemap
+ * code. The general form of $typemap is as follows:
+ *
+ * $typemap(method, typelist, var1=value, var2=value, ...)
+ *
+ * where varx parameters are optional and undocumented; they were used in an earlier version of $typemap.
+ * A search is made using the typemap matching rules of form:
+ *
+ * %typemap(method) typelist {...}
+ *
+ * and if found will substitute in the typemap contents, making appropriate variable replacements.
+ *
+ * For example:
+ * $typemap(in, int) # simple usage matching %typemap(in) int { ... }
+ * $typemap(in, int b) # simple usage matching %typemap(in) int b { ... } or above %typemap
+ * $typemap(in, (Foo<int, bool> a, int b)) # multi-argument typemap matching %typemap(in) (Foo<int, bool> a, int b) {...}
+ * ----------------------------------------------------------------------------- */
+
+static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f, Node *file_line_node) {
+ char *start = 0;
+ while ((start = strstr(Char(s), "$TYPEMAP("))) { /* note $typemap capitalisation to $TYPEMAP hack */
+
+ /* Gather the parameters */
+ char *end = 0, *c;
+ int level = 0;
+ String *dollar_typemap;
+ int syntax_error = 1;
+ c = start;
+ while (*c) {
+ if (*c == '(')
+ level++;
+ if (*c == ')') {
+ level--;
+ if (level == 0) {
+ end = c + 1;
+ break;
+ }
+ }
+ c++;
+ }
+ if (end) {
+ dollar_typemap = NewStringWithSize(start, (int)((end - start)));
+ syntax_error = 0;
+ } else {
+ dollar_typemap = NewStringWithSize(start, (int)((c - start)));
+ }
+
+ if (!syntax_error) {
+ List *l;
+ String *tmap_method;
+ Hash *vars;
+ syntax_error = 1;
+
+ /* Split apart each parameter in $typemap(...) */
+ l = split_embedded_typemap(dollar_typemap);
+
+ if (Len(l) >= 2) {
+ ParmList *to_match_parms;
+ tmap_method = Getitem(l, 0);
+
+ /* the second parameter might contain multiple sub-parameters for multi-argument
+ * typemap matching, so split these parameters apart */
+ to_match_parms = Swig_cparse_parms(Getitem(l, 1), file_line_node);
+ if (to_match_parms) {
+ Parm *p = to_match_parms;
+ Parm *sub_p = parm_sublist;
+ String *empty_string = NewStringEmpty();
+ String *lname = empty_string;
+ while (p) {
+ if (sub_p) {
+ lname = Getattr(sub_p, "lname");
+ sub_p = nextSibling(sub_p);
+ }
+ Setattr(p, "lname", lname);
+ p = nextSibling(p);
+ }
+ Delete(empty_string);
+ }
+
+ /* process optional extra parameters - the variable replacements (undocumented) */
+ vars = NewHash();
+ {
+ int i, ilen;
+ ilen = Len(l);
+ for (i = 2; i < ilen; i++) {
+ String *parm = Getitem(l, i);
+ char *eq = strchr(Char(parm), '=');
+ char *c = Char(parm);
+ if (eq && (eq - c > 0)) {
+ String *name = NewStringWithSize(c, (int)(eq - c));
+ String *value = NewString(eq + 1);
+ Insert(name, 0, "$");
+ Setattr(vars, name, value);
+ } else {
+ to_match_parms = 0; /* error - variable replacement parameters must be of form varname=value */
+ }
+ }
+ }
+
+ /* Perform a typemap search */
+ if (to_match_parms) {
+ static int already_substituting = 0;
+ String *tm;
+ String *attr;
+ int match = 0;
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_typemap_attach_parms: embedded\n");
+#endif
+ if (already_substituting < 10) {
+ char* found_colon;
+ already_substituting++;
+ if ((in_typemap_search_multi == 0) && typemap_search_debug) {
+ String *dtypemap = NewString(dollar_typemap);
+ Replaceall(dtypemap, "$TYPEMAP", "$typemap");
+ Printf(stdout, " Containing: %s\n", dtypemap);
+ Delete(dtypemap);
+ }
+ found_colon = Strchr(tmap_method, ':');
+ if (found_colon) {
+ /* Substitute from a keyword argument to a typemap. Avoid emitting local variables from the attached typemap by passing NULL for the file. */
+ String *temp_tmap_method = NewStringWithSize(Char(tmap_method), (int)(found_colon - Char(tmap_method)));
+ Swig_typemap_attach_parms(temp_tmap_method, to_match_parms, NULL);
+ Delete(temp_tmap_method);
+ } else {
+ Swig_typemap_attach_parms(tmap_method, to_match_parms, f);
+ }
+ already_substituting--;
+
+ /* Look for the typemap code */
+ attr = NewStringf("tmap:%s", tmap_method);
+ tm = Getattr(to_match_parms, attr);
+ if (tm) {
+ Printf(attr, "%s", ":next");
+ /* fail if multi-argument lookup requested in $typemap(...) and the lookup failed */
+ if (!Getattr(to_match_parms, attr)) {
+ /* Replace parameter variables */
+ Iterator ki;
+ for (ki = First(vars); ki.key; ki = Next(ki)) {
+ Replace(tm, ki.key, ki.item, DOH_REPLACE_ANY);
+ }
+ /* offer the target language module the chance to make special variable substitutions */
+ Language_replace_special_variables(tmap_method, tm, to_match_parms);
+ /* finish up - do the substitution */
+ Replace(s, dollar_typemap, tm, DOH_REPLACE_ANY);
+ Delete(tm);
+ match = 1;
+ }
+ }
+
+ if (!match) {
+ String *dtypemap = NewString(dollar_typemap);
+ Replaceall(dtypemap, "$TYPEMAP", "$typemap");
+ Swig_error(Getfile(s), Getline(s), "No typemap found for %s\n", dtypemap);
+ Delete(dtypemap);
+ }
+ Delete(attr);
+ } else {
+ /* Simple recursive call check to prevent infinite recursion - this strategy only allows a limited
+ * number of calls by a embedded typemaps to other embedded typemaps though */
+ String *dtypemap = NewString(dollar_typemap);
+ Replaceall(dtypemap, "$TYPEMAP", "$typemap");
+ Swig_error(Getfile(s), Getline(s), "Likely recursive $typemap calls containing %s. Use -debug-tmsearch to debug.\n", dtypemap);
+ Delete(dtypemap);
+ }
+ syntax_error = 0;
+ }
+ Delete(vars);
+ }
+ Delete(l);
+ }
+
+ if (syntax_error) {
+ String *dtypemap = NewString(dollar_typemap);
+ Replaceall(dtypemap, "$TYPEMAP", "$typemap");
+ Swig_error(Getfile(s), Getline(s), "Syntax error in: %s\n", dtypemap);
+ Delete(dtypemap);
+ }
+ Replace(s, dollar_typemap, "<error in embedded typemap>", DOH_REPLACE_ANY);
+ Delete(dollar_typemap);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_debug()
+ *
+ * Display all typemaps
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_debug(void) {
+ int nesting_level = 2;
+ Printf(stdout, "---[ typemaps ]--------------------------------------------------------------\n");
+ Swig_print(typemaps, nesting_level);
+ Printf(stdout, "-----------------------------------------------------------------------------\n");
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_search_debug_set()
+ *
+ * Turn on typemap searching debug display
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_search_debug_set(void) {
+ typemap_search_debug = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_used_debug_set()
+ *
+ * Turn on typemaps used debug display
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_used_debug_set(void) {
+ typemaps_used_debug = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_register_debug_set()
+ *
+ * Turn on typemaps used debug display
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_register_debug_set(void) {
+ typemap_register_debug = 1;
+}
+
diff --git a/contrib/tools/swig/Source/Swig/typeobj.c b/contrib/tools/swig/Source/Swig/typeobj.c
new file mode 100644
index 0000000000..8cd2e28e98
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/typeobj.c
@@ -0,0 +1,1367 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * typeobj.c
+ *
+ * This file provides functions for constructing, manipulating, and testing
+ * type objects. Type objects are merely the raw low-level representation
+ * of C++ types. They do not incorporate high-level type system features
+ * like typedef, namespaces, etc.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <ctype.h>
+#include <limits.h>
+
+/* -----------------------------------------------------------------------------
+ * Synopsis
+ *
+ * This file provides a collection of low-level functions for constructing and
+ * manipulating C++ data types. In SWIG, C++ datatypes are encoded as simple
+ * text strings. This representation is compact, easy to debug, and easy to read.
+ *
+ * General idea:
+ *
+ * Types are represented by a base type (e.g., "int") and a collection of
+ * type operators applied to the base (e.g., pointers, arrays, etc...).
+ *
+ * Encoding:
+ *
+ * Types are encoded as strings of type constructors such as follows:
+ *
+ * String Encoding C Example
+ * --------------- ---------
+ * p.p.int int **
+ * a(300).a(400).int int [300][400]
+ * p.q(const).char char const *
+ *
+ * All type constructors are denoted by a trailing '.':
+ *
+ * 'p.' = Pointer (*)
+ * 'r.' = Reference or ref-qualifier (&)
+ * 'z.' = Rvalue reference or ref-qualifier (&&)
+ * 'a(n).' = Array of size n [n]
+ * 'f(..,..).' = Function with arguments (args)
+ * 'q(str).' = Qualifier, such as const or volatile (cv-qualifier)
+ * 'm(cls).' = Pointer to member (cls::*)
+ *
+ * The complete type representation for varargs is:
+ * 'v(...)'
+ *
+ * The encoding follows the order that you might describe a type in words.
+ * For example "p.a(200).int" is "A pointer to array of int's" and
+ * "p.q(const).char" is "a pointer to a const char".
+ *
+ * This representation of types is fairly convenient because ordinary string
+ * operations can be used for type manipulation. For example, a type could be
+ * formed by combining two strings such as the following:
+ *
+ * "p.p." + "a(400).int" = "p.p.a(400).int"
+ *
+ * For C++, typenames may be parameterized using <(...)>. Here are some
+ * examples:
+ *
+ * String Encoding C++ Example
+ * --------------- ------------
+ * p.vector<(int)> vector<int> *
+ * r.foo<(int,p.double)> foo<int,double *> &
+ *
+ * Contents of this file:
+ *
+ * Most of this functions in this file pertain to the low-level manipulation
+ * of type objects. There are constructor functions like this:
+ *
+ * SwigType_add_pointer()
+ * SwigType_add_reference()
+ * SwigType_add_rvalue_reference()
+ * SwigType_add_array()
+ *
+ * These are used to build new types. There are also functions to undo these
+ * operations. For example:
+ *
+ * SwigType_del_pointer()
+ * SwigType_del_reference()
+ * SwigType_del_rvalue_reference()
+ * SwigType_del_array()
+ *
+ * In addition, there are query functions
+ *
+ * SwigType_ispointer()
+ * SwigType_isreference()
+ * SwigType_isrvalue_reference()
+ * SwigType_isarray()
+ *
+ * Finally, there are some data extraction functions that can be used to
+ * extract array dimensions, template arguments, and so forth.
+ *
+ * It is very important for developers to realize that the functions in this
+ * module do *NOT* incorporate higher-level type system features like typedef.
+ * For example, you could have C code like this:
+ *
+ * typedef int *intptr;
+ *
+ * In this case, a SwigType of type 'intptr' will be treated as a simple type and
+ * functions like SwigType_ispointer() will evaluate as false. It is strongly
+ * advised that developers use the TypeSys_* interface to check types in a more
+ * reliable manner.
+ * ----------------------------------------------------------------------------- */
+
+
+/* -----------------------------------------------------------------------------
+ * NewSwigType()
+ *
+ * Constructs a new type object. Eventually, it would be nice for this function
+ * to accept an initial value in the form a C/C++ abstract type (currently unimplemented).
+ * ----------------------------------------------------------------------------- */
+
+#ifdef NEW
+SwigType *NewSwigType(const_String_or_char_ptr initial) {
+ return NewString(initial);
+}
+
+#endif
+
+/* The next few functions are utility functions used in the construction and
+ management of types */
+
+/* -----------------------------------------------------------------------------
+ * static element_size()
+ *
+ * This utility function finds the size of a single type element in a type string.
+ * Type elements are always delimited by periods, but may be nested with
+ * parentheses. A nested element is always handled as a single item.
+ *
+ * Returns the integer size of the element (which can be used to extract a
+ * substring, to chop the element off, or for other purposes).
+ * ----------------------------------------------------------------------------- */
+
+static int element_size(char *c) {
+ int nparen;
+ char *s = c;
+ while (*c) {
+ if (*c == '.') {
+ c++;
+ return (int) (c - s);
+ } else if (*c == '(') {
+ nparen = 1;
+ c++;
+ while (*c) {
+ if (*c == '(')
+ nparen++;
+ if (*c == ')') {
+ nparen--;
+ if (nparen == 0)
+ break;
+ }
+ c++;
+ }
+ }
+ if (*c)
+ c++;
+ }
+ return (int) (c - s);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_del_element()
+ *
+ * Deletes one type element from the type.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_del_element(SwigType *t) {
+ int sz = element_size(Char(t));
+ Delslice(t, 0, sz);
+ return t;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_pop()
+ *
+ * Pop one type element off the type.
+ * For example:
+ * t in: q(const).p.Integer
+ * t out: p.Integer
+ * result: q(const).
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_pop(SwigType *t) {
+ SwigType *result;
+ char *c;
+ int sz;
+
+ c = Char(t);
+ if (!*c)
+ return 0;
+
+ sz = element_size(c);
+ result = NewStringWithSize(c, sz);
+ Delslice(t, 0, sz);
+ c = Char(t);
+ if (*c == '.') {
+ Delitem(t, 0);
+ }
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_last()
+ *
+ * Return the last element of the given (partial) type.
+ * For example:
+ * t: q(const).p.
+ * result: p.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_last(SwigType *t) {
+ SwigType *result;
+ char *c;
+ char *last;
+ int sz = 0;
+
+ if (!t)
+ return 0;
+
+ /* Find the last element */
+ c = Char(t);
+ last = 0;
+ while (*c) {
+ last = c;
+ sz = element_size(c);
+ c = c + sz;
+ if (*c == '.') {
+ c++;
+ sz++;
+ }
+ }
+
+ /* Extract the last element */
+ if (last) {
+ result = NewStringWithSize(last, sz);
+ } else {
+ result = 0;
+ }
+
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_parm()
+ *
+ * Returns the parameter of an operator as a string
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_parm(const SwigType *t) {
+ char *start, *c;
+ int nparens = 0;
+
+ c = Char(t);
+ while (*c && (*c != '(') && (*c != '.'))
+ c++;
+ if (!*c || (*c == '.'))
+ return 0;
+ c++;
+ start = c;
+ while (*c) {
+ if (*c == ')') {
+ if (nparens == 0)
+ break;
+ nparens--;
+ } else if (*c == '(') {
+ nparens++;
+ }
+ c++;
+ }
+ return NewStringWithSize(start, (int) (c - start));
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_split()
+ *
+ * Splits a type into its component parts and returns a list of string.
+ * ----------------------------------------------------------------------------- */
+
+List *SwigType_split(const SwigType *t) {
+ String *item;
+ List *list;
+ char *c;
+ int len;
+
+ c = Char(t);
+ list = NewList();
+ while (*c) {
+ len = element_size(c);
+ item = NewStringWithSize(c, len);
+ Append(list, item);
+ Delete(item);
+ c = c + len;
+ if (*c == '.')
+ c++;
+ }
+ return list;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_parmlist()
+ *
+ * Splits a comma separated list of parameters into its component parts
+ * The input is expected to contain the parameter list within () brackets
+ * Returns 0 if no argument list in the input, ie there are no round brackets ()
+ * Returns an empty List if there are no parameters in the () brackets
+ * For example:
+ *
+ * Foo(std::string,p.f().Bar<(int,double)>)
+ *
+ * returns 2 elements in the list:
+ * std::string
+ * p.f().Bar<(int,double)>
+ * ----------------------------------------------------------------------------- */
+
+List *SwigType_parmlist(const String *p) {
+ String *item = 0;
+ List *list;
+ char *c;
+ char *itemstart;
+ int size;
+
+ assert(p);
+ c = Char(p);
+ while (*c && (*c != '(') && (*c != '.'))
+ c++;
+ if (!*c)
+ return 0;
+ assert(*c != '.'); /* p is expected to contain sub elements of a type */
+ c++;
+ list = NewList();
+ itemstart = c;
+ while (*c) {
+ if (*c == ',') {
+ size = (int) (c - itemstart);
+ item = NewStringWithSize(itemstart, size);
+ Append(list, item);
+ Delete(item);
+ itemstart = c + 1;
+ } else if (*c == '(') {
+ int nparens = 1;
+ c++;
+ while (*c) {
+ if (*c == '(')
+ nparens++;
+ if (*c == ')') {
+ nparens--;
+ if (nparens == 0)
+ break;
+ }
+ c++;
+ }
+ } else if (*c == ')') {
+ break;
+ }
+ if (*c)
+ c++;
+ }
+ size = (int) (c - itemstart);
+ if (size > 0) {
+ item = NewStringWithSize(itemstart, size);
+ Append(list, item);
+ }
+ Delete(item);
+ return list;
+}
+
+/* -----------------------------------------------------------------------------
+ * Pointers
+ *
+ * SwigType_add_pointer()
+ * SwigType_del_pointer()
+ * SwigType_ispointer()
+ *
+ * Add, remove, and test if a type is a pointer. The deletion and query
+ * functions take into account qualifiers (if any).
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_pointer(SwigType *t) {
+ Insert(t, 0, "p.");
+ return t;
+}
+
+SwigType *SwigType_del_pointer(SwigType *t) {
+ char *c, *s;
+ c = Char(t);
+ s = c;
+ /* Skip qualifiers, if any */
+ if (strncmp(c, "q(", 2) == 0) {
+ c = strchr(c, '.');
+ assert(c);
+ c++;
+ }
+ if (strncmp(c, "p.", 2)) {
+ printf("Fatal error: SwigType_del_pointer applied to non-pointer.\n");
+ Exit(EXIT_FAILURE);
+ }
+ Delslice(t, 0, (int)((c - s) + 2));
+ return t;
+}
+
+int SwigType_ispointer(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ /* Skip qualifiers, if any */
+ if (strncmp(c, "q(", 2) == 0) {
+ c = strchr(c, '.');
+ if (!c)
+ return 0;
+ c++;
+ }
+ if (strncmp(c, "p.", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * References
+ *
+ * SwigType_add_reference()
+ * SwigType_del_reference()
+ * SwigType_isreference()
+ *
+ * Add, remove, and test if a type is a reference. The deletion and query
+ * functions take into account qualifiers (if any).
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_reference(SwigType *t) {
+ Insert(t, 0, "r.");
+ return t;
+}
+
+SwigType *SwigType_del_reference(SwigType *t) {
+ char *c = Char(t);
+ if (strncmp(c, "r.", 2)) {
+ printf("Fatal error: SwigType_del_reference applied to non-reference.\n");
+ Exit(EXIT_FAILURE);
+ }
+ Delslice(t, 0, 2);
+ return t;
+}
+
+int SwigType_isreference(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "r.", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Rvalue References
+ *
+ * SwigType_add_rvalue_reference()
+ * SwigType_del_rvalue_reference()
+ * SwigType_isrvalue_reference()
+ *
+ * Add, remove, and test if a type is a rvalue reference. The deletion and query
+ * functions take into account qualifiers (if any).
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_rvalue_reference(SwigType *t) {
+ Insert(t, 0, "z.");
+ return t;
+}
+
+SwigType *SwigType_del_rvalue_reference(SwigType *t) {
+ char *c = Char(t);
+ if (strncmp(c, "z.", 2)) {
+ fprintf(stderr, "Fatal error: SwigType_del_rvalue_reference() applied to non-rvalue-reference.\n");
+ Exit(EXIT_FAILURE);
+ }
+ Delslice(t, 0, 2);
+ return t;
+}
+
+int SwigType_isrvalue_reference(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "z.", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Qualifiers
+ *
+ * SwigType_add_qualifier()
+ * SwigType_del_qualifier()
+ * SwigType_is_qualifier()
+ *
+ * Adds type qualifiers like "const" and "volatile". When multiple qualifiers
+ * are added to a type, they are combined together into a single qualifier.
+ * Repeated qualifications have no effect. Moreover, the order of qualifications
+ * is alphabetical---meaning that "const volatile" and "volatile const" are
+ * stored in exactly the same way as "q(const volatile)".
+ * 'qual' can be a list of multiple qualifiers in any order, separated by spaces.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual) {
+ List *qlist;
+ String *allq, *newq;
+ int i, sz;
+ const char *cqprev = 0;
+ const char *c = Char(t);
+ const char *cqual = Char(qual);
+
+ /* if 't' has no qualifiers and 'qual' is a single qualifier, simply add it */
+ if ((strncmp(c, "q(", 2) != 0) && (strstr(cqual, " ") == 0)) {
+ String *temp = NewStringf("q(%s).", cqual);
+ Insert(t, 0, temp);
+ Delete(temp);
+ return t;
+ }
+
+ /* create string of all qualifiers */
+ if (strncmp(c, "q(", 2) == 0) {
+ allq = SwigType_parm(t);
+ Append(allq, " ");
+ SwigType_del_element(t); /* delete old qualifier list from 't' */
+ } else {
+ allq = NewStringEmpty();
+ }
+ Append(allq, qual);
+
+ /* create list of all qualifiers from string */
+ qlist = Split(allq, ' ', INT_MAX);
+ Delete(allq);
+
+ /* sort in alphabetical order */
+ SortList(qlist, Strcmp);
+
+ /* create new qualifier string from unique elements of list */
+ sz = Len(qlist);
+ newq = NewString("q(");
+ for (i = 0; i < sz; ++i) {
+ String *q = Getitem(qlist, i);
+ const char *cq = Char(q);
+ if (cqprev == 0 || strcmp(cqprev, cq) != 0) {
+ if (i > 0) {
+ Append(newq, " ");
+ }
+ Append(newq, q);
+ cqprev = cq;
+ }
+ }
+ Append(newq, ").");
+ Delete(qlist);
+
+ /* replace qualifier string with new one */
+ Insert(t, 0, newq);
+ Delete(newq);
+ return t;
+}
+
+SwigType *SwigType_del_qualifier(SwigType *t) {
+ char *c = Char(t);
+ int check = strncmp(c, "q(", 2);
+ assert(check == 0);
+ (void)check;
+ Delslice(t, 0, element_size(c));
+ return t;
+}
+
+int SwigType_isqualifier(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "q(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Function Pointers
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_isfunctionpointer(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "p.f(", 4) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_functionpointer_decompose
+ *
+ * Decompose the function pointer into the parameter list and the return type
+ * t - input and on completion contains the return type
+ * returns the function's parameters
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_functionpointer_decompose(SwigType *t) {
+ String *p;
+ assert(SwigType_isfunctionpointer(t));
+ p = SwigType_pop(t);
+ Delete(p);
+ p = SwigType_pop(t);
+ return p;
+}
+
+/* -----------------------------------------------------------------------------
+ * Member Pointers
+ *
+ * SwigType_add_memberpointer()
+ * SwigType_del_memberpointer()
+ * SwigType_ismemberpointer()
+ *
+ * Add, remove, and test for C++ pointer to members.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_memberpointer(SwigType *t, const_String_or_char_ptr name) {
+ String *temp = NewStringf("m(%s).", name);
+ Insert(t, 0, temp);
+ Delete(temp);
+ return t;
+}
+
+SwigType *SwigType_del_memberpointer(SwigType *t) {
+ char *c = Char(t);
+ int check = strncmp(c, "m(", 2);
+ assert(check == 0);
+ (void)check;
+ Delslice(t, 0, element_size(c));
+ return t;
+}
+
+int SwigType_ismemberpointer(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "m(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Arrays
+ *
+ * SwigType_add_array()
+ * SwigType_del_array()
+ * SwigType_isarray()
+ *
+ * Utility functions:
+ *
+ * SwigType_array_ndim() - Calculate number of array dimensions.
+ * SwigType_array_getdim() - Get array dimension
+ * SwigType_array_setdim() - Set array dimension
+ * SwigType_array_type() - Return array type
+ * SwigType_pop_arrays() - Remove all arrays
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_array(SwigType *t, const_String_or_char_ptr size) {
+ String *temp = NewString("a(");
+ Append(temp, size);
+ Append(temp, ").");
+ Insert(t, 0, temp);
+ Delete(temp);
+ return t;
+}
+
+SwigType *SwigType_del_array(SwigType *t) {
+ char *c = Char(t);
+ if (strncmp(c, "a(", 2)) {
+ fprintf(stderr, "Fatal error: SwigType_del_array() applied to non-array.\n");
+ Exit(EXIT_FAILURE);
+ }
+ Delslice(t, 0, element_size(c));
+ return t;
+}
+
+int SwigType_isarray(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "a(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+/*
+ * SwigType_prefix_is_simple_1D_array
+ *
+ * Determine if the type is a 1D array type that is treated as a pointer within SWIG
+ * eg Foo[], Foo[3] return true, but Foo[3][3], Foo*[], Foo*[3], Foo**[] return false
+ */
+int SwigType_prefix_is_simple_1D_array(const SwigType *t) {
+ char *c = Char(t);
+
+ if (c && (strncmp(c, "a(", 2) == 0)) {
+ c = strchr(c, '.');
+ if (c)
+ return (*(++c) == 0);
+ }
+ return 0;
+}
+
+
+/* Remove all arrays */
+SwigType *SwigType_pop_arrays(SwigType *t) {
+ String *ta;
+ assert(SwigType_isarray(t));
+ ta = NewStringEmpty();
+ while (SwigType_isarray(t)) {
+ SwigType *td = SwigType_pop(t);
+ Append(ta, td);
+ Delete(td);
+ }
+ return ta;
+}
+
+/* Return number of array dimensions */
+int SwigType_array_ndim(const SwigType *t) {
+ int ndim = 0;
+ char *c = Char(t);
+
+ while (c && (strncmp(c, "a(", 2) == 0)) {
+ c = strchr(c, '.');
+ if (c) {
+ c++;
+ ndim++;
+ }
+ }
+ return ndim;
+}
+
+/* Get nth array dimension */
+String *SwigType_array_getdim(const SwigType *t, int n) {
+ char *c = Char(t);
+ while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
+ c = strchr(c, '.');
+ if (c) {
+ c++;
+ n--;
+ }
+ }
+ if (n == 0) {
+ String *dim = SwigType_parm(c);
+ if (SwigType_istemplate(dim)) {
+ String *ndim = SwigType_namestr(dim);
+ Delete(dim);
+ dim = ndim;
+ }
+
+ return dim;
+ }
+
+ return 0;
+}
+
+/* Replace nth array dimension */
+void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep) {
+ String *result = 0;
+ char temp;
+ char *start;
+ char *c = Char(t);
+
+ start = c;
+ if (strncmp(c, "a(", 2)) {
+ fprintf(stderr, "Fatal error: SwigType_array_type applied to non-array.\n");
+ Exit(EXIT_FAILURE);
+ }
+
+ while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
+ c = strchr(c, '.');
+ if (c) {
+ c++;
+ n--;
+ }
+ }
+ if (n == 0) {
+ temp = *c;
+ *c = 0;
+ result = NewString(start);
+ Printf(result, "a(%s)", rep);
+ *c = temp;
+ c = strchr(c, '.');
+ Append(result, c);
+ }
+ Clear(t);
+ Append(t, result);
+ Delete(result);
+}
+
+/* Return base type of an array */
+SwigType *SwigType_array_type(const SwigType *ty) {
+ SwigType *t;
+ t = Copy(ty);
+ while (SwigType_isarray(t)) {
+ Delete(SwigType_pop(t));
+ }
+ return t;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Functions
+ *
+ * SwigType_add_function()
+ * SwigType_isfunction()
+ * SwigType_pop_function()
+ *
+ * Add, remove, and test for function types.
+ * ----------------------------------------------------------------------------- */
+
+/* Returns the function type, t, constructed from the parameters, parms */
+SwigType *SwigType_add_function(SwigType *t, ParmList *parms) {
+ String *pstr;
+ Parm *p;
+
+ Insert(t, 0, ").");
+ pstr = NewString("f(");
+ for (p = parms; p; p = nextSibling(p)) {
+ if (p != parms)
+ Putc(',', pstr);
+ Append(pstr, Getattr(p, "type"));
+ }
+ Insert(t, 0, pstr);
+ Delete(pstr);
+ return t;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_pop_function()
+ *
+ * Pop and return the function from the input type leaving the function's return
+ * type, if any.
+ * For example:
+ * t in: q(const).f().p.
+ * t out: p.
+ * result: q(const).f().
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_pop_function(SwigType *t) {
+ SwigType *f = 0;
+ SwigType *g = 0;
+ char *c = Char(t);
+ if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) {
+ /* Remove ref-qualifier */
+ f = SwigType_pop(t);
+ c = Char(t);
+ }
+ if (strncmp(c, "q(", 2) == 0) {
+ /* Remove cv-qualifier */
+ String *qual = SwigType_pop(t);
+ if (f) {
+ SwigType_push(qual, f);
+ Delete(f);
+ }
+ f = qual;
+ c = Char(t);
+ }
+ if (strncmp(c, "f(", 2)) {
+ fprintf(stderr, "Fatal error. SwigType_pop_function applied to non-function.\n");
+ Exit(EXIT_FAILURE);
+ }
+ g = SwigType_pop(t);
+ if (f)
+ SwigType_push(g, f);
+ Delete(f);
+ return g;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_pop_function_qualifiers()
+ *
+ * Pop and return the function qualifiers from the input type leaving the rest of
+ * function declaration. Returns NULL if no qualifiers.
+ * For example:
+ * t in: r.q(const).f().p.
+ * t out: f().p.
+ * result: r.q(const)
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_pop_function_qualifiers(SwigType *t) {
+ SwigType *qualifiers = 0;
+ char *c = Char(t);
+ if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) {
+ /* Remove ref-qualifier */
+ String *qual = SwigType_pop(t);
+ qualifiers = qual;
+ c = Char(t);
+ }
+ if (strncmp(c, "q(", 2) == 0) {
+ /* Remove cv-qualifier */
+ String *qual = SwigType_pop(t);
+ if (qualifiers) {
+ SwigType_push(qual, qualifiers);
+ Delete(qualifiers);
+ }
+ qualifiers = qual;
+ }
+ assert(Strncmp(t, "f(", 2) == 0);
+
+ return qualifiers;
+}
+
+int SwigType_isfunction(const SwigType *t) {
+ char *c;
+ if (!t) {
+ return 0;
+ }
+ c = Char(t);
+ if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) {
+ /* Might be a function with a ref-qualifier, skip over */
+ c += 2;
+ if (!*c)
+ return 0;
+ }
+ if (strncmp(c, "q(", 2) == 0) {
+ /* Might be a function with a cv-qualifier, skip over */
+ c = strchr(c, '.');
+ if (c)
+ c++;
+ else
+ return 0;
+ }
+ if (strncmp(c, "f(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* Create a list of parameters from the type t, using the file_line_node Node for
+ * file and line numbering for the parameters */
+ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node) {
+ List *l = SwigType_parmlist(t);
+ Hash *p, *pp = 0, *firstp = 0;
+ Iterator o;
+
+ for (o = First(l); o.item; o = Next(o)) {
+ p = file_line_node ? NewParm(o.item, 0, file_line_node) : NewParmWithoutFileLineInfo(o.item, 0);
+ if (!firstp)
+ firstp = p;
+ if (pp) {
+ set_nextSibling(pp, p);
+ Delete(p);
+ }
+ pp = p;
+ }
+ Delete(l);
+ return firstp;
+}
+
+int SwigType_isvarargs(const SwigType *t) {
+ if (Strcmp(t, "v(...)") == 0)
+ return 1;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Templates
+ *
+ * SwigType_add_template()
+ *
+ * Template handling.
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * SwigType_add_template()
+ *
+ * Adds a template to a type. This template is encoded in the SWIG type
+ * mechanism and produces a string like this:
+ *
+ * vector<int *> ----> "vector<(p.int)>"
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_template(SwigType *t, ParmList *parms) {
+ Parm *p;
+
+ Append(t, "<(");
+ for (p = parms; p; p = nextSibling(p)) {
+ String *v;
+ if (Getattr(p, "default"))
+ continue;
+ if (p != parms)
+ Append(t, ",");
+ v = Getattr(p, "value");
+ if (v) {
+ Append(t, v);
+ } else {
+ Append(t, Getattr(p, "type"));
+ }
+ }
+ Append(t, ")>");
+ return t;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_templateprefix()
+ *
+ * Returns the prefix before the first template definition.
+ * Returns the type unmodified if not a template.
+ * For example:
+ *
+ * Foo<(p.int)>::bar => Foo
+ * r.q(const).Foo<(p.int)>::bar => r.q(const).Foo
+ * Foo => Foo
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_templateprefix(const SwigType *t) {
+ const char *s = Char(t);
+ const char *c = strstr(s, "<(");
+ return c ? NewStringWithSize(s, (int)(c - s)) : NewString(s);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_templatesuffix()
+ *
+ * Returns text after a template substitution. Used to handle scope names
+ * for example:
+ *
+ * Foo<(p.int)>::bar
+ *
+ * returns "::bar"
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_templatesuffix(const SwigType *t) {
+ const char *c;
+ c = Char(t);
+ while (*c) {
+ if ((*c == '<') && (*(c + 1) == '(')) {
+ int nest = 1;
+ c++;
+ while (*c && nest) {
+ if (*c == '<')
+ nest++;
+ if (*c == '>')
+ nest--;
+ c++;
+ }
+ return NewString(c);
+ }
+ c++;
+ }
+ return NewStringEmpty();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_istemplate_templateprefix()
+ *
+ * Combines SwigType_istemplate and SwigType_templateprefix efficiently into one function.
+ * Returns the prefix before the first template definition.
+ * Returns NULL if not a template.
+ * For example:
+ *
+ * Foo<(p.int)>::bar => Foo
+ * r.q(const).Foo<(p.int)>::bar => r.q(const).Foo
+ * Foo => NULL
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_istemplate_templateprefix(const SwigType *t) {
+ const char *s = Char(t);
+ const char *c = strstr(s, "<(");
+ return c ? NewStringWithSize(s, (int)(c - s)) : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_istemplate_only_templateprefix()
+ *
+ * Similar to SwigType_istemplate_templateprefix() but only returns the template
+ * prefix if the type is just the template and not a subtype/symbol within the template.
+ * Returns NULL if not a template or is a template with a symbol within the template.
+ * For example:
+ *
+ * Foo<(p.int)> => Foo
+ * Foo<(p.int)>::bar => NULL
+ * r.q(const).Foo<(p.int)> => r.q(const).Foo
+ * r.q(const).Foo<(p.int)>::bar => NULL
+ * Foo => NULL
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_istemplate_only_templateprefix(const SwigType *t) {
+ int len = Len(t);
+ const char *s = Char(t);
+ if (len >= 4 && strcmp(s + len - 2, ")>") == 0) {
+ const char *c = strstr(s, "<(");
+ return c ? NewStringWithSize(s, (int)(c - s)) : 0;
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_templateargs()
+ *
+ * Returns the template arguments
+ * For example:
+ *
+ * Foo<(p.int)>::bar
+ *
+ * returns "<(p.int)>"
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_templateargs(const SwigType *t) {
+ const char *c;
+ const char *start;
+ c = Char(t);
+ while (*c) {
+ if ((*c == '<') && (*(c + 1) == '(')) {
+ int nest = 1;
+ start = c;
+ c++;
+ while (*c && nest) {
+ if (*c == '<')
+ nest++;
+ if (*c == '>')
+ nest--;
+ c++;
+ }
+ return NewStringWithSize(start, (int)(c - start));
+ }
+ c++;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_istemplate()
+ *
+ * Tests a type to see if it includes template parameters
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_istemplate(const SwigType *t) {
+ char *ct = Char(t);
+ ct = strstr(ct, "<(");
+ if (ct && (strstr(ct + 2, ")>")))
+ return 1;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_base()
+ *
+ * This function returns the base of a type. For example, if you have a
+ * type "p.p.int", the function would return "int".
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_base(const SwigType *t) {
+ char *c;
+ char *lastop = 0;
+ c = Char(t);
+
+ lastop = c;
+
+ /* Search for the last type constructor separator '.' */
+ while (*c) {
+ if (*c == '.') {
+ if (*(c + 1)) {
+ lastop = c + 1;
+ }
+ c++;
+ continue;
+ }
+ if (*c == '<') {
+ /* Skip over template---it's part of the base name */
+ int ntemp = 1;
+ c++;
+ while ((*c) && (ntemp > 0)) {
+ if (*c == '>')
+ ntemp--;
+ else if (*c == '<')
+ ntemp++;
+ c++;
+ }
+ if (ntemp)
+ break;
+ continue;
+ }
+ if (*c == '(') {
+ /* Skip over params */
+ int nparen = 1;
+ c++;
+ while ((*c) && (nparen > 0)) {
+ if (*c == '(')
+ nparen++;
+ else if (*c == ')')
+ nparen--;
+ c++;
+ }
+ if (nparen)
+ break;
+ continue;
+ }
+ c++;
+ }
+ return NewString(lastop);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_prefix()
+ *
+ * Returns the prefix of a datatype. For example, the prefix of the
+ * type "p.p.int" is "p.p.".
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_prefix(const SwigType *t) {
+ char *c, *d;
+ String *r = 0;
+
+ c = Char(t);
+ d = c + strlen(c);
+
+ /* Check for a type constructor */
+ if ((d > c) && (*(d - 1) == '.'))
+ d--;
+
+ while (d > c) {
+ d--;
+ if (*d == '>') {
+ int nest = 1;
+ d--;
+ while ((d > c) && (nest)) {
+ if (*d == '>')
+ nest++;
+ if (*d == '<')
+ nest--;
+ d--;
+ }
+ }
+ if (*d == ')') {
+ /* Skip over params */
+ int nparen = 1;
+ d--;
+ while ((d > c) && (nparen)) {
+ if (*d == ')')
+ nparen++;
+ if (*d == '(')
+ nparen--;
+ d--;
+ }
+ }
+
+ if (*d == '.') {
+ char t = *(d + 1);
+ *(d + 1) = 0;
+ r = NewString(c);
+ *(d + 1) = t;
+ return r;
+ }
+ }
+ return NewStringEmpty();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_strip_qualifiers()
+ *
+ * Strip all qualifiers from a type and return a new type
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_strip_qualifiers(const SwigType *t) {
+ static Hash *memoize_stripped = 0;
+ SwigType *r;
+ List *l;
+ Iterator ei;
+
+ if (!memoize_stripped)
+ memoize_stripped = NewHash();
+ r = Getattr(memoize_stripped, t);
+ if (r)
+ return Copy(r);
+
+ l = SwigType_split(t);
+ r = NewStringEmpty();
+
+ for (ei = First(l); ei.item; ei = Next(ei)) {
+ if (SwigType_isqualifier(ei.item))
+ continue;
+ Append(r, ei.item);
+ }
+ Delete(l);
+ {
+ String *key, *value;
+ key = Copy(t);
+ value = Copy(r);
+ Setattr(memoize_stripped, key, value);
+ Delete(key);
+ Delete(value);
+ }
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_strip_single_qualifier()
+ *
+ * If the type contains a qualifier, strip one qualifier and return a new type.
+ * The left most qualifier is stripped first (when viewed as C source code) but
+ * this is the equivalent to the right most qualifier using SwigType notation.
+ * Example:
+ * r.q(const).p.q(const).int => r.q(const).p.int
+ * r.q(const).p.int => r.p.int
+ * r.p.int => r.p.int
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_strip_single_qualifier(const SwigType *t) {
+ static Hash *memoize_stripped = 0;
+ SwigType *r = 0;
+ List *l;
+ int numitems;
+
+ if (!memoize_stripped)
+ memoize_stripped = NewHash();
+ r = Getattr(memoize_stripped, t);
+ if (r)
+ return Copy(r);
+
+ l = SwigType_split(t);
+
+ numitems = Len(l);
+ if (numitems >= 2) {
+ int item;
+ /* iterate backwards from last but one item */
+ for (item = numitems - 2; item >= 0; --item) {
+ String *subtype = Getitem(l, item);
+ if (SwigType_isqualifier(subtype)) {
+ Iterator it;
+ Delitem(l, item);
+ r = NewStringEmpty();
+ for (it = First(l); it.item; it = Next(it)) {
+ Append(r, it.item);
+ }
+ break;
+ }
+ }
+ }
+ if (!r)
+ r = Copy(t);
+
+ Delete(l);
+ {
+ String *key, *value;
+ key = Copy(t);
+ value = Copy(r);
+ Setattr(memoize_stripped, key, value);
+ Delete(key);
+ Delete(value);
+ }
+ return r;
+}
+
diff --git a/contrib/tools/swig/Source/Swig/typesys.c b/contrib/tools/swig/Source/Swig/typesys.c
new file mode 100644
index 0000000000..4a11790c72
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/typesys.c
@@ -0,0 +1,2309 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * typesys.c
+ *
+ * SWIG type system management. These functions are used to manage
+ * the C++ type system including typenames, typedef, type scopes,
+ * inheritance, and namespaces. Generation of support code for the
+ * run-time type checker is also handled here.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+
+/* -----------------------------------------------------------------------------
+ * Synopsis
+ *
+ * The purpose of this module is to manage type names and scoping issues related
+ * to the C++ type system. The primary use is tracking typenames through typedef
+ * and inheritance.
+ *
+ * New typenames are introduced by typedef, class, and enum declarations.
+ * Each type is declared in a scope. This is either the global scope, a
+ * class, or a namespace. For example:
+ *
+ * typedef int A; // Typename A, in global scope
+ * namespace Foo {
+ * typedef int A; // Typename A, in scope Foo::
+ * }
+ * class Bar { // Typename Bar, in global scope
+ * typedef int A; // Typename A, in scope Bar::
+ * }
+ *
+ * To manage scopes, the type system is constructed as a tree of hash tables. Each
+ * hash table contains the following attributes:
+ *
+ * "name" - Scope name
+ * "qname" - Fully qualified typename
+ * "typetab" - Type table containing typenames and typedef information
+ * For a given key in the typetab table, the value is a fully
+ * qualified name if not pointing to itself.
+ * "symtab" - Hash table of symbols defined in a scope
+ * "inherit" - List of inherited scopes
+ * "parent" - Parent scope
+ *
+ * The contents of these tables can be viewed for debugging using the -debug-typedef
+ * option which calls SwigType_print_scope().
+ *
+ * Typedef information is stored in the "typetab" hash table. For example,
+ * if you have these declarations:
+ *
+ * typedef int A;
+ * typedef A B;
+ * typedef B *C;
+ *
+ * typetab in scope '' contains:
+ * "A" : "int"
+ * "B" : "A"
+ * "C" : "p.B"
+ *
+ * To resolve a type back to its root type, one repeatedly expands on the type base.
+ * For example:
+ *
+ * C *[40] ---> a(40).p.C (string type representation, see stype.c)
+ * ---> a(40).p.p.B (C --> p.B)
+ * ---> a(40).p.p.A (B --> A)
+ * ---> a(40).p.p.int (A --> int)
+ *
+ *
+ * Using declarations are stored in the "typetab" hash table. For example,
+ *
+ * namespace NN {
+ * struct SS {};
+ * }
+ * namespace N {
+ * struct S {};
+ * using NN::SS;
+ * }
+ * using N::S;
+ *
+ * typetab in scope '' contains:
+ * "S" : "N::S"
+ *
+ * and typetab in scope 'N' contains:
+ * "SS" : "NN::SS"
+ * "S" : "S"
+ *
+ *
+ * For inheritance, SWIG tries to resolve types back to the base class. For instance, if
+ * you have this:
+ *
+ * class Foo {
+ * public:
+ * typedef int Integer;
+ * };
+ * struct Bar : public Foo {
+ * void blah(Integer x);
+ * };
+ *
+ * In this case typetab in scope '' contains:
+ * "Foo" : "Foo"
+ * "Bar" : "Bar"
+ * and scope 'Foo' contains:
+ * "Integer" : "int"
+ * and scope 'Bar' inherits from 'Foo' but is empty (observe that blah is not a scope or typedef)
+ *
+ * The argument type of Bar::blah will be set to Foo::Integer.
+ *
+ *
+ * The scope-inheritance mechanism is used to manage C++ using directives.
+ *
+ * namespace XX {
+ * class CC {};
+ * }
+ * namespace X {
+ * class C {};
+ * using namespace XX;
+ * }
+ * using namespace X;
+ *
+ * typetab in scope '' inherits from 'X'
+ * typetab in scope 'X' inherits from 'XX' and contains:
+ * "C" : "C"
+ * typetab in scope 'XX' contains:
+ * "CC" : "CC"
+ *
+ *
+ * The scope-inheritance mechanism is used to manage C++ namespace aliases.
+ * For example, if you have this:
+ *
+ * namespace Foo {
+ * typedef int Integer;
+ * }
+ *
+ * namespace F = Foo;
+ *
+ * In this case, F is defined as a scope that "inherits" from Foo. Internally,
+ * F will merely be an empty scope that points to Foo. SWIG will never
+ * place new type information into a namespace alias---attempts to do so
+ * will generate a warning message (in the parser) and will place information into
+ * Foo instead.
+ *
+ *----------------------------------------------------------------------------- */
+
+static Typetab *current_scope = 0; /* Current type scope */
+static Hash *current_typetab = 0; /* Current type table */
+static Hash *current_symtab = 0; /* Current symbol table */
+static Typetab *global_scope = 0; /* The global scope */
+static Hash *scopes = 0; /* Hash table containing fully qualified scopes */
+
+/* Performance optimization */
+#define SWIG_TYPEDEF_RESOLVE_CACHE
+static Hash *typedef_resolve_cache = 0;
+static Hash *typedef_all_cache = 0;
+static Hash *typedef_qualified_cache = 0;
+
+static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix);
+
+/* common attribute keys, to avoid calling find_key all the times */
+
+/*
+ Enable this one if your language fully support SwigValueWrapper<T>.
+
+ Leaving at '0' keeps the old swig behavior, which is not
+ always safe, but is well known.
+
+ Setting at '1' activates the new scheme, which is always safe but
+ it requires all the typemaps to be ready for that.
+
+*/
+static int value_wrapper_mode = 0;
+int Swig_value_wrapper_mode(int mode) {
+ value_wrapper_mode = mode;
+ return mode;
+}
+
+
+static void flush_cache(void) {
+ typedef_resolve_cache = 0;
+ typedef_all_cache = 0;
+ typedef_qualified_cache = 0;
+}
+
+/* Initialize the scoping system */
+
+void SwigType_typesystem_init(void) {
+ if (global_scope)
+ Delete(global_scope);
+ if (scopes)
+ Delete(scopes);
+
+ current_scope = NewHash();
+ global_scope = current_scope;
+
+ Setattr(current_scope, "name", ""); /* No name for global scope */
+ current_typetab = NewHash();
+ Setattr(current_scope, "typetab", current_typetab);
+
+ current_symtab = 0;
+ scopes = NewHash();
+ Setattr(scopes, "", current_scope);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef()
+ *
+ * Defines a new typedef in the current scope. Returns -1 if the type name is
+ * already defined.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) {
+ /* Printf(stdout, "typedef %s %s\n", type, name); */
+ if (Getattr(current_typetab, name))
+ return -1; /* Already defined */
+ if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */
+ return 0;
+ }
+
+ /* Check if 'type' is already a scope. If so, we create an alias in the type
+ system for it. This is needed to make strange nested scoping problems work
+ correctly. */
+ {
+ Typetab *t = SwigType_find_scope(current_scope, type);
+ if (t) {
+ SwigType_new_scope(name);
+ SwigType_inherit_scope(t);
+ SwigType_pop_scope();
+ }
+ }
+ Setattr(current_typetab, name, type);
+ flush_cache();
+ return 0;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef_class()
+ *
+ * Defines a class in the current scope.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_typedef_class(const_String_or_char_ptr name) {
+ String *cname;
+ /* Printf(stdout,"class : '%s'\n", name); */
+ if (Getattr(current_typetab, name))
+ return -1; /* Already defined */
+ cname = NewString(name);
+ Setmeta(cname, "class", "1");
+ Setattr(current_typetab, cname, cname);
+ Delete(cname);
+ flush_cache();
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_scope_name()
+ *
+ * Returns the qualified scope name of a type table
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_scope_name(Typetab *ttab) {
+ String *qname = NewString(Getattr(ttab, "name"));
+ ttab = Getattr(ttab, "parent");
+ while (ttab) {
+ String *pname = Getattr(ttab, "name");
+ if (Len(pname)) {
+ Insert(qname, 0, "::");
+ Insert(qname, 0, pname);
+ }
+ ttab = Getattr(ttab, "parent");
+ }
+ return qname;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_new_scope()
+ *
+ * Creates a new scope
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_new_scope(const_String_or_char_ptr name) {
+ Typetab *s;
+ Hash *ttab;
+ String *qname;
+
+ if (!name) {
+ name = "<unnamed>";
+ }
+ s = NewHash();
+ Setattr(s, "name", name);
+ Setattr(s, "parent", current_scope);
+ ttab = NewHash();
+ Setattr(s, "typetab", ttab);
+
+ /* Build fully qualified name */
+ qname = SwigType_scope_name(s);
+#if 1
+ {
+ /* TODO: only do with templates? What happens with non-templates with code below? */
+ String *stripped_qname;
+ stripped_qname = SwigType_remove_global_scope_prefix(qname);
+ /* Use fully qualified name for hash key without unary scope prefix, qname may contain unary scope */
+ Setattr(scopes, stripped_qname, s);
+ Setattr(s, "qname", qname);
+ /*
+ Printf(stdout, "SwigType_new_scope stripped %s %s\n", qname, stripped_qname);
+ */
+ Delete(stripped_qname);
+ }
+#else
+ Printf(stdout, "SwigType_new_scope %s\n", qname);
+ Setattr(scopes, qname, s);
+ Setattr(s, "qname", qname);
+#endif
+ Delete(qname);
+
+ current_scope = s;
+ current_typetab = ttab;
+ current_symtab = 0;
+ flush_cache();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_inherit_scope()
+ *
+ * Makes the current scope inherit from another scope. This is used for both
+ * C++ class inheritance, namespaces, and namespace aliases.
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_inherit_scope(Typetab *scope) {
+ List *inherits;
+ int i, len;
+ inherits = Getattr(current_scope, "inherit");
+ if (!inherits) {
+ inherits = NewList();
+ Setattr(current_scope, "inherit", inherits);
+ Delete(inherits);
+ }
+ assert(scope != current_scope);
+
+ len = Len(inherits);
+ for (i = 0; i < len; i++) {
+ Node *n = Getitem(inherits, i);
+ if (n == scope)
+ return;
+ }
+ Append(inherits, scope);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_scope_alias()
+ *
+ * Creates a scope-alias.
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_scope_alias(String *aliasname, Typetab *ttab) {
+ String *q;
+ /* Printf(stdout,"alias: '%s' '%p'\n", aliasname, ttab); */
+ q = SwigType_scope_name(current_scope);
+ if (Len(q)) {
+ Append(q, "::");
+ }
+ Append(q, aliasname);
+ Setattr(scopes, q, ttab);
+ flush_cache();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_using_scope()
+ *
+ * Import another scope into this scope.
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_using_scope(Typetab *scope) {
+ SwigType_inherit_scope(scope);
+ {
+ List *ulist;
+ int i, len;
+ ulist = Getattr(current_scope, "using");
+ if (!ulist) {
+ ulist = NewList();
+ Setattr(current_scope, "using", ulist);
+ Delete(ulist);
+ }
+ assert(scope != current_scope);
+ len = Len(ulist);
+ for (i = 0; i < len; i++) {
+ Typetab *n = Getitem(ulist, i);
+ if (n == scope)
+ return;
+ }
+ Append(ulist, scope);
+ }
+ flush_cache();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_pop_scope()
+ *
+ * Pop off the last scope and perform a merge operation. Returns the hash
+ * table for the scope that was popped off.
+ * ----------------------------------------------------------------------------- */
+
+Typetab *SwigType_pop_scope(void) {
+ Typetab *t, *old = current_scope;
+ t = Getattr(current_scope, "parent");
+ if (!t)
+ t = global_scope;
+ current_scope = t;
+ current_typetab = Getattr(t, "typetab");
+ current_symtab = Getattr(t, "symtab");
+ flush_cache();
+ return old;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_set_scope()
+ *
+ * Set the scope. Returns the old scope.
+ * ----------------------------------------------------------------------------- */
+
+Typetab *SwigType_set_scope(Typetab *t) {
+ Typetab *old = current_scope;
+ if (!t)
+ t = global_scope;
+ current_scope = t;
+ current_typetab = Getattr(t, "typetab");
+ current_symtab = Getattr(t, "symtab");
+ flush_cache();
+ return old;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_attach_symtab()
+ *
+ * Attaches a symbol table to a type scope
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_attach_symtab(Symtab *sym) {
+ Setattr(current_scope, "symtab", sym);
+ current_symtab = sym;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_print_scope()
+ *
+ * Debugging function for printing out current scope
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_print_scope(void) {
+ Hash *ttab;
+ Iterator i, j;
+
+ Printf(stdout, "SCOPES start =======================================\n");
+ for (i = First(scopes); i.key; i = Next(i)) {
+ Printf(stdout, "-------------------------------------------------------------\n");
+ ttab = Getattr(i.item, "typetab");
+
+ Printf(stdout, "Type scope '%s' (%p)\n", i.key, i.item);
+ {
+ List *inherit = Getattr(i.item, "inherit");
+ if (inherit) {
+ Iterator j;
+ for (j = First(inherit); j.item; j = Next(j)) {
+ Printf(stdout, " Inherits from '%s' (%p)\n", Getattr(j.item, "qname"), j.item);
+ }
+ }
+ }
+ for (j = First(ttab); j.key; j = Next(j)) {
+ Printf(stdout, "%40s -> %s\n", j.key, j.item);
+ }
+ }
+ Printf(stdout, "SCOPES finish =======================================\n");
+}
+
+static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
+ Typetab *ss;
+ Typetab *s_orig = s;
+ String *nnameprefix = 0;
+ static int check_parent = 1;
+ int is_template = 0;
+
+ if (Getmark(s))
+ return 0;
+ Setmark(s, 1);
+
+ is_template = SwigType_istemplate(nameprefix);
+ if (is_template) {
+ nnameprefix = SwigType_typedef_resolve_all(nameprefix);
+ nameprefix = nnameprefix;
+ }
+
+ ss = s;
+ while (ss) {
+ String *full;
+ String *qname = Getattr(ss, "qname");
+ if (qname) {
+ full = NewStringf("%s::%s", qname, nameprefix);
+ } else {
+ full = NewString(nameprefix);
+ }
+ s = Getattr(scopes, full);
+ if (!s && is_template) {
+ /* try look up scope with all the unary scope operators within the template parameter list removed */
+ SwigType *full_stripped = SwigType_remove_global_scope_prefix(full);
+ s = Getattr(scopes, full_stripped);
+ Delete(full_stripped);
+ }
+ Delete(full);
+ if (s) {
+ if (nnameprefix)
+ Delete(nnameprefix);
+ Setmark(s_orig, 0);
+ return s;
+ }
+ if (!s) {
+ /* Check inheritance */
+ List *inherit;
+ inherit = Getattr(ss, "using");
+ if (inherit) {
+ Typetab *ttab;
+ int i, len;
+ len = Len(inherit);
+ for (i = 0; i < len; i++) {
+ int oldcp = check_parent;
+ ttab = Getitem(inherit, i);
+ check_parent = 0;
+ s = SwigType_find_scope(ttab, nameprefix);
+ check_parent = oldcp;
+ if (s) {
+ if (nnameprefix)
+ Delete(nnameprefix);
+ Setmark(s_orig, 0);
+ return s;
+ }
+ }
+ }
+ }
+ if (!check_parent)
+ break;
+ ss = Getattr(ss, "parent");
+ }
+ if (nnameprefix)
+ Delete(nnameprefix);
+ Setmark(s_orig, 0);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * typedef_resolve()
+ *
+ * Resolves a typedef and returns a new type string. Returns 0 if there is no
+ * typedef mapping. base is a name without qualification.
+ * Internal function.
+ * ----------------------------------------------------------------------------- */
+
+static Typetab *resolved_scope = 0;
+
+/* Internal function */
+
+static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) {
+ Hash *ttab;
+ SwigType *type = 0;
+ List *inherit;
+ Typetab *parent;
+
+ /* if (!s) return 0; *//* now is checked below */
+ /* Printf(stdout,"Typetab %s : %s\n", Getattr(s,"name"), base); */
+
+ if (!Getmark(s)) {
+ Setmark(s, 1);
+
+ ttab = Getattr(s, "typetab");
+ type = Getattr(ttab, base);
+ if (type) {
+ resolved_scope = s;
+ Setmark(s, 0);
+ } else {
+ /* Hmmm. Not found in my scope. It could be in an inherited scope */
+ inherit = Getattr(s, "inherit");
+ if (inherit) {
+ int i, len;
+ len = Len(inherit);
+ for (i = 0; i < len; i++) {
+ type = _typedef_resolve(Getitem(inherit, i), base, 0);
+ if (type) {
+ Setmark(s, 0);
+ break;
+ }
+ }
+ }
+ if (!type) {
+ /* Hmmm. Not found in my scope. check parent */
+ if (look_parent) {
+ parent = Getattr(s, "parent");
+ type = parent ? _typedef_resolve(parent, base, 1) : 0;
+ }
+ }
+ Setmark(s, 0);
+ }
+ }
+ return type;
+}
+
+/* -----------------------------------------------------------------------------
+ * template_parameters_resolve()
+ *
+ * For use with templates only. Attempts to resolve one template parameter.
+ *
+ * If one of the template parameters can be resolved, the type is returned with
+ * just the one parameter resolved and the remaining parameters left as is.
+ * If none of the template parameters can be resolved, zero is returned.
+ * ----------------------------------------------------------------------------- */
+
+static String *template_parameters_resolve(const String *base) {
+ List *tparms;
+ String *suffix;
+ String *type;
+ int i, sz;
+ int rep = 0;
+ type = SwigType_templateprefix(base);
+ suffix = SwigType_templatesuffix(base);
+ Append(type, "<(");
+ tparms = SwigType_parmlist(base);
+ sz = Len(tparms);
+ for (i = 0; i < sz; i++) {
+ SwigType *tpr;
+ SwigType *tp = Getitem(tparms, i);
+ if (!rep) {
+ tpr = SwigType_typedef_resolve(tp);
+ } else {
+ tpr = 0;
+ }
+ if (tpr) {
+ Append(type, tpr);
+ Delete(tpr);
+ rep = 1;
+ } else {
+ Append(type, tp);
+ }
+ if ((i + 1) < sz)
+ Append(type, ",");
+ }
+ if (rep) {
+ Append(type, ")>");
+ Append(type, suffix);
+ } else {
+ Delete(type);
+ type = 0;
+ }
+ Delete(suffix);
+ Delete(tparms);
+ return type;
+}
+
+static SwigType *typedef_resolve(Typetab *s, String *base) {
+ return _typedef_resolve(s, base, 1);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef_resolve()
+ *
+ * Given a type declaration, this function looks to reduce/resolve the type via a
+ * typedef (including via C++ using declarations).
+ *
+ * If it is able to find a typedef, the resolved type is returned. If no typedef
+ * is found NULL is returned. The type name is resolved in the current scope.
+ * The type returned is not always fully qualified for the global scope, it is
+ * valid for use in the current scope. If the current scope is global scope, a
+ * fully qualified type should be returned.
+ *
+ * Some additional notes are in Doc/Manual/Extending.html.
+ * ----------------------------------------------------------------------------- */
+
+/* #define SWIG_DEBUG */
+SwigType *SwigType_typedef_resolve(const SwigType *t) {
+ String *base;
+ String *type = 0;
+ String *r = 0;
+ Typetab *s;
+ Hash *ttab;
+ String *namebase = 0;
+ String *nameprefix = 0, *rnameprefix = 0;
+ int newtype = 0;
+
+ resolved_scope = 0;
+
+#ifdef SWIG_TYPEDEF_RESOLVE_CACHE
+ if (!typedef_resolve_cache) {
+ typedef_resolve_cache = NewHash();
+ }
+ r = Getattr(typedef_resolve_cache, t);
+ if (r) {
+ resolved_scope = Getmeta(r, "scope");
+ return Copy(r);
+ }
+#endif
+
+ base = SwigType_base(t);
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "base = '%s' t='%s'\n", base, t);
+#endif
+
+ if (SwigType_issimple(base)) {
+ s = current_scope;
+ ttab = current_typetab;
+ if (strncmp(Char(base), "::", 2) == 0) {
+ s = global_scope;
+ ttab = Getattr(s, "typetab");
+ Delitem(base, 0);
+ Delitem(base, 0);
+ }
+ /* Do a quick check in the local scope */
+ type = Getattr(ttab, base);
+ if (type) {
+ resolved_scope = s;
+ }
+ if (!type) {
+ /* Didn't find in this scope. We need to do a little more searching */
+ if (Swig_scopename_check(base)) {
+ /* A qualified name. */
+ Swig_scopename_split(base, &nameprefix, &namebase);
+#ifdef SWIG_DEBUG
+ Printf(stdout, "nameprefix = '%s'\n", nameprefix);
+#endif
+ if (nameprefix) {
+ rnameprefix = SwigType_typedef_resolve(nameprefix);
+ if(rnameprefix != NULL) {
+#ifdef SWIG_DEBUG
+ Printf(stdout, "nameprefix '%s' is a typedef to '%s'\n", nameprefix, rnameprefix);
+#endif
+ type = Copy(namebase);
+ Insert(type, 0, "::");
+ Insert(type, 0, rnameprefix);
+ if (strncmp(Char(type), "::", 2) == 0) {
+ Delitem(type, 0);
+ Delitem(type, 0);
+ }
+ newtype = 1;
+ } else {
+ /* Name had a prefix on it. See if we can locate the proper scope for it */
+ String *rnameprefix = template_parameters_resolve(nameprefix);
+ nameprefix = rnameprefix ? Copy(rnameprefix) : nameprefix;
+ Delete(rnameprefix);
+ s = SwigType_find_scope(s, nameprefix);
+
+ /* Couldn't locate a scope for the type. */
+ if (!s) {
+ Delete(base);
+ Delete(namebase);
+ Delete(nameprefix);
+ r = 0;
+ goto return_result;
+ }
+ /* Try to locate the name starting in the scope */
+#ifdef SWIG_DEBUG
+ Printf(stdout, "namebase = '%s'\n", namebase);
+#endif
+ type = typedef_resolve(s, namebase);
+ if (type && resolved_scope) {
+ /* we need to look for the resolved type, this will also
+ fix the resolved_scope if 'type' and 'namebase' are
+ declared in different scopes */
+ String *rtype = 0;
+ rtype = typedef_resolve(resolved_scope, type);
+ if (rtype)
+ type = rtype;
+ }
+#ifdef SWIG_DEBUG
+ Printf(stdout, "%s type = '%s'\n", Getattr(s, "name"), type);
+#endif
+ if ((type) && (!Swig_scopename_check(type)) && resolved_scope) {
+ Typetab *rtab = resolved_scope;
+ String *qname = Getattr(resolved_scope, "qname");
+ /* If qualified *and* the typename is defined from the resolved scope, we qualify */
+ if ((qname) && typedef_resolve(resolved_scope, type)) {
+ type = Copy(type);
+ Insert(type, 0, "::");
+ Insert(type, 0, qname);
+#ifdef SWIG_DEBUG
+ Printf(stdout, "qual %s \n", type);
+#endif
+ newtype = 1;
+ }
+ resolved_scope = rtab;
+ }
+ }
+ } else {
+ /* Name is unqualified. */
+ type = typedef_resolve(s, base);
+ }
+ } else {
+ /* Name is unqualified. */
+ type = typedef_resolve(s, base);
+ }
+ }
+
+ if (!type && SwigType_istemplate(base)) {
+ String *tprefix = SwigType_templateprefix(base);
+ String *rtprefix = SwigType_typedef_resolve(tprefix);
+ /* We're looking for a using declaration on the template prefix to resolve the template prefix
+ * in another scope. Using declaration do not have template parameters. */
+ if (rtprefix && !SwigType_istemplate(rtprefix)) {
+ String *tsuffix = SwigType_templatesuffix(base);
+ String *targs = SwigType_templateargs(base);
+ type = NewString(rtprefix);
+ newtype = 1;
+ Append(type, targs);
+ Append(type, tsuffix);
+ Delete(targs);
+ Delete(tsuffix);
+ Delete(rtprefix);
+ }
+ Delete(tprefix);
+ }
+
+ if (type && (Equal(base, type))) {
+ if (newtype)
+ Delete(type);
+ Delete(base);
+ Delete(namebase);
+ Delete(nameprefix);
+ r = 0;
+ goto return_result;
+ }
+
+ /* If the type is a template, and no typedef was found, we need to check the
+ template arguments one by one to see if they can be resolved. */
+
+ if (!type && SwigType_istemplate(base)) {
+ newtype = 1;
+ type = template_parameters_resolve(base);
+ }
+ Delete(namebase);
+ Delete(nameprefix);
+ } else {
+ if (SwigType_isfunction(base)) {
+ List *parms;
+ int i, sz;
+ int rep = 0;
+ type = NewString("f(");
+ newtype = 1;
+ parms = SwigType_parmlist(base);
+ sz = Len(parms);
+ for (i = 0; i < sz; i++) {
+ SwigType *tpr;
+ SwigType *tp = Getitem(parms, i);
+ if (!rep) {
+ tpr = SwigType_typedef_resolve(tp);
+ } else {
+ tpr = 0;
+ }
+ if (tpr) {
+ Append(type, tpr);
+ Delete(tpr);
+ rep = 1;
+ } else {
+ Append(type, tp);
+ }
+ if ((i + 1) < sz)
+ Append(type, ",");
+ }
+ Append(type, ").");
+ Delete(parms);
+ if (!rep) {
+ Delete(type);
+ type = 0;
+ }
+ } else if (SwigType_ismemberpointer(base)) {
+ String *rt;
+ String *mtype = SwigType_parm(base);
+ rt = SwigType_typedef_resolve(mtype);
+ if (rt) {
+ type = NewStringf("m(%s).", rt);
+ newtype = 1;
+ Delete(rt);
+ }
+ Delete(mtype);
+ } else {
+ type = 0;
+ }
+ }
+ r = SwigType_prefix(t);
+ if (!type) {
+ if (r && Len(r)) {
+ char *cr = Char(r);
+ if ((strstr(cr, "f(") || (strstr(cr, "m(")))) {
+ SwigType *rt = SwigType_typedef_resolve(r);
+ if (rt) {
+ Delete(r);
+ Append(rt, base);
+ Delete(base);
+ r = rt;
+ goto return_result;
+ }
+ }
+ }
+ Delete(r);
+ Delete(base);
+ r = 0;
+ goto return_result;
+ }
+ Delete(base);
+
+ /* If 'type' is an array, then the right-most qualifier in 'r' should
+ be added to 'type' after the array qualifier, so that given
+ a(7).q(volatile).double myarray // typedef volatile double[7] myarray;
+ the type
+ q(const).myarray // const myarray
+ becomes
+ a(7).q(const volatile).double // const volatile double[7]
+ and NOT
+ q(const).a(7).q(volatile).double // non-sensical type
+ */
+ if (r && Len(r) && SwigType_isarray(type)) {
+ List *r_elem;
+ String *r_qual;
+ int r_sz;
+ r_elem = SwigType_split(r);
+ r_sz = Len(r_elem);
+ r_qual = Getitem(r_elem, r_sz-1);
+ if (SwigType_isqualifier(r_qual)) {
+ String *new_r;
+ String *new_type;
+ List *type_elem;
+ String *type_qual;
+ String *r_qual_arg;
+ int i, type_sz;
+
+ type_elem = SwigType_split(type);
+ type_sz = Len(type_elem);
+
+ for (i = 0; i < type_sz; ++i) {
+ String *e = Getitem(type_elem, i);
+ if (!SwigType_isarray(e))
+ break;
+ }
+ type_qual = Copy(Getitem(type_elem, i));
+ r_qual_arg = SwigType_parm(r_qual);
+ SwigType_add_qualifier(type_qual, r_qual_arg);
+ Delete(r_qual_arg);
+ Setitem(type_elem, i, type_qual);
+
+ new_r = NewStringEmpty();
+ for (i = 0; i < r_sz-1; ++i) {
+ Append(new_r, Getitem(r_elem, i));
+ }
+ new_type = NewStringEmpty();
+ for (i = 0; i < type_sz; ++i) {
+ Append(new_type, Getitem(type_elem, i));
+ }
+#ifdef SWIG_DEBUG
+ Printf(stdout, "r+type='%s%s' new_r+new_type='%s%s'\n", r, type, new_r, new_type);
+#endif
+
+ Delete(r);
+ r = new_r;
+ newtype = 1;
+ type = new_type;
+ Delete(type_elem);
+ }
+ Delete(r_elem);
+ }
+
+ Append(r, type);
+ if (newtype) {
+ Delete(type);
+ }
+
+return_result:
+#ifdef SWIG_TYPEDEF_RESOLVE_CACHE
+ {
+ String *key = NewString(t);
+ if (r) {
+ SwigType *r1;
+ Setattr(typedef_resolve_cache, key, r);
+ Setmeta(r, "scope", resolved_scope);
+ r1 = Copy(r);
+ Delete(r);
+ r = r1;
+ }
+ Delete(key);
+ }
+#endif
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef_resolve_all()
+ *
+ * Fully resolve a type down to its most basic datatype
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
+ SwigType *n;
+ SwigType *r;
+ int count = 0;
+
+ /* Check to see if the typedef resolve has been done before by checking the cache */
+ if (!typedef_all_cache) {
+ typedef_all_cache = NewHash();
+ }
+ r = Getattr(typedef_all_cache, t);
+ if (r) {
+ return Copy(r);
+ }
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "SwigType_typedef_resolve_all start ... %s\n", t);
+#endif
+ /* Recursively resolve the typedef */
+ r = NewString(t);
+ while ((n = SwigType_typedef_resolve(r))) {
+ Delete(r);
+ r = n;
+ if (++count >= 512) {
+ Swig_error(Getfile(t), Getline(t), "Recursive typedef detected resolving '%s' to '%s' to '%s' and so on...\n", SwigType_str(t, 0), SwigType_str(SwigType_typedef_resolve(t), 0), SwigType_str(SwigType_typedef_resolve(SwigType_typedef_resolve(t)), 0));
+ break;
+ }
+ }
+
+ /* Add the typedef to the cache for next time it is looked up */
+ {
+ String *key;
+ SwigType *rr = Copy(r);
+ key = NewString(t);
+ Setattr(typedef_all_cache, key, rr);
+ Delete(key);
+ Delete(rr);
+ }
+#ifdef SWIG_DEBUG
+ Printf(stdout, "SwigType_typedef_resolve_all end === %s => %s\n", t, r);
+#endif
+ return r;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef_qualified()
+ *
+ * Given a type declaration, this function tries to fully qualify it so that the
+ * resulting type can be used in the global scope. The type name is resolved in
+ * the current scope.
+ *
+ * It provides a fully qualified name, not necessarily a fully expanded name.
+ * When a using declaration or using directive is found the type may not be fully
+ * expanded, but it will be resolved and fully qualified for use in the global scope.
+ *
+ * This function is for looking up scopes to qualify a type. It does not resolve
+ * C typedefs, it just qualifies them. See SwigType_typedef_resolve for resolving.
+ *
+ * If the unary scope operator (::) is used as a prefix to the type to denote global
+ * scope, it is left in place.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_typedef_qualified(const SwigType *t) {
+ List *elements;
+ String *result;
+ int i, len;
+
+ if (!typedef_qualified_cache)
+ typedef_qualified_cache = NewHash();
+ result = Getattr(typedef_qualified_cache, t);
+ if (result) {
+ String *rc = Copy(result);
+ return rc;
+ }
+
+ result = NewStringEmpty();
+ elements = SwigType_split(t);
+ len = Len(elements);
+ for (i = 0; i < len; i++) {
+ String *ty = 0;
+ String *e = Getitem(elements, i);
+ if (SwigType_issimple(e)) {
+ if (!SwigType_istemplate(e)) {
+ String *isenum = 0;
+ if (SwigType_isenum(e)) {
+ isenum = NewString("enum ");
+ ty = NewString(Char(e) + 5);
+ e = ty;
+ }
+ resolved_scope = 0;
+ if (typedef_resolve(current_scope, e) && resolved_scope) {
+ /* resolved_scope contains the scope that actually resolved the symbol */
+ String *qname = Getattr(resolved_scope, "qname");
+ if (qname) {
+ Insert(e, 0, "::");
+ Insert(e, 0, qname);
+ }
+ } else {
+ if (Swig_scopename_check(e)) {
+ String *qlast;
+ String *qname;
+ Swig_scopename_split(e, &qname, &qlast);
+ if (qname) {
+ String *tqname = SwigType_typedef_qualified(qname);
+ Clear(e);
+ Printf(e, "%s::%s", tqname, qlast);
+ Delete(qname);
+ Delete(tqname);
+ }
+ Delete(qlast);
+
+ /* Automatic template instantiation might go here??? */
+ } else {
+ /* It's a bare name. It's entirely possible, that the
+ name is part of a namespace. We'll check this by unrolling
+ out of the current scope */
+
+ Typetab *cs = current_scope;
+ if (cs) {
+ Typetab *found_scope = SwigType_find_scope(cs, e);
+ if (found_scope) {
+ String *qs = SwigType_scope_name(found_scope);
+ Clear(e);
+ Append(e, qs);
+ Delete(qs);
+ }
+ }
+ }
+ }
+ if (isenum) {
+ Insert(e, 0, isenum);
+ Delete(isenum);
+ }
+ } else {
+ /* Template. We need to qualify template parameters as well as the template itself */
+ String *tprefix, *qprefix;
+ String *tsuffix;
+ Iterator pi;
+ Parm *p;
+ List *parms;
+ ty = Swig_symbol_template_deftype(e, current_symtab);
+ e = ty;
+ parms = SwigType_parmlist(e);
+ tprefix = SwigType_templateprefix(e);
+ tsuffix = SwigType_templatesuffix(e);
+ qprefix = SwigType_typedef_qualified(tprefix);
+ Append(qprefix, "<(");
+ pi = First(parms);
+ while ((p = pi.item)) {
+ /* TODO: the logic here should be synchronised with that in symbol_template_qualify() in symbol.c */
+ String *qt = SwigType_typedef_qualified(p);
+ if (Equal(qt, p)) { /* && (!Swig_scopename_check(qt))) */
+ /* No change in value. It is entirely possible that the parameter is an integer value.
+ If there is a symbol table associated with this scope, we're going to check for this */
+
+ if (current_symtab) {
+ Node *lastnode = 0;
+ String *value = Copy(p);
+ while (1) {
+ Node *n = Swig_symbol_clookup(value, current_symtab);
+ if (n == lastnode)
+ break;
+ lastnode = n;
+ if (n) {
+ char *ntype = Char(nodeType(n));
+ if (strcmp(ntype, "enumitem") == 0) {
+ /* An enum item. Generate a fully qualified name */
+ String *qn = Swig_symbol_qualified(n);
+ if (Len(qn)) {
+ Append(qn, "::");
+ Append(qn, Getattr(n, "name"));
+ Delete(value);
+ value = qn;
+ continue;
+ } else {
+ Delete(qn);
+ break;
+ }
+ } else if ((strcmp(ntype, "cdecl") == 0) && (Getattr(n, "value"))) {
+ Delete(value);
+ value = Copy(Getattr(n, "value"));
+ continue;
+ }
+ }
+ break;
+ }
+ Append(qprefix, value);
+ Delete(value);
+ } else {
+ Append(qprefix, p);
+ }
+ } else {
+ Append(qprefix, qt);
+ }
+ Delete(qt);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(qprefix, ",");
+ }
+ }
+ Append(qprefix, ")>");
+ Append(qprefix, tsuffix);
+ Delete(tsuffix);
+ Clear(e);
+ Append(e, qprefix);
+ Delete(tprefix);
+ Delete(qprefix);
+ Delete(parms);
+ }
+ Append(result, e);
+ Delete(ty);
+ } else if (SwigType_isfunction(e)) {
+ List *parms = SwigType_parmlist(e);
+ String *s = NewString("f(");
+ Iterator pi;
+ pi = First(parms);
+ while (pi.item) {
+ String *pq = SwigType_typedef_qualified(pi.item);
+ Append(s, pq);
+ Delete(pq);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(s, ",");
+ }
+ }
+ Append(s, ").");
+ Append(result, s);
+ Delete(s);
+ Delete(parms);
+ } else if (SwigType_isarray(e)) {
+ String *ndim;
+ String *dim = SwigType_parm(e);
+ ndim = Swig_symbol_string_qualify(dim, 0);
+ Printf(result, "a(%s).", ndim);
+ Delete(dim);
+ Delete(ndim);
+ } else {
+ Append(result, e);
+ }
+ }
+ Delete(elements);
+ {
+ String *key, *cresult;
+ key = NewString(t);
+ cresult = NewString(result);
+ Setattr(typedef_qualified_cache, key, cresult);
+ Delete(key);
+ Delete(cresult);
+ }
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_istypedef()
+ *
+ * Checks a typename to see if it is a typedef.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_istypedef(const SwigType *t) {
+ String *type;
+
+ type = SwigType_typedef_resolve(t);
+ if (type) {
+ Delete(type);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef_using()
+ *
+ * Processes a 'using' declaration to import types from one scope into another.
+ * Name is a qualified name like A::B.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_typedef_using(const_String_or_char_ptr name) {
+ String *base;
+ String *td;
+ String *prefix;
+ Typetab *s;
+ Typetab *tt = 0;
+
+ String *defined_name = 0;
+
+ /* Printf(stdout, "using %s\n", name); */
+
+ if (!Swig_scopename_check(name))
+ return -1; /* Not properly qualified */
+ base = Swig_scopename_last(name);
+
+ /* See if the base is already defined in this scope */
+ if (Getattr(current_typetab, base)) {
+ Delete(base);
+ return -1;
+ }
+
+ /* See if the using name is a scope */
+ /* tt = SwigType_find_scope(current_scope,name);
+ Printf(stdout,"tt = %p, name = '%s'\n", tt, name); */
+
+ /* We set up a typedef B --> A::B */
+ Setattr(current_typetab, base, name);
+
+ /* Find the scope name where the symbol is defined */
+ td = SwigType_typedef_resolve(name);
+ /* Printf(stdout,"td = '%s' %p\n", td, resolved_scope); */
+ if (resolved_scope) {
+ defined_name = Getattr(resolved_scope, "qname");
+ if (defined_name) {
+ defined_name = Copy(defined_name);
+ Append(defined_name, "::");
+ Append(defined_name, base);
+ /* Printf(stdout,"defined_name = '%s'\n", defined_name); */
+ tt = SwigType_find_scope(current_scope, defined_name);
+ }
+ }
+ if (td)
+ Delete(td);
+
+
+ /* Figure out the scope the using directive refers to */
+ {
+ prefix = Swig_scopename_prefix(name);
+ if (prefix) {
+ s = SwigType_find_scope(current_scope, prefix);
+ if (s) {
+ Hash *ttab = Getattr(s, "typetab");
+ if (!Getattr(ttab, base) && defined_name) {
+ Setattr(ttab, base, defined_name);
+ }
+ }
+ }
+ }
+
+ if (tt) {
+ /* Using directive had its own scope. We need to create a new scope for it */
+ SwigType_new_scope(base);
+ SwigType_inherit_scope(tt);
+ SwigType_pop_scope();
+ }
+
+ if (defined_name)
+ Delete(defined_name);
+ Delete(prefix);
+ Delete(base);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_isclass()
+ *
+ * Determines if a type defines a class or not. A class is defined by
+ * its type-table entry maps to itself. Note: a pointer to a class is not
+ * a class.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_isclass(const SwigType *t) {
+ SwigType *qty, *qtys;
+ int isclass = 0;
+
+ qty = SwigType_typedef_resolve_all(t);
+ qtys = SwigType_strip_qualifiers(qty);
+ if (SwigType_issimple(qtys)) {
+ String *td = SwigType_typedef_resolve(qtys);
+ if (td) {
+ Delete(td);
+ }
+ if (resolved_scope) {
+ isclass = 1;
+ }
+ /* Hmmm. Not a class. If a template, it might be uninstantiated */
+ if (!isclass) {
+ String *tp = SwigType_istemplate_templateprefix(qtys);
+ if (tp && Strcmp(tp, t) != 0) {
+ isclass = SwigType_isclass(tp);
+ }
+ Delete(tp);
+ }
+ }
+ Delete(qty);
+ Delete(qtys);
+ return isclass;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_type()
+ *
+ * Returns an integer code describing the datatype. This is only used for
+ * compatibility with SWIG1.1 language modules and is likely to go away once
+ * everything is based on typemaps.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_type(const SwigType *t) {
+ char *c;
+ /* Check for the obvious stuff */
+ c = Char(t);
+
+ if (strncmp(c, "p.", 2) == 0) {
+ if (SwigType_type(c + 2) == T_CHAR)
+ return T_STRING;
+ else if (SwigType_type(c + 2) == T_WCHAR)
+ return T_WSTRING;
+ else
+ return T_POINTER;
+ }
+ if (strncmp(c, "a(", 2) == 0)
+ return T_ARRAY;
+ if (strncmp(c, "r.", 2) == 0)
+ return T_REFERENCE;
+ if (strncmp(c, "z.", 2) == 0)
+ return T_RVALUE_REFERENCE;
+ if (strncmp(c, "m(", 2) == 0)
+ return T_MPOINTER;
+ if (strncmp(c, "q(", 2) == 0) {
+ while (*c && (*c != '.'))
+ c++;
+ if (*c)
+ return SwigType_type(c + 1);
+ return T_ERROR;
+ }
+ if (strncmp(c, "f(", 2) == 0)
+ return T_FUNCTION;
+
+ /* Look for basic types */
+ if (strcmp(c, "int") == 0)
+ return T_INT;
+ if (strcmp(c, "long") == 0)
+ return T_LONG;
+ if (strcmp(c, "short") == 0)
+ return T_SHORT;
+ if (strcmp(c, "unsigned") == 0)
+ return T_UINT;
+ if (strcmp(c, "unsigned short") == 0)
+ return T_USHORT;
+ if (strcmp(c, "unsigned long") == 0)
+ return T_ULONG;
+ if (strcmp(c, "unsigned int") == 0)
+ return T_UINT;
+ if (strcmp(c, "char") == 0)
+ return T_CHAR;
+ if (strcmp(c, "signed char") == 0)
+ return T_SCHAR;
+ if (strcmp(c, "unsigned char") == 0)
+ return T_UCHAR;
+ if (strcmp(c, "wchar_t") == 0)
+ return T_WCHAR;
+ if (strcmp(c, "float") == 0)
+ return T_FLOAT;
+ if (strcmp(c, "double") == 0)
+ return T_DOUBLE;
+ if (strcmp(c, "long double") == 0)
+ return T_LONGDOUBLE;
+ if (!cparse_cplusplus && (strcmp(c, "float _Complex") == 0))
+ return T_FLTCPLX;
+ if (!cparse_cplusplus && (strcmp(c, "double _Complex") == 0))
+ return T_DBLCPLX;
+ if (!cparse_cplusplus && (strcmp(c, "_Complex") == 0))
+ return T_COMPLEX;
+ if (strcmp(c, "void") == 0)
+ return T_VOID;
+ if (strcmp(c, "bool") == 0)
+ return T_BOOL;
+ if (strcmp(c, "long long") == 0)
+ return T_LONGLONG;
+ if (strcmp(c, "unsigned long long") == 0)
+ return T_ULONGLONG;
+ if (strncmp(c, "enum ", 5) == 0)
+ return T_INT;
+ if (strcmp(c, "auto") == 0)
+ return T_AUTO;
+
+ if (strcmp(c, "v(...)") == 0)
+ return T_VARARGS;
+ /* Hmmm. Unknown type */
+ if (SwigType_istypedef(t)) {
+ int r;
+ SwigType *nt = SwigType_typedef_resolve(t);
+ r = SwigType_type(nt);
+ Delete(nt);
+ return r;
+ }
+ return T_USER;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_alttype()
+ *
+ * Returns the alternative value type needed in C++ for class value
+ * types. When swig is not sure about using a plain $ltype value,
+ * since the class doesn't have a default constructor, or it can't be
+ * assigned, you will get back 'SwigValueWrapper<type >'.
+ *
+ * This is the default behavior unless:
+ *
+ * 1.- swig detects a default_constructor and 'setallocate:default_constructor'
+ * attribute.
+ *
+ * 2.- swig doesn't mark 'type' as non-assignable.
+ *
+ * 3.- the user specifies that the value wrapper is not needed by using
+ * %feature("novaluewrapper") like so:
+ *
+ * %feature("novaluewrapper") MyOpaqueClass;
+ * class MyOpaqueClass;
+ *
+ * The user can also force the use of the value wrapper with
+ * %feature("valuewrapper").
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_alttype(const SwigType *t, int local_tmap) {
+ Node *n;
+ SwigType *w = 0;
+ int use_wrapper = 0;
+ SwigType *td = 0;
+
+ if (!cparse_cplusplus)
+ return 0;
+
+ if (value_wrapper_mode == 0) {
+ /* old partial use of SwigValueTypes, it can fail for opaque types */
+ if (local_tmap)
+ return 0;
+ if (SwigType_isclass(t)) {
+ SwigType *ftd = SwigType_typedef_resolve_all(t);
+ td = SwigType_strip_qualifiers(ftd);
+ Delete(ftd);
+ n = Swig_symbol_clookup(td, 0);
+ if (n) {
+ if (GetFlag(n, "feature:valuewrapper")) {
+ use_wrapper = 1;
+ } else {
+ if (Checkattr(n, "nodeType", "class")
+ && (!Getattr(n, "allocate:default_constructor")
+ || (Getattr(n, "allocate:noassign")))) {
+ use_wrapper = !GetFlag(n, "feature:novaluewrapper") || GetFlag(n, "feature:nodefault");
+ }
+ }
+ } else {
+ if (SwigType_issimple(td) && SwigType_istemplate(td)) {
+ use_wrapper = 1;
+ }
+ }
+ }
+ } else {
+ /* safe use of SwigValueTypes, it can fail with some typemaps */
+ SwigType *ftd = SwigType_typedef_resolve_all(t);
+ td = SwigType_strip_qualifiers(ftd);
+ Delete(ftd);
+ if (SwigType_type(td) == T_USER) {
+ use_wrapper = 1;
+ n = Swig_symbol_clookup(td, 0);
+ if (n) {
+ if ((Checkattr(n, "nodeType", "class")
+ && !Getattr(n, "allocate:noassign")
+ && (Getattr(n, "allocate:default_constructor")))
+ || (GetFlag(n, "feature:novaluewrapper"))) {
+ use_wrapper = GetFlag(n, "feature:valuewrapper");
+ }
+ }
+ }
+ }
+
+ if (use_wrapper) {
+ /* Need a space before the type in case it starts "::" (since the <:
+ * token is a digraph for [ in C++. Also need a space after the
+ * type in case it ends with ">" since then we form the token ">>".
+ */
+ w = NewStringf("SwigValueWrapper< %s >", td);
+ }
+ Delete(td);
+ return w;
+}
+
+/* ----------------------------------------------------------------------------
+ * * * * WARNING * * * ***
+ * ***
+ * Don't even think about modifying anything below this line unless you ***
+ * are completely on top of *EVERY* subtle aspect of the C++ type system ***
+ * and you are prepared to suffer endless hours of agony trying to ***
+ * debug the SWIG run-time type checker after you break it. ***
+ * ------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * SwigType_remember()
+ *
+ * This function "remembers" a datatype that was used during wrapper code generation
+ * so that a type-checking table can be generated later on. It is up to the language
+ * modules to actually call this function--it is not done automatically.
+ *
+ * Type tracking is managed through two separate hash tables. The hash 'r_mangled'
+ * is mapping between mangled type names (used in the target language) and
+ * fully-resolved C datatypes used in the source input. The second hash 'r_resolved'
+ * is the inverse mapping that maps fully-resolved C datatypes to all of the mangled
+ * names in the scripting languages. For example, consider the following set of
+ * typedef declarations:
+ *
+ * typedef double Real;
+ * typedef double Float;
+ * typedef double Point[3];
+ *
+ * Now, suppose that the types 'double *', 'Real *', 'Float *', 'double[3]', and
+ * 'Point' were used in an interface file and "remembered" using this function.
+ * The hash tables would look like this:
+ *
+ * r_mangled {
+ * _p_double : [ p.double, a(3).double ]
+ * _p_Real : [ p.double ]
+ * _p_Float : [ p.double ]
+ * _Point : [ a(3).double ]
+ *
+ * r_resolved {
+ * p.double : [ _p_double, _p_Real, _p_Float ]
+ * a(3).double : [ _p_double, _Point ]
+ * }
+ *
+ * Together these two hash tables can be used to determine type-equivalency between
+ * mangled typenames. To do this, we view the two hash tables as a large graph and
+ * compute the transitive closure.
+ * ----------------------------------------------------------------------------- */
+
+static Hash *r_mangled = 0; /* Hash mapping mangled types to fully resolved types */
+static Hash *r_resolved = 0; /* Hash mapping resolved types to mangled types */
+static Hash *r_ltype = 0; /* Hash mapping mangled names to their local c type */
+static Hash *r_clientdata = 0; /* Hash mapping resolved types to client data */
+static Hash *r_mangleddata = 0; /* Hash mapping mangled types to client data */
+static Hash *r_remembered = 0; /* Hash of types we remembered already */
+
+static void (*r_tracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0;
+
+void SwigType_remember_mangleddata(String *mangled, const_String_or_char_ptr clientdata) {
+ if (!r_mangleddata) {
+ r_mangleddata = NewHash();
+ }
+ Setattr(r_mangleddata, mangled, clientdata);
+}
+
+
+void SwigType_remember_clientdata(const SwigType *t, const_String_or_char_ptr clientdata) {
+ String *mt;
+ SwigType *lt;
+ Hash *h;
+ SwigType *fr;
+ SwigType *qr;
+ String *tkey;
+ String *cd;
+ Hash *lthash;
+
+ if (!r_mangled) {
+ r_mangled = NewHash();
+ r_resolved = NewHash();
+ r_ltype = NewHash();
+ r_clientdata = NewHash();
+ r_remembered = NewHash();
+ }
+
+ {
+ String *last;
+ last = Getattr(r_remembered, t);
+ if (last && (Cmp(last, clientdata) == 0))
+ return;
+ }
+
+ tkey = Copy(t);
+ cd = clientdata ? NewString(clientdata) : NewStringEmpty();
+ Setattr(r_remembered, tkey, cd);
+ Delete(tkey);
+ Delete(cd);
+
+ mt = SwigType_manglestr(t); /* Create mangled string */
+
+ if (r_tracefunc) {
+ (*r_tracefunc) (t, mt, (String *) clientdata);
+ }
+
+ if (SwigType_istypedef(t)) {
+ lt = Copy(t);
+ } else {
+ lt = SwigType_ltype(t);
+ }
+
+ lthash = Getattr(r_ltype, mt);
+ if (!lthash) {
+ lthash = NewHash();
+ Setattr(r_ltype, mt, lthash);
+ }
+ Setattr(lthash, lt, "1");
+ Delete(lt);
+
+ fr = SwigType_typedef_resolve_all(t); /* Create fully resolved type */
+ qr = SwigType_typedef_qualified(fr);
+ Delete(fr);
+
+ /* Added to deal with possible table bug */
+ fr = SwigType_strip_qualifiers(qr);
+ Delete(qr);
+
+ /*Printf(stdout,"t = '%s'\n", t);
+ Printf(stdout,"fr= '%s'\n\n", fr); */
+
+ if (t) {
+ char *ct = Char(t);
+ const char *lt = strchr(ct, '<');
+ /* Allow for `<<` operator in constant expression for array size. */
+ if (lt && lt[1] != '(' && lt[1] != '<') {
+ Printf(stdout, "Bad template type passed to SwigType_remember: %s\n", t);
+ assert(0);
+ }
+ }
+
+ h = Getattr(r_mangled, mt);
+ if (!h) {
+ h = NewHash();
+ Setattr(r_mangled, mt, h);
+ Delete(h);
+ }
+ Setattr(h, fr, mt);
+
+ h = Getattr(r_resolved, fr);
+ if (!h) {
+ h = NewHash();
+ Setattr(r_resolved, fr, h);
+ Delete(h);
+ }
+ Setattr(h, mt, fr);
+
+ if (clientdata) {
+ String *cd = Getattr(r_clientdata, fr);
+ if (cd) {
+ if (Strcmp(clientdata, cd) != 0) {
+ Printf(stderr, "*** Internal error. Inconsistent clientdata for type '%s'\n", SwigType_str(fr, 0));
+ Printf(stderr, "*** '%s' != '%s'\n", clientdata, cd);
+ assert(0);
+ }
+ } else {
+ String *cstr = NewString(clientdata);
+ Setattr(r_clientdata, fr, cstr);
+ Delete(cstr);
+ }
+ }
+
+ /* If the remembered type is a reference, we also remember the pointer version.
+ This is to prevent odd problems with mixing pointers and references--especially
+ when different functions are using different typenames (via typedef). */
+
+ if (SwigType_isreference(t)) {
+ SwigType *tt = Copy(t);
+ SwigType_del_reference(tt);
+ SwigType_add_pointer(tt);
+ SwigType_remember_clientdata(tt, clientdata);
+ } else if (SwigType_isrvalue_reference(t)) {
+ SwigType *tt = Copy(t);
+ SwigType_del_rvalue_reference(tt);
+ SwigType_add_pointer(tt);
+ SwigType_remember_clientdata(tt, clientdata);
+ }
+}
+
+void SwigType_remember(const SwigType *ty) {
+ SwigType_remember_clientdata(ty, 0);
+}
+
+void (*SwigType_remember_trace(void (*tf) (const SwigType *, String *, String *))) (const SwigType *, String *, String *) {
+ void (*o) (const SwigType *, String *, String *) = r_tracefunc;
+ r_tracefunc = tf;
+ return o;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_equivalent_mangle()
+ *
+ * Return a list of all of the mangled typenames that are equivalent to another
+ * mangled name. This works as follows: For each fully qualified C datatype
+ * in the r_mangled hash entry, we collect all of the mangled names from the
+ * r_resolved hash and combine them together in a list (removing duplicate entries).
+ * ----------------------------------------------------------------------------- */
+
+List *SwigType_equivalent_mangle(String *ms, Hash *checked, Hash *found) {
+ List *l;
+ Hash *h;
+ Hash *ch;
+ Hash *mh;
+
+ if (found) {
+ h = found;
+ } else {
+ h = NewHash();
+ }
+ if (checked) {
+ ch = checked;
+ } else {
+ ch = NewHash();
+ }
+ if (Getattr(ch, ms))
+ goto check_exit; /* Already checked this type */
+ Setattr(h, ms, "1");
+ Setattr(ch, ms, "1");
+ mh = Getattr(r_mangled, ms);
+ if (mh) {
+ Iterator ki;
+ ki = First(mh);
+ while (ki.key) {
+ Hash *rh;
+ if (Getattr(ch, ki.key)) {
+ ki = Next(ki);
+ continue;
+ }
+ Setattr(ch, ki.key, "1");
+ rh = Getattr(r_resolved, ki.key);
+ if (rh) {
+ Iterator rk;
+ rk = First(rh);
+ while (rk.key) {
+ Setattr(h, rk.key, "1");
+ SwigType_equivalent_mangle(rk.key, ch, h);
+ rk = Next(rk);
+ }
+ }
+ ki = Next(ki);
+ }
+ }
+check_exit:
+ if (!found) {
+ l = Keys(h);
+ Delete(h);
+ Delete(ch);
+ return l;
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_clientdata_collect()
+ *
+ * Returns the clientdata field for a mangled type-string.
+ * ----------------------------------------------------------------------------- */
+
+static
+String *SwigType_clientdata_collect(String *ms) {
+ Hash *mh;
+ String *clientdata = 0;
+
+ if (r_mangleddata) {
+ clientdata = Getattr(r_mangleddata, ms);
+ if (clientdata)
+ return clientdata;
+ }
+
+ mh = Getattr(r_mangled, ms);
+ if (mh) {
+ Iterator ki;
+ ki = First(mh);
+ while (ki.key) {
+ clientdata = Getattr(r_clientdata, ki.key);
+ if (clientdata)
+ break;
+ ki = Next(ki);
+ }
+ }
+ return clientdata;
+}
+
+
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_inherit()
+ *
+ * Record information about inheritance. We keep a hash table that keeps
+ * a mapping between base classes and all of the classes that are derived
+ * from them.
+ *
+ * subclass is a hash that maps base-classes to all of the classes derived from them.
+ *
+ * derived - name of derived class
+ * base - name of base class
+ * cast - additional casting code when casting from derived to base
+ * conversioncode - if set, overrides the default code in the function when casting
+ * from derived to base
+ * ----------------------------------------------------------------------------- */
+
+static Hash *subclass = 0;
+static Hash *conversions = 0;
+
+void SwigType_inherit(String *derived, String *base, String *cast, String *conversioncode) {
+ Hash *h;
+ String *dd = 0;
+ String *bb = 0;
+ if (!subclass)
+ subclass = NewHash();
+
+ /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */
+
+ if (SwigType_istemplate(derived)) {
+ String *ty = SwigType_typedef_resolve_all(derived);
+ dd = SwigType_typedef_qualified(ty);
+ derived = dd;
+ Delete(ty);
+ }
+ if (SwigType_istemplate(base)) {
+ String *ty = SwigType_typedef_resolve_all(base);
+ bb = SwigType_typedef_qualified(ty);
+ base = bb;
+ Delete(ty);
+ }
+
+ /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */
+
+ h = Getattr(subclass, base);
+ if (!h) {
+ h = NewHash();
+ Setattr(subclass, base, h);
+ Delete(h);
+ }
+ if (!Getattr(h, derived)) {
+ Hash *c = NewHash();
+ if (cast)
+ Setattr(c, "cast", cast);
+ if (conversioncode)
+ Setattr(c, "convcode", conversioncode);
+ Setattr(h, derived, c);
+ Delete(c);
+ }
+
+ Delete(dd);
+ Delete(bb);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_issubtype()
+ *
+ * Determines if a t1 is a subtype of t2, ie, is t1 derived from t2
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_issubtype(const SwigType *t1, const SwigType *t2) {
+ SwigType *ft1, *ft2;
+ String *b1, *b2;
+ Hash *h;
+ int r = 0;
+
+ if (!subclass)
+ return 0;
+
+ ft1 = SwigType_typedef_resolve_all(t1);
+ ft2 = SwigType_typedef_resolve_all(t2);
+ b1 = SwigType_base(ft1);
+ b2 = SwigType_base(ft2);
+
+ h = Getattr(subclass, b2);
+ if (h) {
+ if (Getattr(h, b1)) {
+ r = 1;
+ }
+ }
+ Delete(ft1);
+ Delete(ft2);
+ Delete(b1);
+ Delete(b2);
+ /* Printf(stdout, "issubtype(%s,%s) --> %d\n", t1, t2, r); */
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_inherit_equiv()
+ *
+ * Modify the type table to handle C++ inheritance
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_inherit_equiv(File *out) {
+ String *ckey;
+ String *prefix, *base;
+ String *mprefix, *mkey;
+ Hash *sub;
+ Hash *rh;
+ List *rlist;
+ List *r_resolved_sorted_keys;
+ Iterator rk, bk, ck;
+
+ if (!conversions)
+ conversions = NewHash();
+ if (!subclass)
+ subclass = NewHash();
+
+ r_resolved_sorted_keys = SortedKeys(r_resolved, Strcmp);
+ rk = First(r_resolved_sorted_keys);
+ while (rk.item) {
+ List *sub_sorted_keys;
+ /* rkey is a fully qualified type. We strip all of the type constructors off of it just to get the base */
+ base = SwigType_base(rk.item);
+ /* Check to see whether the base is recorded in the subclass table */
+ sub = Getattr(subclass, base);
+ Delete(base);
+ if (!sub) {
+ rk = Next(rk);
+ continue;
+ }
+
+ /* This type has subclasses. We now need to walk through these subtypes and generate pointer conversion functions */
+
+ rh = Getattr(r_resolved, rk.item);
+ rlist = NewList();
+ for (ck = First(rh); ck.key; ck = Next(ck)) {
+ Append(rlist, ck.key);
+ }
+ /* Printf(stdout,"rk.item = '%s'\n", rk.item);
+ Printf(stdout,"rh = %p '%s'\n", rh,rh); */
+
+ sub_sorted_keys = SortedKeys(sub, Strcmp);
+ bk = First(sub_sorted_keys);
+ while (bk.item) {
+ prefix = SwigType_prefix(rk.item);
+ Append(prefix, bk.item);
+ /* Printf(stdout,"set %p = '%s' : '%s'\n", rh, SwigType_manglestr(prefix),prefix); */
+ mprefix = SwigType_manglestr(prefix);
+ Setattr(rh, mprefix, prefix);
+ mkey = SwigType_manglestr(rk.item);
+ ckey = NewStringf("%s+%s", mprefix, mkey);
+ if (!Getattr(conversions, ckey)) {
+ String *convname = NewStringf("%sTo%s", mprefix, mkey);
+ String *lkey = SwigType_lstr(rk.item, 0);
+ String *lprefix = SwigType_lstr(prefix, 0);
+ Hash *subhash = Getattr(sub, bk.item);
+ String *convcode = Getattr(subhash, "convcode");
+ if (convcode) {
+ char *newmemoryused = Strstr(convcode, "newmemory"); /* see if newmemory parameter is used in order to avoid unused parameter warnings */
+ String *fn = Copy(convcode);
+ Replaceall(fn, "$from", "x");
+ Printf(out, "static void *%s(void *x, int *%s) {", convname, newmemoryused ? "newmemory" : "SWIGUNUSEDPARM(newmemory)");
+ Printf(out, "%s", fn);
+ } else {
+ String *cast = Getattr(subhash, "cast");
+ Printf(out, "static void *%s(void *x, int *SWIGUNUSEDPARM(newmemory)) {", convname);
+ Printf(out, "\n return (void *)((%s) ", lkey);
+ if (cast)
+ Printf(out, "%s", cast);
+ Printf(out, " ((%s) x));\n", lprefix);
+ }
+ Printf(out, "}\n");
+ Setattr(conversions, ckey, convname);
+ Delete(ckey);
+ Delete(lkey);
+ Delete(lprefix);
+
+ /* This inserts conversions for typedefs */
+ {
+ Hash *r = Getattr(r_resolved, prefix);
+ if (r) {
+ Iterator rrk;
+ rrk = First(r);
+ while (rrk.key) {
+ Iterator rlk;
+ String *rkeymangle;
+
+ /* Make sure this name equivalence is not due to inheritance */
+ if (Cmp(prefix, Getattr(r, rrk.key)) == 0) {
+ rkeymangle = Copy(mkey);
+ ckey = NewStringf("%s+%s", rrk.key, rkeymangle);
+ if (!Getattr(conversions, ckey)) {
+ Setattr(conversions, ckey, convname);
+ }
+ Delete(ckey);
+ for (rlk = First(rlist); rlk.item; rlk = Next(rlk)) {
+ ckey = NewStringf("%s+%s", rrk.key, rlk.item);
+ Setattr(conversions, ckey, convname);
+ Delete(ckey);
+ }
+ Delete(rkeymangle);
+ /* This is needed to pick up other alternative names for the same type.
+ Needed to make templates work */
+ Setattr(rh, rrk.key, rrk.item);
+ }
+ rrk = Next(rrk);
+ }
+ }
+ }
+ Delete(convname);
+ }
+ Delete(prefix);
+ Delete(mprefix);
+ Delete(mkey);
+ bk = Next(bk);
+ }
+ Delete(sub_sorted_keys);
+ rk = Next(rk);
+ Delete(rlist);
+ }
+ Delete(r_resolved_sorted_keys);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_type_table()
+ *
+ * Generate the type-table for the type-checker.
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_emit_type_table(File *f_forward, File *f_table) {
+ Iterator ki;
+ String *types, *table, *cast, *cast_init, *cast_temp;
+ Hash *imported_types;
+ List *mangled_list;
+ List *table_list = NewList();
+ int i = 0;
+
+ if (!r_mangled) {
+ r_mangled = NewHash();
+ r_resolved = NewHash();
+ }
+
+ Printf(f_table, "\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */\n\n");
+
+ SwigType_inherit_equiv(f_table);
+
+ /*#define DEBUG 1*/
+#ifdef DEBUG
+ Printf(stdout, "---r_mangled---\n");
+ Swig_print(r_mangled, 2);
+
+ Printf(stdout, "---r_resolved---\n");
+ Swig_print(r_resolved, 2);
+
+ Printf(stdout, "---r_ltype---\n");
+ Swig_print(r_ltype, 2);
+
+ Printf(stdout, "---subclass---\n");
+ Swig_print(subclass, 2);
+
+ Printf(stdout, "---conversions---\n");
+ Swig_print(conversions, 2);
+
+ Printf(stdout, "---r_clientdata---\n");
+ Swig_print(r_clientdata, 2);
+
+#endif
+ table = NewStringEmpty();
+ types = NewStringEmpty();
+ cast = NewStringEmpty();
+ cast_init = NewStringEmpty();
+ imported_types = NewHash();
+
+ Printf(table, "static swig_type_info *swig_type_initial[] = {\n");
+ Printf(cast_init, "static swig_cast_info *swig_cast_initial[] = {\n");
+
+ Printf(f_forward, "\n/* -------- TYPES TABLE (BEGIN) -------- */\n\n");
+
+ mangled_list = SortedKeys(r_mangled, Strcmp);
+ for (ki = First(mangled_list); ki.item; ki = Next(ki)) {
+ List *el;
+ Iterator ei;
+ String *nt;
+ String *ln;
+ String *rn;
+ const String *cd;
+ Hash *lthash;
+ Iterator ltiter;
+ Hash *nthash;
+ String *cast_temp_conv;
+ String *resolved_lstr = 0;
+ List *ntlist;
+
+ cast_temp = NewStringEmpty();
+ cast_temp_conv = NewStringEmpty();
+
+ Printv(types, "static swig_type_info _swigt_", ki.item, " = {", NIL);
+ Append(table_list, ki.item);
+ Printf(cast_temp, "static swig_cast_info _swigc_%s[] = {", ki.item);
+ i++;
+
+ cd = SwigType_clientdata_collect(ki.item);
+ if (!cd)
+ cd = "0";
+
+ lthash = Getattr(r_ltype, ki.item);
+ nt = 0;
+ nthash = NewHash();
+ ltiter = First(lthash);
+ while (ltiter.key) {
+ SwigType *lt = ltiter.key;
+ SwigType *rt = SwigType_typedef_resolve_all(lt);
+ /* we save the original type and the fully resolved version */
+ ln = SwigType_lstr(lt, 0);
+ rn = SwigType_lstr(rt, 0);
+ if (Equal(ln, rn)) {
+ Setattr(nthash, ln, "1");
+ } else {
+ Setattr(nthash, rn, "1");
+ Setattr(nthash, ln, "1");
+ }
+ if (!resolved_lstr) {
+ resolved_lstr = Copy(rn);
+ } else if (Len(rn) < Len(resolved_lstr)) {
+ Delete(resolved_lstr);
+ resolved_lstr = Copy(rn);
+ }
+ if (SwigType_istemplate(rt)) {
+ String *dt = Swig_symbol_template_deftype(rt, 0);
+ String *dn = SwigType_lstr(dt, 0);
+ if (!Equal(dn, rn) && !Equal(dn, ln)) {
+ Setattr(nthash, dn, "1");
+ }
+ Delete(dt);
+ Delete(dn);
+ }
+ Delete(rt);
+ Delete(rn);
+ Delete(ln);
+
+ ltiter = Next(ltiter);
+ }
+
+ /* now build nt */
+ ntlist = SortedKeys(nthash, Strcmp);
+ ltiter = First(ntlist);
+ nt = 0;
+ while (ltiter.item) {
+ if (!Equal(resolved_lstr, ltiter.item)) {
+ if (nt) {
+ Printf(nt, "|%s", ltiter.item);
+ } else {
+ nt = NewString(ltiter.item);
+ }
+ }
+ ltiter = Next(ltiter);
+ }
+ /* Last in list is a resolved type used by SWIG_TypePrettyName.
+ * There can be more than one resolved type and the chosen one is simply the
+ * shortest in length, arguably the most user friendly/readable. */
+ if (nt) {
+ Printf(nt, "|%s", resolved_lstr);
+ } else {
+ nt = NewString(resolved_lstr);
+ }
+ Delete(ntlist);
+ Delete(nthash);
+ Delete(resolved_lstr);
+
+ Printf(types, "\"%s\", \"%s\", 0, 0, (void*)%s, 0};\n", ki.item, nt, cd);
+
+ el = SwigType_equivalent_mangle(ki.item, 0, 0);
+ SortList(el, Strcmp);
+ for (ei = First(el); ei.item; ei = Next(ei)) {
+ String *ckey;
+ String *conv;
+ ckey = NewStringf("%s+%s", ei.item, ki.item);
+ conv = Getattr(conversions, ckey);
+ if (conv) {
+ Printf(cast_temp_conv, " {&_swigt_%s, %s, 0, 0},", ei.item, conv);
+ } else {
+ Printf(cast_temp, " {&_swigt_%s, 0, 0, 0},", ei.item);
+ }
+ Delete(ckey);
+
+ if (!Getattr(r_mangled, ei.item) && !Getattr(imported_types, ei.item)) {
+ Printf(types, "static swig_type_info _swigt_%s = {\"%s\", 0, 0, 0, 0, 0};\n", ei.item, ei.item);
+ Append(table_list, ei.item);
+
+ Printf(cast, "static swig_cast_info _swigc_%s[] = {{&_swigt_%s, 0, 0, 0},{0, 0, 0, 0}};\n", ei.item, ei.item);
+ i++;
+
+ Setattr(imported_types, ei.item, "1");
+ }
+ }
+ Delete(el);
+ Printf(cast, "%s%s{0, 0, 0, 0}};\n", cast_temp, cast_temp_conv);
+ Delete(cast_temp_conv);
+ Delete(cast_temp);
+ Delete(nt);
+ }
+ /* print the tables in the proper order */
+ SortList(table_list, Strcmp);
+ i = 0;
+ for (ki = First(table_list); ki.item; ki = Next(ki)) {
+ Printf(f_forward, "#define SWIGTYPE%s swig_types[%d]\n", ki.item, i++);
+ Printf(table, " &_swigt_%s,\n", ki.item);
+ Printf(cast_init, " _swigc_%s,\n", ki.item);
+ }
+ if (i == 0) {
+ /* empty arrays are not allowed by ISO C */
+ Printf(table, " NULL\n");
+ Printf(cast_init, " NULL\n");
+ }
+
+ Delete(table_list);
+
+ Delete(mangled_list);
+
+ Printf(table, "};\n");
+ Printf(cast_init, "};\n");
+ Printf(f_table, "%s\n", types);
+ Printf(f_table, "%s\n", table);
+ Printf(f_table, "%s\n", cast);
+ Printf(f_table, "%s\n", cast_init);
+ Printf(f_table, "\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */\n\n");
+
+ Printf(f_forward, "static swig_type_info *swig_types[%d];\n", i + 1);
+ Printf(f_forward, "static swig_module_info swig_module = {swig_types, %d, 0, 0, 0, 0};\n", i);
+ Printf(f_forward, "#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)\n");
+ Printf(f_forward, "#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)\n");
+ Printf(f_forward, "\n/* -------- TYPES TABLE (END) -------- */\n\n");
+
+ Delete(types);
+ Delete(table);
+ Delete(cast);
+ Delete(cast_init);
+ Delete(imported_types);
+}
diff --git a/contrib/tools/swig/Source/Swig/wrapfunc.c b/contrib/tools/swig/Source/Swig/wrapfunc.c
new file mode 100644
index 0000000000..6d82372453
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/wrapfunc.c
@@ -0,0 +1,520 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * wrapfunc.c
+ *
+ * This file defines a object for creating wrapper functions. Primarily
+ * this is used for convenience since it allows pieces of a wrapper function
+ * to be created in a piecemeal manner.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <ctype.h>
+
+static int Compact_mode = 0; /* set to 0 on default */
+static int Max_line_size = 128;
+
+/* -----------------------------------------------------------------------------
+ * NewWrapper()
+ *
+ * Create a new wrapper function object.
+ * ----------------------------------------------------------------------------- */
+
+Wrapper *NewWrapper(void) {
+ Wrapper *w;
+ w = (Wrapper *) Malloc(sizeof(Wrapper));
+ w->localh = NewHash();
+ w->locals = NewStringEmpty();
+ w->code = NewStringEmpty();
+ w->def = NewStringEmpty();
+ return w;
+}
+
+/* -----------------------------------------------------------------------------
+ * DelWrapper()
+ *
+ * Delete a wrapper function object.
+ * ----------------------------------------------------------------------------- */
+
+void DelWrapper(Wrapper *w) {
+ Delete(w->localh);
+ Delete(w->locals);
+ Delete(w->code);
+ Delete(w->def);
+ Free(w);
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_compact_print_mode_set()
+ *
+ * Set compact_mode.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_compact_print_mode_set(int flag) {
+ Compact_mode = flag;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_pretty_print()
+ *
+ * Formats a wrapper function and fixes up the indentation.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_pretty_print(String *str, File *f) {
+ String *ts;
+ int level = 0;
+ int c, i;
+ int empty = 1;
+ int indent = 2;
+ int plevel = 0;
+ int label = 0;
+
+ ts = NewStringEmpty();
+ Seek(str, 0, SEEK_SET);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\"') {
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\"')
+ break;
+ }
+ empty = 0;
+ } else if (c == '\'') {
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\'')
+ break;
+ }
+ empty = 0;
+ } else if (c == ':') {
+ Putc(c, ts);
+ if ((c = Getc(str)) == '\n') {
+ if (!empty && !strchr(Char(ts), '?'))
+ label = 1;
+ }
+ Ungetc(c, str);
+ } else if (c == '(') {
+ Putc(c, ts);
+ plevel += indent;
+ empty = 0;
+ } else if (c == ')') {
+ Putc(c, ts);
+ plevel -= indent;
+ empty = 0;
+ } else if (c == '{') {
+ Putc(c, ts);
+ Putc('\n', ts);
+ for (i = 0; i < level; i++)
+ Putc(' ', f);
+ Printf(f, "%s", ts);
+ Clear(ts);
+ level += indent;
+ while ((c = Getc(str)) != EOF) {
+ if (!isspace(c)) {
+ Ungetc(c, str);
+ break;
+ }
+ }
+ empty = 0;
+ } else if (c == '}') {
+ if (!empty) {
+ Putc('\n', ts);
+ for (i = 0; i < level; i++)
+ Putc(' ', f);
+ Printf(f, "%s", ts);
+ Clear(ts);
+ }
+ level -= indent;
+ Putc(c, ts);
+ empty = 0;
+ } else if (c == '\n') {
+ Putc(c, ts);
+ empty = 0;
+ if (!empty) {
+ int slevel = level;
+ if (label && (slevel >= indent))
+ slevel -= indent;
+ if ((Char(ts))[0] != '#') {
+ for (i = 0; i < slevel; i++)
+ Putc(' ', f);
+ }
+ Printf(f, "%s", ts);
+ for (i = 0; i < plevel; i++)
+ Putc(' ', f);
+ }
+ Clear(ts);
+ label = 0;
+ empty = 1;
+ } else if (c == '/') {
+ empty = 0;
+ Putc(c, ts);
+ c = Getc(str);
+ if (c != EOF) {
+ Putc(c, ts);
+ if (c == '/') { /* C++ comment */
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\n') {
+ Ungetc(c, str);
+ break;
+ }
+ Putc(c, ts);
+ }
+ } else if (c == '*') { /* C comment */
+ int endstar = 0;
+ while ((c = Getc(str)) != EOF) {
+ if (endstar && c == '/') { /* end of C comment */
+ Putc(c, ts);
+ break;
+ }
+ endstar = (c == '*');
+ Putc(c, ts);
+ if (c == '\n') { /* multi-line C comment. Could be improved slightly. */
+ for (i = 0; i < level; i++)
+ Putc(' ', ts);
+ }
+ }
+ }
+ }
+ } else {
+ if (!empty || !isspace(c)) {
+ Putc(c, ts);
+ empty = 0;
+ }
+ }
+ }
+ if (!empty)
+ Printf(f, "%s", ts);
+ Delete(ts);
+ Printf(f, "\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_compact_print()
+ *
+ * Formats a wrapper function and fixes up the indentation.
+ * Print out in compact format, with Compact enabled.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_compact_print(String *str, File *f) {
+ String *ts, *tf; /*temp string & temp file */
+ int level = 0;
+ int c, i;
+ int empty = 1;
+ int indent = 2;
+
+ ts = NewStringEmpty();
+ tf = NewStringEmpty();
+ Seek(str, 0, SEEK_SET);
+
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\"') { /* string 1 */
+ empty = 0;
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\"')
+ break;
+ }
+ } else if (c == '\'') { /* string 2 */
+ empty = 0;
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\'')
+ break;
+ }
+ } else if (c == '{') { /* start of {...} */
+ empty = 0;
+ Putc(c, ts);
+ if (Len(tf) == 0) {
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ } else if ((Len(tf) + Len(ts)) < Max_line_size) {
+ Putc(' ', tf);
+ } else {
+ Putc('\n', tf);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ }
+ Append(tf, ts);
+ Clear(ts);
+ level += indent;
+ while ((c = Getc(str)) != EOF) {
+ if (!isspace(c)) {
+ Ungetc(c, str);
+ break;
+ }
+ }
+ } else if (c == '}') { /* end of {...} */
+ empty = 0;
+ if (Len(tf) == 0) {
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ } else if ((Len(tf) + Len(ts)) < Max_line_size) {
+ Putc(' ', tf);
+ } else {
+ Putc('\n', tf);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ }
+ Append(tf, ts);
+ Putc(c, tf);
+ Clear(ts);
+ level -= indent;
+ } else if (c == '\n') { /* line end */
+ while ((c = Getc(str)) != EOF) {
+ if (!isspace(c))
+ break;
+ }
+ if (c == '#') {
+ Putc('\n', ts);
+ } else if (c == '}') {
+ Putc(' ', ts);
+ } else if ((c != EOF) || (Len(ts) != 0)) {
+ if (Len(tf) == 0) {
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ } else if ((Len(tf) + Len(ts)) < Max_line_size) {
+ Putc(' ', tf);
+ } else {
+ Putc('\n', tf);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ }
+ Append(tf, ts);
+ Clear(ts);
+ }
+ Ungetc(c, str);
+
+ empty = 1;
+ } else if (c == '/') { /* comment */
+ empty = 0;
+ c = Getc(str);
+ if (c != EOF) {
+ if (c == '/') { /* C++ comment */
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\n') {
+ Ungetc(c, str);
+ break;
+ }
+ }
+ } else if (c == '*') { /* C comment */
+ int endstar = 0;
+ while ((c = Getc(str)) != EOF) {
+ if (endstar && c == '/') { /* end of C comment */
+ break;
+ }
+ endstar = (c == '*');
+ }
+ } else {
+ Putc('/', ts);
+ Putc(c, ts);
+ }
+ }
+ } else if (c == '#') { /* Preprocessor line */
+ Putc('#', ts);
+ while ((c = Getc(str)) != EOF) {
+ Putc(c, ts);
+ if (c == '\\') { /* Continued line of the same PP */
+ c = Getc(str);
+ if (c == '\n')
+ Putc(c, ts);
+ else
+ Ungetc(c, str);
+ } else if (c == '\n')
+ break;
+ }
+ if (!empty) {
+ Append(tf, "\n");
+ }
+ Append(tf, ts);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ Clear(ts);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ empty = 1;
+ } else {
+ if (!empty || !isspace(c)) {
+ Putc(c, ts);
+ empty = 0;
+ }
+ }
+ }
+ if (!empty) {
+ Append(tf, ts);
+ }
+ if (Len(tf) != 0)
+ Printf(f, "%s", tf);
+ Delete(ts);
+ Delete(tf);
+ Printf(f, "\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_print()
+ *
+ * Print out a wrapper function. Does pretty or compact printing as well.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_print(Wrapper *w, File *f) {
+ String *str;
+
+ str = NewStringEmpty();
+ Printf(str, "%s\n", w->def);
+ Printf(str, "%s\n", w->locals);
+ Printf(str, "%s\n", w->code);
+ if (Compact_mode == 1)
+ Wrapper_compact_print(str, f);
+ else
+ Wrapper_pretty_print(str, f);
+
+ Delete(str);
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_add_local()
+ *
+ * Adds a new local variable declaration to a function. Returns -1 if already
+ * present (which may or may not be okay to the caller).
+ * ----------------------------------------------------------------------------- */
+
+int Wrapper_add_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
+ /* See if the local has already been declared */
+ if (Getattr(w->localh, name)) {
+ return -1;
+ }
+ Setattr(w->localh, name, decl);
+ Printf(w->locals, "%s;\n", decl);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_add_localv()
+ *
+ * Same as add_local(), but allows a NULL terminated list of strings to be
+ * used as a replacement for decl. This saves the caller the trouble of having
+ * to manually construct the 'decl' string before calling.
+ * ----------------------------------------------------------------------------- */
+
+int Wrapper_add_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
+ va_list ap;
+ int ret;
+ String *decl;
+ DOH *obj;
+ decl = NewStringEmpty();
+ va_start(ap, name);
+
+ obj = va_arg(ap, void *);
+ while (obj) {
+ Append(decl, obj);
+ Putc(' ', decl);
+ obj = va_arg(ap, void *);
+ }
+ va_end(ap);
+
+ ret = Wrapper_add_local(w, name, decl);
+ Delete(decl);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_check_local()
+ *
+ * Check to see if a local name has already been declared
+ * ----------------------------------------------------------------------------- */
+
+int Wrapper_check_local(Wrapper *w, const_String_or_char_ptr name) {
+ if (Getattr(w->localh, name)) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_new_local()
+ *
+ * Adds a new local variable with a guarantee that a unique local name will be
+ * used. Returns the name that was actually selected.
+ * ----------------------------------------------------------------------------- */
+
+char *Wrapper_new_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
+ int i;
+ String *nname = NewString(name);
+ String *ndecl = NewString(decl);
+ char *ret;
+
+ i = 0;
+
+ while (Wrapper_check_local(w, nname)) {
+ Clear(nname);
+ Printf(nname, "%s%d", name, i);
+ i++;
+ }
+ Replace(ndecl, name, nname, DOH_REPLACE_ID);
+ Setattr(w->localh, nname, ndecl);
+ Printf(w->locals, "%s;\n", ndecl);
+ ret = Char(nname);
+ Delete(nname);
+ Delete(ndecl);
+ return ret; /* Note: nname should still exists in the w->localh hash */
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_new_localv()
+ *
+ * Same as add_local(), but allows a NULL terminated list of strings to be
+ * used as a replacement for decl. This saves the caller the trouble of having
+ * to manually construct the 'decl' string before calling.
+ * ----------------------------------------------------------------------------- */
+
+char *Wrapper_new_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
+ va_list ap;
+ char *ret;
+ String *decl;
+ DOH *obj;
+ decl = NewStringEmpty();
+ va_start(ap, name);
+
+ obj = va_arg(ap, void *);
+ while (obj) {
+ Append(decl, obj);
+ Putc(' ', decl);
+ obj = va_arg(ap, void *);
+ }
+ va_end(ap);
+
+ ret = Wrapper_new_local(w, name, decl);
+ Delete(decl);
+ return ret;
+}