From 01277d700ca44e695d584838dc42c98e035ad514 Mon Sep 17 00:00:00 2001 From: Thomas Reitmayr Date: Tue, 9 Jun 2020 21:58:47 +0200 Subject: [PATCH 001/217] Unwrap director classes only when returning a pointer or reference to an object This involves properly counting the number of references and pointers in the return type of a function and only generate unwrapping code if this number is 1. For template instances some post-processing code is added to fix the 'decl' and 'type' attributes of functions if changed in an unfavorable way during template expansion. This commit fixes swig#1811. --- Examples/test-suite/common.mk | 1 + Examples/test-suite/director_unwrap_result.i | 82 ++++++++++++++ Examples/test-suite/javascript/Makefile.in | 1 + .../ruby/director_unwrap_result_runme.rb | 106 ++++++++++++++++++ Source/CParse/templ.c | 91 +++++++++++++++ Source/Modules/python.cxx | 4 +- Source/Modules/ruby.cxx | 4 +- Source/Swig/swig.h | 2 + Source/Swig/typeobj.c | 84 ++++++++++++++ 9 files changed, 369 insertions(+), 6 deletions(-) create mode 100644 Examples/test-suite/director_unwrap_result.i create mode 100644 Examples/test-suite/ruby/director_unwrap_result_runme.rb diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index e77f09c86..abc1e9997 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -213,6 +213,7 @@ CPP_TEST_CASES += \ director_smartptr \ director_thread \ director_unroll \ + director_unwrap_result \ director_using \ director_void \ director_wombat \ diff --git a/Examples/test-suite/director_unwrap_result.i b/Examples/test-suite/director_unwrap_result.i new file mode 100644 index 000000000..bcb7f0fcc --- /dev/null +++ b/Examples/test-suite/director_unwrap_result.i @@ -0,0 +1,82 @@ +%module(directors="1") director_unwrap_result + +%warnfilter(SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) Storage; +%warnfilter(SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) StorageTmpl; + +%feature("director") Element; +%feature("director") Storage; +%feature("director") StorageTmpl; + +%inline %{ + +class Element { + Element* self; + Element** selfptr; + public: + Element() { + self = this; + selfptr = &self; + } + virtual ~Element() {} + Element **getPtrPtr() { + return &self; + } + Element ***getPtrPtrPtr() { + return &selfptr; + } +}; + +class Storage { + public: + virtual ~Storage() {} + virtual Element **getIt() = 0; + Element getElement() { + return **getIt(); + } + Element* const getElementPtr() { + return *getIt(); + } + Element& getElementRef() { + return **getIt(); + } + Element* const *getElementPtrPtr() { + return getIt(); + } + Element *&getElementPtrRef() { + return *getIt(); + } +}; + +template class StorageTmpl { + public: + virtual ~StorageTmpl() {} + virtual T &getIt() = 0; + T getVal() { + return getIt(); + } + T *getPtr() { + return &getIt(); + } + T &getRef() { + return getIt(); + } +}; + +%} + +%template(ElementStorage) StorageTmpl; +%template(ElementPtrStorage) StorageTmpl; +%template(ElementPtrPtrStorage) StorageTmpl; + +%inline %{ + +template T getParam(T t) { + return t; +} + +%} + +%template(getIntParam) getParam; +%template(getIntPtrParam) getParam; +%template(getElementPtrParam) getParam; + diff --git a/Examples/test-suite/javascript/Makefile.in b/Examples/test-suite/javascript/Makefile.in index 8127415f1..bf7f24236 100644 --- a/Examples/test-suite/javascript/Makefile.in +++ b/Examples/test-suite/javascript/Makefile.in @@ -52,6 +52,7 @@ ifeq (node,$(JSENGINE)) apply_signed_char.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\" constant_pointers.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\" enum_thorough.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\" + director_unwrap_result.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\" setup_node = \ test -d $* || mkdir $* && \ diff --git a/Examples/test-suite/ruby/director_unwrap_result_runme.rb b/Examples/test-suite/ruby/director_unwrap_result_runme.rb new file mode 100644 index 000000000..56970b3e8 --- /dev/null +++ b/Examples/test-suite/ruby/director_unwrap_result_runme.rb @@ -0,0 +1,106 @@ +#!/usr/bin/env ruby +# +# This test checks the proper unwrapping of director objects before returning +# a pointer to the (wrapped) instance. +# Unwrapping must not happen for return-by-value and returning higher +# reference levels (pointer to pointer, reference to pointer, etc.), but this +# is already checked by the C++ compiler. +# + +require 'swig_assert' + +require 'director_unwrap_result' + +############################ +# test with a regular (non-template) class + +class MyElement < Director_unwrap_result::Element +end + +class MyStorage < Director_unwrap_result::Storage + def initialize(e) + super() + @elem = e + end + def getIt + @elem.getPtrPtr + end +end + +e = MyElement.new +s = MyStorage.new(e) + +swig_assert_equal('s.getElement.class', 'Director_unwrap_result::Element', binding) +swig_assert('s.getElement != e', binding) + +# this shows that the director class was unwrapped: +swig_assert_equal('s.getElementPtr.class', 'MyElement', binding) +swig_assert_equal('s.getElementPtr', 'e', binding) + +# this shows that the director class was unwrapped: +swig_assert_equal('s.getElementRef.class', 'MyElement', binding) +swig_assert_equal('s.getElementRef', 'e', binding) + +swig_assert_equal('s.getElementPtrPtr.class', 'SWIG::TYPE_p_p_Element', binding) +swig_assert_equal('s.getElementPtrPtr.class', 'SWIG::TYPE_p_p_Element', binding) + +swig_assert_equal('s.getElementPtrRef.class', 'SWIG::TYPE_p_p_Element', binding) +swig_assert_equal('s.getElementPtrRef.class', 'SWIG::TYPE_p_p_Element', binding) + +############################ +# test with a template class + +class MyElementStorage < Director_unwrap_result::ElementStorage + def initialize(e) + super() + @elem = e + end + def getIt + @elem + end +end + +class MyElementPtrStorage < Director_unwrap_result::ElementPtrStorage + def initialize(e) + super() + @elem = e + end + def getIt + @elem.getPtrPtr + end +end + +class MyElementPtrPtrStorage < Director_unwrap_result::ElementPtrPtrStorage + def initialize(e) + super() + @elem = e + end + def getIt + @elem.getPtrPtrPtr + end +end + +e = MyElement.new + +s = MyElementStorage.new(e) +swig_assert_equal('s.getVal.class', 'Director_unwrap_result::Element', binding) +swig_assert('s.getVal != e', binding) +# this shows that the director class was unwrapped: +swig_assert_equal('s.getPtr.class', 'MyElement', binding) +swig_assert_equal('s.getPtr', 'e', binding) +# this shows that the director class was unwrapped: +swig_assert_equal('s.getRef.class', 'MyElement', binding) +swig_assert_equal('s.getRef', 'e', binding) + +s = MyElementPtrStorage.new(e) +# this shows that the director class was unwrapped: +swig_assert_equal('s.getVal.class', 'MyElement', binding) +swig_assert_equal('s.getVal', 'e', binding) +swig_assert_equal('s.getPtr.class', 'SWIG::TYPE_p_p_Element', binding) +swig_assert_equal('s.getRef.class', 'SWIG::TYPE_p_p_Element', binding) + +s = MyElementPtrPtrStorage.new(e) +swig_assert_equal('s.getVal.class', 'SWIG::TYPE_p_p_Element', binding) +swig_assert_equal('s.getPtr.class', 'SWIG::TYPE_p_p_p_Element', binding) +swig_assert_equal('s.getRef.class', 'SWIG::TYPE_p_p_p_Element', binding) + diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index 22d49fac5..5f43bad82 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -234,6 +234,95 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri } } +/* ----------------------------------------------------------------------------- + * cparse_fix_function_decl() + * + * Move the prefix of the "type" attribute (excluding any trailing qualifier) + * to the end of the "decl" attribute. + * Examples: + * decl="f().", type="p.q(const).char" => decl="f().p.", type="q(const).char" + * decl="f().p.", type="p.SomeClass" => decl="f().p.p.", type="SomeClass" + * decl="f().", type="r.q(const).p.int" => decl="f().r.q(const).p.", type="int" + * ----------------------------------------------------------------------------- */ + +static void cparse_fix_function_decl(String *name, SwigType *decl, SwigType *type) { + String *prefix; + int prefixLen; + SwigType* last; + + /* The type's prefix is what potentially has to be moved to the end of 'decl' */ + prefix = SwigType_prefix(type); + + /* First some parts (qualifier and array) have to be removed from prefix + in order to remain in the 'type' attribute. */ + last = SwigType_last(prefix); + while (last) { + if (SwigType_isqualifier(last) || SwigType_isarray(last)) { + /* Keep this part in the 'type' */ + Delslice(prefix, Len(prefix) - Len(last), DOH_END); + Delete(last); + last = SwigType_last(prefix); + } else { + /* Done with processing prefix */ + Delete(last); + last = 0; + } + } + + /* Transfer prefix from the 'type' to the 'decl' attribute */ + prefixLen = Len(prefix); + if (prefixLen > 0) { + Append(decl, prefix); + Delslice(type, 0, prefixLen); + if (template_debug) { + Printf(stdout, " change function '%s' to type='%s', decl='%s'\n", + name, type, decl); + } + } + + Delete(prefix); +} + +/* ----------------------------------------------------------------------------- + * cparse_postprocess_expanded_template() + * + * This function postprocesses the given node after template expansion. + * Currently the only task to perform is fixing function decl and type attributes. + * ----------------------------------------------------------------------------- */ + +static void cparse_postprocess_expanded_template(Node *n) { + String *nodeType; + if (!n) + return; + nodeType = nodeType(n); + if (Getattr(n, "error")) + return; + + if (Equal(nodeType, "cdecl")) { + /* A simple C declaration */ + SwigType *d = Getattr(n, "decl"); + if (d && SwigType_isfunction(d)) { + /* A function node */ + SwigType *t = Getattr(n, "type"); + if (t) { + String *name = Getattr(n, "name"); + cparse_fix_function_decl(name, d, t); + } + } + } else { + /* Look for any children */ + Node *cn = firstChild(n); + while (cn) { + cparse_postprocess_expanded_template(cn); + cn = nextSibling(cn); + } + } +} + +/* ----------------------------------------------------------------------------- + * partial_arg() + * ----------------------------------------------------------------------------- */ + static String *partial_arg(String *s, String *p) { char *c; @@ -414,6 +503,8 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab } } + cparse_postprocess_expanded_template(n); + /* Patch bases */ { List *bases = Getattr(n, "baselist"); diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index c8c45df35..336f6c219 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -3118,9 +3118,7 @@ public: #if 1 int unwrap = 0; String *decl = Getattr(n, "decl"); - int is_pointer = SwigType_ispointer_return(decl); - int is_reference = SwigType_isreference_return(decl); - if (is_pointer || is_reference) { + if (SwigType_refptr_count_return(decl) == 1) { String *type = Getattr(n, "type"); //Node *classNode = Swig_methodclass(n); //Node *module = Getattr(classNode, "module"); diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 48b0efab3..64bc4df89 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -1893,9 +1893,7 @@ public: */ bool unwrap = false; String *decl = Getattr(n, "decl"); - int is_pointer = SwigType_ispointer_return(decl); - int is_reference = SwigType_isreference_return(decl); - if (is_pointer || is_reference) { + if (SwigType_refptr_count_return(decl) == 1) { String *type = Getattr(n, "type"); Node *parent = Swig_methodclass(n); Node *modname = Getattr(parent, "module"); diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 76691269e..2bf3e08b0 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -141,6 +141,8 @@ extern "C" { 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 int SwigType_refptr_count_return(const 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); diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c index 69fb6662b..8e64bad92 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -208,6 +208,90 @@ SwigType *SwigType_pop(SwigType *t) { 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_refptr_count_return() + * + * Returns the number of pointer and reference indirections found in the given + * type. For functions this concerns the return type. + * For example: + * r.p. => 2 + * q(const).p. => 1 + * r.f(int).p.p. => 2 + * f().p.q(const).p. => 2 + * ----------------------------------------------------------------------------- */ + +int SwigType_refptr_count_return(const SwigType *t) { + char *c; + char *last; + int sz; + int result = 0; + + if (!t) + return 0; + + c = Char(t); + last = c; + while (*c) { + last = c; + sz = element_size(c); + c = c + sz; + if (*(c-1) == '.') { + if (((last[0] == 'p') || (last[0] == 'r')) && (last[1] == '.')) { + result++; + } else if (strncmp(last, "f(", 2) == 0) { + /* restart counter if this is a function type */ + result = 0; + } + } + if (*c == '.') { + c++; + } + } + + return result; +} + /* ----------------------------------------------------------------------------- * SwigType_parm() * From 6aeee8effc089ba21bb771dd329350ac5b0c755f Mon Sep 17 00:00:00 2001 From: Sergio Garcia Murillo Date: Fri, 5 Mar 2021 15:08:17 +0100 Subject: [PATCH 002/217] Use SWIG_TypeCast in SWIG_V8_ConvertInstancePtr if types don't match (#3) Use SWIG_TypeCast in SWIG_V8_ConvertInstancePtr if types don't match --- Lib/javascript/v8/javascriptrun.swg | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Lib/javascript/v8/javascriptrun.swg b/Lib/javascript/v8/javascriptrun.swg index 62c7bf829..45dd8fe28 100644 --- a/Lib/javascript/v8/javascriptrun.swg +++ b/Lib/javascript/v8/javascriptrun.swg @@ -289,8 +289,12 @@ SWIGRUNTIME int SWIG_V8_ConvertInstancePtr(SWIGV8_OBJECT objRef, void **ptr, swi if(!type_valid) { return SWIG_TypeError; } + int newmemory = 0; + *ptr = SWIG_TypeCast(tc, cdata->swigCObject, &newmemory); + } else { + *ptr = cdata->swigCObject; } - *ptr = cdata->swigCObject; + if(flags & SWIG_POINTER_DISOWN) { cdata->swigCMemOwn = false; } From 56e7455af91911c06210cf551729df61a428e5a6 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Murillo Date: Mon, 29 Nov 2021 16:08:03 +0100 Subject: [PATCH 003/217] Return uint64_t as double if is bigger than uint32_t --- Lib/javascript/v8/javascriptprimtypes.swg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/javascript/v8/javascriptprimtypes.swg b/Lib/javascript/v8/javascriptprimtypes.swg index 0af406b90..8ed571df1 100644 --- a/Lib/javascript/v8/javascriptprimtypes.swg +++ b/Lib/javascript/v8/javascriptprimtypes.swg @@ -81,7 +81,7 @@ int SWIG_AsVal_dec(long)(SWIGV8_VALUE obj, long* val) SWIGINTERNINLINE SWIGV8_VALUE SWIG_From_dec(unsigned long)(unsigned long value) { - return SWIGV8_INTEGER_NEW_UNS(value); + return value <= UINT32_MAX ? (SWIGV8_VALUE)SWIGV8_INTEGER_NEW_UNS(value) : (SWIGV8_VALUE)SWIGV8_NUMBER_NEW(static_cast(value)); } } @@ -149,7 +149,7 @@ int SWIG_AsVal_dec(long long)(SWIGV8_VALUE obj, long long* val) SWIGINTERNINLINE SWIGV8_VALUE SWIG_From_dec(unsigned long long)(unsigned long long value) { - return SWIGV8_INTEGER_NEW_UNS(value); + return value <= UINT32_MAX ? (SWIGV8_VALUE)SWIGV8_INTEGER_NEW_UNS(value) : (SWIGV8_VALUE)SWIGV8_NUMBER_NEW(static_cast(value)); } %#endif } From a9f76c89ec0f4b2b60f2edc3d705c14cc6aec5f6 Mon Sep 17 00:00:00 2001 From: benjamin-sch Date: Wed, 12 Jan 2022 14:22:11 +0100 Subject: [PATCH 004/217] added interpreter_counter to deinitialize only once in case of subinterpreters --- Lib/python/pyrun.swg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index a49cbb5b3..d42dc0f0f 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -1643,12 +1643,17 @@ SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) { return (swig_module_info *) type_pointer; } + +static int interpreter_counter = 0; // how many (sub-)interpreters are using swig_module's types + SWIGRUNTIME void SWIG_Python_DestroyModule(PyObject *obj) { swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME); swig_type_info **types = swig_module->types; size_t i; + if (--interpreter_counter != 0) // another sub-interpreter may still be using the swig_module's types + return; for (i =0; i < swig_module->size; ++i) { swig_type_info *ty = types[i]; if (ty->owndata) { @@ -1676,6 +1681,7 @@ SWIG_Python_SetModule(swig_module_info *swig_module) { #endif PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule); if (pointer && module) { + ++interpreter_counter; if (PyModule_AddObject(module, "type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer) != 0) { Py_DECREF(pointer); } From a2992fe42e0a462dc9c08bbffa29c6b4fdbd07ff Mon Sep 17 00:00:00 2001 From: benjamin-sch Date: Tue, 8 Feb 2022 09:04:18 +0100 Subject: [PATCH 005/217] always get the type_pointer from capsule instead of using a static variable as the value may change after re-initilization/due to subinterpreters --- Lib/python/pyrun.swg | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index d42dc0f0f..2aef3ad0f 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -1627,19 +1627,19 @@ SWIG_Python_TypeCache(void) { SWIGRUNTIME swig_module_info * SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) { +#ifdef SWIG_LINK_RUNTIME static void *type_pointer = (void *)0; /* first check if module already created */ if (!type_pointer) { -#ifdef SWIG_LINK_RUNTIME type_pointer = SWIG_ReturnGlobalTypeList((void *)0); -#else - type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0); - if (PyErr_Occurred()) { - PyErr_Clear(); - type_pointer = (void *)0; - } -#endif } +#else + void *type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0); + if (PyErr_Occurred()) { + PyErr_Clear(); + type_pointer = (void *)0; + } +#endif return (swig_module_info *) type_pointer; } From 117a917dd155258891a4557526b0888284128d2d Mon Sep 17 00:00:00 2001 From: benjamin-sch Date: Tue, 8 Feb 2022 09:04:30 +0100 Subject: [PATCH 006/217] added comment in CHANGES.current --- CHANGES.current | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 287325483..4bb88acf5 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-02-08: benjamin-sch + [Python] added an interpreter counter to fix deinitialization + issues if multiple subinterpreters are used + 2022-02-07: sethrj #2196 Add alternative syntax for specifying fragments in typemaps. From e60a02941fa0329f4f7c30d6e0b9560b95570bb9 Mon Sep 17 00:00:00 2001 From: sethg Date: Thu, 31 Mar 2022 19:08:46 +0200 Subject: [PATCH 007/217] Update Windows CMake builds to use NuGet package for PCRE2 --- Doc/Manual/Windows.html | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/Doc/Manual/Windows.html b/Doc/Manual/Windows.html index 7a39e88f3..106319687 100644 --- a/Doc/Manual/Windows.html +++ b/Doc/Manual/Windows.html @@ -248,16 +248,9 @@ For fully working build steps always check the Continuous Integration (CI) setup and save to a folder e.g. C:\Tools\Bison
  • - Unfortunately, PCRE2 is not yet available on Nuget. Instead we will use CMake to build and install PCRE2 to C:\Tools\pcre2 using the following commands: -
    -cd C:\
    -SET PATH=C:\Tools\CMake\CMake-win64.3.15.5\bin;%PATH%
    -git clone https://github.com/PhilipHazel/pcre2.git
    -cd pcre2
    -cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_PREFIX=C:/Tools/pcre2 -S . -B build
    -cmake --build build --config Release --target install
    -        
    - Alternatively, set WITH_PCRE=OFF to disable PCRE2 support if you are sure you do not require it. + Install the PCRE2 Nuget package using the following command:
    C:\Tools\nuget install PCRE2 -Version 10.39 -OutputDirectory C:\Tools\pcre2
    . + Note this is a x64 build, if this is not suitable PCRE2 can be built from source using https://github.com/PhilipHazel/pcre2/. + Alternatively, set WITH_PCRE=OFF to disable PCRE2 support if you are sure you do not require it.
  • We will also need the SWIG source code. Either download a zipped archive from GitHub, or if git is installed clone the latest codebase @@ -271,10 +264,12 @@ cmake --build build --config Release --target install architecture. We add the required build tools to the system PATH, and then build a Release version of SWIG. If all runs successfully a new swig.exe should be generated in the C:/swig/install2/bin folder.

    -
    +    
  • + +
     cd C:\swig
     SET PATH=C:\Tools\CMake\CMake-win64.3.15.5\bin;C:\Tools\bison\Bison.3.7.4\bin;%PATH%
    -SET PCRE_ROOT=C:/Tools/pcre2
    +SET PCRE_ROOT=C:\Tools\pcre2\PCRE2.10.39.0
     SET PCRE_PLATFORM=x64
     cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_PREFIX="%CD:\=/%/install2" -DCMAKE_C_FLAGS="/DPCRE2_STATIC" ^
     -DCMAKE_CXX_FLAGS="/DPCRE2_STATIC" -DPCRE2_INCLUDE_DIR=%PCRE_ROOT%/include -DPCRE2_LIBRARY=%PCRE_ROOT%/lib/pcre2-8-static.lib -S . -B build
    @@ -283,9 +278,8 @@ cmake --build build --config Release --target install
     REM to test the exe
     cd install2/bin
     swig.exe -help
    -    
    - - + +

    In addition to Release builds you can create a Debug build using:

    From dbebb2dac81499b34505e6bcd460c90622e4df29 Mon Sep 17 00:00:00 2001 From: sethg Date: Sat, 20 Aug 2022 15:54:27 +0200 Subject: [PATCH 008/217] Add GitHub Action to test Windows builds using Nuget as described in the docs --- .github/workflows/nuget.yml | 47 +++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/nuget.yml diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml new file mode 100644 index 000000000..f42ee784a --- /dev/null +++ b/.github/workflows/nuget.yml @@ -0,0 +1,47 @@ +name: Windows Nuget Build + +on: + push: + paths-ignore: + - 'CHANGES*' + - 'Doc/**' + - 'appveyor.yml' + pull_request: + branches: master + paths-ignore: + - 'CHANGES*' + - 'Doc/**' + - 'appveyor.yml' + +jobs: + build: + + runs-on: windows-2019 + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Install Dependencies + run: | + nuget install CMake-win64 -Version 3.15.5 -OutputDirectory C:\Tools\CMake + nuget install Bison -Version 3.7.4 -OutputDirectory C:\Tools\bison + nuget install PCRE2 -Version 10.39 -OutputDirectory C:\Tools\pcre2 + + - name: Build + shell: cmd + run: | + SET PATH=C:\Tools\CMake\CMake-win64.3.15.5\bin;C:\Tools\bison\Bison.3.7.4\bin;%PATH% + SET PCRE_ROOT=C:\Tools\pcre2\PCRE2.10.39.0 + SET PCRE_PLATFORM=x64 + cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_PREFIX="%CD:\=/%/install2" -DCMAKE_C_FLAGS="/DPCRE2_STATIC" ^ + -DCMAKE_CXX_FLAGS="/DPCRE2_STATIC" -DPCRE2_INCLUDE_DIR=%PCRE_ROOT%/include -DPCRE2_LIBRARY=%PCRE_ROOT%/lib/pcre2-8-static.lib -S . -B build + cmake --build build --config Release --target install + + - name: Test + shell: cmd + working-directory: install2/bin + run: | + swig.exe -help From ae0e62dd1ad8e8f2054ceb1908b9fcceccbc64eb Mon Sep 17 00:00:00 2001 From: sethg Date: Sat, 20 Aug 2022 16:02:45 +0200 Subject: [PATCH 009/217] Test using version rather than help --- .github/workflows/nuget.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index f42ee784a..02100ab94 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -44,4 +44,4 @@ jobs: shell: cmd working-directory: install2/bin run: | - swig.exe -help + swig.exe -version From 720c28f1ed068b17a5df89e2571a1208b79f5e22 Mon Sep 17 00:00:00 2001 From: Markus Friedrich Date: Sun, 18 Sep 2022 19:40:37 +0200 Subject: [PATCH 010/217] Reenable and fix octave horzcat operator test This test was disabled with 0a0743f25cc0bbb395d03a27ac62887c8cbee5cf since it fails with octave 7.2.0 The test function horzcat now uses a variable length argument list to fix this. Before octave 7 it seems to be possible to call a N-argument octave function with > N arguments without any error. With octave 7 this seems no longer to be possible which caused the test failure. --- Examples/octave/operator/@swig_ref/horzcat.m | 9 ++++++--- Examples/octave/operator/runme.m | 5 ++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Examples/octave/operator/@swig_ref/horzcat.m b/Examples/octave/operator/@swig_ref/horzcat.m index 00fdfd5ce..6d4a55b20 100644 --- a/Examples/octave/operator/@swig_ref/horzcat.m +++ b/Examples/octave/operator/@swig_ref/horzcat.m @@ -1,6 +1,9 @@ % test octaves concatenation operator -function ret=horzcat(a, b) - % return the concatenation of two ComplexVal values as a cell array. +function ret=horzcat(varargin) + % return the concatenation of several ComplexVal values as a cell array. % (not really useful but it tests the concatenation of swig_ref objects) - ret={a, b}; + ret={}; + for i=1:length(varargin) + ret{i}=varargin{i}; + end end diff --git a/Examples/octave/operator/runme.m b/Examples/octave/operator/runme.m index 41c2c14a7..ff8b594da 100644 --- a/Examples/octave/operator/runme.m +++ b/Examples/octave/operator/runme.m @@ -47,6 +47,5 @@ if swig_octave_prereq(3,8,0) endif # concatenation operator, note: calls @swig_ref/horzcat.m -# g = [a, b, c]; -# printf("g = %s\n",disp(g)); -# Above temporarily removed as broken in octave-7.2.0, see https://github.com/swig/swig/issues/2353 +g = [a, b, c]; +printf("g = %s\n",disp(g)); From d1b7765838c2145e8c6fb545d46075298f2ee2a8 Mon Sep 17 00:00:00 2001 From: Markus Friedrich Date: Sun, 18 Sep 2022 20:19:39 +0200 Subject: [PATCH 011/217] Extended the documentation for octave operator overloading Octave has more operators than C++. These operators can be overloaded for the type swig_ref using the standard Octave Object Oriented Programming mechanism. This is now added to the documentation. --- Doc/Manual/Octave.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Doc/Manual/Octave.html b/Doc/Manual/Octave.html index de39a1d96..b5168b899 100644 --- a/Doc/Manual/Octave.html +++ b/Doc/Manual/Octave.html @@ -625,6 +625,16 @@ On the C++ side, the default mappings are as follows: Octave can also utilise friend (i.e. non-member) operators with a simple %rename: see the example in the Examples/octave/operator directory.

    +

    +Octave has several operators for which no corresponding C++ operators exist. For example, the Octave code +

    +
    +x=[a,b,c];
    +
    +

    +calls the Octave operator horzcat of the class of a. Hence, if a is of type swig_ref you can write an overload for this operator for your wrapped C++ class by placing a file @swig_ref/horzcat.m in the Octave load path (like for every Octave class, see Creating a Class). This Octave function file is then called whenever the above Octave code is executed for a variable of type swig_ref. +

    +

    30.3.10 Class extension with %extend

    From b9fa8c23bb590c307c42ec277255a927ee654c4e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 17 Sep 2022 14:27:51 +0200 Subject: [PATCH 012/217] Make method wrappers suffix optional and disabled by default Unfortunately the changes of 26bf86322 (Use SWIG-specific for non-overloaded synthesized functions too, 2021-11-09) did break some existing code bases using SWIG as they hardcoded the old wrapper function names. So turn this off by default and add a global variable allowing to enable this, which can be done for a specific language only. This is ugly but, unfortunately, there is no way to use the Language object from the C function Swig_MethodToFunction(), so the only alternative would be to add another parameter to it, but it already has 6 of them, so it wouldn't really be that much better. See #2366, #2368, #2370. --- Source/Modules/lang.cxx | 5 ++++- Source/Modules/main.cxx | 3 +++ Source/Swig/cwrap.c | 8 +++++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index eb61752b8..4abb6b8b5 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -77,6 +77,9 @@ static Hash *classhash; extern int GenerateDefault; extern int ForceExtern; extern int AddExtern; +extern "C" { + extern int UseWrapperSuffix; +} /* import modes */ @@ -1324,7 +1327,7 @@ int Language::staticmemberfunctionHandler(Node *n) { // See Swig_MethodToFunction() for the explanation of this code. if (Getattr(n, "sym:overloaded")) { Append(cname, Getattr(defaultargs ? defaultargs : n, "sym:overname")); - } else { + } else if (UseWrapperSuffix) { Append(cname, "__SWIG"); } diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 9344a7299..44d30e893 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -37,6 +37,9 @@ int Verbose = 0; int AddExtern = 0; int NoExcept = 0; int SwigRuntime = 0; // 0 = no option, 1 = -runtime, 2 = -noruntime +extern "C" { + int UseWrapperSuffix = 0; // If 1, append suffix to non-overloaded functions too. +} /* Suppress warning messages for private inheritance, preprocessor evaluation etc... WARN_PP_EVALUATION 202 diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index 36e69332c..3b20f4e4f 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -15,6 +15,8 @@ #include "swig.h" #include "cparse.h" +extern int UseWrapperSuffix; // from main.cxx + static const char *cresult_variable_name = "result"; static Parm *nonvoid_parms(Parm *p) { @@ -1083,13 +1085,13 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas 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, so make it sufficiently unique by - appending a suffix similar to the one used for overloaded functions to it. + 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 { + } else if (UseWrapperSuffix) { Append(mangled, "__SWIG"); } } From 00190c484f1705906573b0475b5eda97cd0107d9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 17 Sep 2022 16:06:44 +0100 Subject: [PATCH 013/217] Javascript, Octave, R - Improve exceptions for %catches and exception specifications for native types. Now the raised exception contains the string value as the exception message instead of just the C/C++ type of the exception. R exceptions were completely swallowed beforehand --- CHANGES.current | 5 +++++ Examples/javascript/exception/runme.js | 12 ++++++------ Lib/javascript/jsc/javascriptrun.swg | 14 +++++++++----- Lib/javascript/jsc/javascripttypemaps.swg | 2 +- Lib/javascript/v8/javascriptrun.swg | 5 +++++ Lib/javascript/v8/javascripttypemaps.swg | 2 +- Lib/octave/octtypemaps.swg | 2 +- Lib/r/r.swg | 10 +++++++--- 8 files changed, 35 insertions(+), 17 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 6fe039d30..3731b7561 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-09-17: wsfulton + [Javascript, Octave, R] Improve exceptions for %catches and exception + specifications for native types. String exception messages are shown as + the exception message instead of just the type of the exception. + 2022-09-17: wsfulton Add missing typecheck typemaps for std::auto_ptr and std::unique_ptr to fix overloading when using these types. diff --git a/Examples/javascript/exception/runme.js b/Examples/javascript/exception/runme.js index 1001a7111..8c583f81f 100644 --- a/Examples/javascript/exception/runme.js +++ b/Examples/javascript/exception/runme.js @@ -10,7 +10,7 @@ try{ if(error == -1) { console.log("t.unknown() didn't throw"); } else { - console.log("successfully caught throw in Test::unknown()."); + console.log("successfully caught throw in Test::unknown() :" + error); } } @@ -22,7 +22,7 @@ catch(error){ if(error == -1) { console.log("t.simple() did not throw"); } else { - console.log("successfully caught throw in Test::simple()."); + console.log("successfully caught throw in Test::simple() :" + error); } } @@ -33,7 +33,7 @@ try{ if(error == -1) { console.log("t.message() did not throw"); } else { - console.log("successfully caught throw in Test::message()."); + console.log("successfully caught throw in Test::message() :" + error); } } @@ -45,7 +45,7 @@ catch(error){ if(error == -1) { console.log("t.hosed() did not throw"); } else { - console.log("successfully caught throw in Test::hosed()."); + console.log("successfully caught throw in Test::hosed() :" + error + " " + error.code + " " + error.msg); } } @@ -58,7 +58,7 @@ for (var i=1; i<4; i++) { if(error == -1) { console.log("t.multi(" + i + ") did not throw"); } else { - console.log("successfully caught throw in Test::multi()."); + console.log("successfully caught throw in Test::multi() :" + error); } } -} +} diff --git a/Lib/javascript/jsc/javascriptrun.swg b/Lib/javascript/jsc/javascriptrun.swg index 2ffb533f4..4d5a9355b 100644 --- a/Lib/javascript/jsc/javascriptrun.swg +++ b/Lib/javascript/jsc/javascriptrun.swg @@ -7,23 +7,27 @@ #define SWIG_exception(code, msg) do { SWIG_JSC_exception(context, exception, code, msg); SWIG_fail; } while (0) #define SWIG_fail goto fail -SWIGRUNTIME void SWIG_Javascript_Raise(JSContextRef context, JSValueRef *exception, const char* type) { - JSStringRef message = JSStringCreateWithUTF8CString(type); +SWIGRUNTIME void SWIG_Javascript_Raise_ValueRef(JSContextRef context, JSValueRef *exception, JSValueRef valRef) { JSValueRef error_arguments[1]; JSObjectRef exception_object; - JSValueRef exception_value; - exception_value = JSValueMakeString(context, message); /* Converting the result to an object will let JavascriptCore add "sourceURL" (file) and "line" (number) and "message" to the exception, instead of just returning a raw string. This is extremely important for debugging your errors. Using JSObjectMakeError is better than JSValueToObject because the latter only populates "sourceURL" and "line", but not "message" or any others I don't know about. */ - error_arguments[0] = exception_value; + error_arguments[0] = valRef; exception_object = JSObjectMakeError(context, 1, error_arguments, NULL); /* Return the exception_object */ *exception = exception_object; +} + +SWIGRUNTIME void SWIG_Javascript_Raise(JSContextRef context, JSValueRef *exception, const char* msg) { + JSStringRef message = JSStringCreateWithUTF8CString(msg); + JSValueRef exception_value = JSValueMakeString(context, message); + + SWIG_Javascript_Raise_ValueRef(context, exception, exception_value); JSStringRelease(message); } diff --git a/Lib/javascript/jsc/javascripttypemaps.swg b/Lib/javascript/jsc/javascripttypemaps.swg index e8fbbeca8..fd8e7aa2f 100644 --- a/Lib/javascript/jsc/javascripttypemaps.swg +++ b/Lib/javascript/jsc/javascripttypemaps.swg @@ -41,7 +41,7 @@ #define SWIG_SetConstant(name, obj) /* raise */ -#define SWIG_Raise(obj, type, desc) SWIG_Javascript_Raise(context, exception, type) +#define SWIG_Raise(obj, type, desc) SWIG_Javascript_Raise_ValueRef(context, exception, obj) %insert("runtime") %{ #define SWIG_JSC_FROM_DECL_ARGS(arg1) (JSContextRef context, arg1) diff --git a/Lib/javascript/v8/javascriptrun.swg b/Lib/javascript/v8/javascriptrun.swg index 6d3d4e82e..a6ccd1e20 100644 --- a/Lib/javascript/v8/javascriptrun.swg +++ b/Lib/javascript/v8/javascriptrun.swg @@ -96,6 +96,11 @@ SWIGINTERN void SWIG_V8_Raise(const char *msg) { SWIGV8_THROW_EXCEPTION(v8::Exception::Error(SWIGV8_STRING_NEW(msg))); } +SWIGINTERN void SWIG_V8_Raise(SWIGV8_VALUE obj, const char *msg) { + SWIGV8_THROW_EXCEPTION(obj); +} + + /* Note: There are two contexts for handling errors. A static V8ErrorHandler is used in not overloaded methods. diff --git a/Lib/javascript/v8/javascripttypemaps.swg b/Lib/javascript/v8/javascripttypemaps.swg index cb31100c5..c4d341be5 100644 --- a/Lib/javascript/v8/javascripttypemaps.swg +++ b/Lib/javascript/v8/javascripttypemaps.swg @@ -37,7 +37,7 @@ #define SWIG_SetConstant(name, obj) /* raise */ -#define SWIG_Raise(obj, type, desc) SWIG_V8_Raise(type) +#define SWIG_Raise(obj, type, desc) SWIG_V8_Raise(obj, type) /* Include the unified typemap library */ %include diff --git a/Lib/octave/octtypemaps.swg b/Lib/octave/octtypemaps.swg index 4acf8e076..8962d1b71 100644 --- a/Lib/octave/octtypemaps.swg +++ b/Lib/octave/octtypemaps.swg @@ -32,7 +32,7 @@ #define SWIG_SetConstant(name, obj) SWIG_Octave_SetConstant(module_ns,name,obj) // raise -#define SWIG_Octave_Raise(OBJ, TYPE, DESC) error("C++ side threw an exception of type " TYPE) +#define SWIG_Octave_Raise(OBJ, TYPE, DESC) error(OBJ.is_string() ? OBJ.string_value().c_str() : "C++ side threw an exception of type " TYPE) #define SWIG_Raise(obj, type, desc) SWIG_Octave_Raise(obj, type, desc) // Include the unified typemap library diff --git a/Lib/r/r.swg b/Lib/r/r.swg index b1962e5ea..eeabcf4ba 100644 --- a/Lib/r/r.swg +++ b/Lib/r/r.swg @@ -26,9 +26,13 @@ SWIGEXPORT void SWIG_init(void) { assign(name, _obj); %end_block %enddef -%define %raise(obj,type,desc) -return R_NilValue; -%enddef +%runtime %{ +void SWIG_R_Raise(SEXP obj, const char *msg) { + Rf_error(Rf_isString(obj) ? STRING_VALUE(obj) : msg); +} +%} + +#define %raise(OBJ, TYPE, DESC) SWIG_R_Raise(OBJ, "C/C++ exception of type " TYPE); return R_NilValue %insert("sinit") "srun.swg" From d32943b2a97c8da986930c8987a3b24afe9aef4b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 18 Sep 2022 13:12:51 +0100 Subject: [PATCH 014/217] Javascript v8 object to string exceptions improvement --- Examples/javascript/exception/runme.js | 2 +- Lib/javascript/v8/javascriptrun.swg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/javascript/exception/runme.js b/Examples/javascript/exception/runme.js index 8c583f81f..646a33dbe 100644 --- a/Examples/javascript/exception/runme.js +++ b/Examples/javascript/exception/runme.js @@ -45,7 +45,7 @@ catch(error){ if(error == -1) { console.log("t.hosed() did not throw"); } else { - console.log("successfully caught throw in Test::hosed() :" + error + " " + error.code + " " + error.msg); + console.log("successfully caught throw in Test::hosed() :" + error); } } diff --git a/Lib/javascript/v8/javascriptrun.swg b/Lib/javascript/v8/javascriptrun.swg index a6ccd1e20..f76270855 100644 --- a/Lib/javascript/v8/javascriptrun.swg +++ b/Lib/javascript/v8/javascriptrun.swg @@ -97,7 +97,7 @@ SWIGINTERN void SWIG_V8_Raise(const char *msg) { } SWIGINTERN void SWIG_V8_Raise(SWIGV8_VALUE obj, const char *msg) { - SWIGV8_THROW_EXCEPTION(obj); + SWIGV8_THROW_EXCEPTION(v8::Exception::Error(SWIGV8_TO_STRING(obj))); } From 034e2358f9302983cd974746a548d10b45b46cf1 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 18 Sep 2022 19:34:11 +0100 Subject: [PATCH 015/217] Add Racket throws typemaps for char * --- Lib/mzscheme/typemaps.i | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/mzscheme/typemaps.i b/Lib/mzscheme/typemaps.i index 25c7b7707..6c31aea52 100644 --- a/Lib/mzscheme/typemaps.i +++ b/Lib/mzscheme/typemaps.i @@ -290,6 +290,10 @@ REF_MAP(float, SCHEME_REALP, scheme_real_to_double, REF_MAP(double, SCHEME_REALP, scheme_real_to_double, scheme_make_double, real); +%typemap(throws) char * { + scheme_signal_error("%s: %s", FUNC_NAME, $1); +} + /* Void */ %typemap(out) void "$result = scheme_void;" From 4a29229bab06cd5ab21715c93c03e9280feae065 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 18 Sep 2022 19:37:02 +0100 Subject: [PATCH 016/217] Add catches_strings test to test throws char * typemap --- Examples/test-suite/catches_strings.i | 13 +++++++++ Examples/test-suite/common.mk | 1 + .../csharp/catches_strings_runme.cs | 20 +++++++++++++ .../test-suite/d/catches_strings_runme.1.d | 20 +++++++++++++ .../test-suite/d/catches_strings_runme.2.d | 20 +++++++++++++ .../test-suite/go/catches_strings_runme.go | 17 +++++++++++ .../guile/catches_strings_runme.scm | 3 ++ .../java/catches_strings_runme.java | 28 +++++++++++++++++++ .../javascript/catches_strings_runme.js | 15 ++++++++++ .../test-suite/lua/catches_strings_runme.lua | 10 +++++++ .../mzscheme/catches_strings_runme.scm | 11 ++++++++ .../test-suite/ocaml/catches_strings_runme.ml | 8 ++++++ .../test-suite/octave/catches_strings_runme.m | 19 +++++++++++++ .../test-suite/perl5/catches_strings_runme.pl | 10 +++++++ .../test-suite/php/catches_strings_runme.php | 14 ++++++++++ .../python/catches_strings_runme.py | 11 ++++++++ Examples/test-suite/r/catches_strings_runme.R | 15 ++++++++++ .../test-suite/ruby/catches_strings_runme.rb | 18 ++++++++++++ .../schemerunme/catches_strings.scm | 5 ++++ .../scilab/catches_strings_runme.sci | 10 +++++++ .../test-suite/tcl/catches_strings_runme.tcl | 18 ++++++++++++ 21 files changed, 286 insertions(+) create mode 100644 Examples/test-suite/catches_strings.i create mode 100644 Examples/test-suite/csharp/catches_strings_runme.cs create mode 100644 Examples/test-suite/d/catches_strings_runme.1.d create mode 100644 Examples/test-suite/d/catches_strings_runme.2.d create mode 100644 Examples/test-suite/go/catches_strings_runme.go create mode 100644 Examples/test-suite/guile/catches_strings_runme.scm create mode 100644 Examples/test-suite/java/catches_strings_runme.java create mode 100644 Examples/test-suite/javascript/catches_strings_runme.js create mode 100644 Examples/test-suite/lua/catches_strings_runme.lua create mode 100644 Examples/test-suite/mzscheme/catches_strings_runme.scm create mode 100644 Examples/test-suite/ocaml/catches_strings_runme.ml create mode 100644 Examples/test-suite/octave/catches_strings_runme.m create mode 100644 Examples/test-suite/perl5/catches_strings_runme.pl create mode 100644 Examples/test-suite/php/catches_strings_runme.php create mode 100644 Examples/test-suite/python/catches_strings_runme.py create mode 100644 Examples/test-suite/r/catches_strings_runme.R create mode 100644 Examples/test-suite/ruby/catches_strings_runme.rb create mode 100644 Examples/test-suite/schemerunme/catches_strings.scm create mode 100644 Examples/test-suite/scilab/catches_strings_runme.sci create mode 100644 Examples/test-suite/tcl/catches_strings_runme.tcl diff --git a/Examples/test-suite/catches_strings.i b/Examples/test-suite/catches_strings.i new file mode 100644 index 000000000..843246e23 --- /dev/null +++ b/Examples/test-suite/catches_strings.i @@ -0,0 +1,13 @@ +%module catches_strings + +%include + +%catches(const char *) StringsThrower::charstring; + +%inline %{ +struct StringsThrower { + static void charstring() { + throw "charstring message"; + } +}; +%} diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 4df120943..64057fbcb 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -133,6 +133,7 @@ CPP_TEST_CASES += \ bloody_hell \ bools \ catches \ + catches_strings \ cast_operator \ casts \ char_binary \ diff --git a/Examples/test-suite/csharp/catches_strings_runme.cs b/Examples/test-suite/csharp/catches_strings_runme.cs new file mode 100644 index 000000000..6eb159141 --- /dev/null +++ b/Examples/test-suite/csharp/catches_strings_runme.cs @@ -0,0 +1,20 @@ +using System; +using catches_stringsNamespace; + +public class catches_strings_runme { + public static void Main() + { + { + bool exception_thrown = false; + try { + StringsThrower.charstring(); + } catch (ApplicationException e) { + if (!e.Message.Contains("charstring message")) + throw new ApplicationException("incorrect exception message:" + e); + exception_thrown = true; + } + if (!exception_thrown) + throw new ApplicationException("Should have thrown an exception"); + } + } +} diff --git a/Examples/test-suite/d/catches_strings_runme.1.d b/Examples/test-suite/d/catches_strings_runme.1.d new file mode 100644 index 000000000..d42035100 --- /dev/null +++ b/Examples/test-suite/d/catches_strings_runme.1.d @@ -0,0 +1,20 @@ +module catches_strings_runme; + +import catches_strings.catches_strings; +import catches_strings.StringsThrower; +import std.algorithm; + +void main() { + { + bool exception_thrown = false; + try { + StringsThrower.charstring(); + } catch (Exception e) { + if (!canFind(e.msg, "charstring message")) + throw new Exception("incorrect exception message:" ~ e.msg); + exception_thrown = true; + } + if (!exception_thrown) + throw new Exception("Should have thrown an exception"); + } +} diff --git a/Examples/test-suite/d/catches_strings_runme.2.d b/Examples/test-suite/d/catches_strings_runme.2.d new file mode 100644 index 000000000..d42035100 --- /dev/null +++ b/Examples/test-suite/d/catches_strings_runme.2.d @@ -0,0 +1,20 @@ +module catches_strings_runme; + +import catches_strings.catches_strings; +import catches_strings.StringsThrower; +import std.algorithm; + +void main() { + { + bool exception_thrown = false; + try { + StringsThrower.charstring(); + } catch (Exception e) { + if (!canFind(e.msg, "charstring message")) + throw new Exception("incorrect exception message:" ~ e.msg); + exception_thrown = true; + } + if (!exception_thrown) + throw new Exception("Should have thrown an exception"); + } +} diff --git a/Examples/test-suite/go/catches_strings_runme.go b/Examples/test-suite/go/catches_strings_runme.go new file mode 100644 index 000000000..6f0be2c9b --- /dev/null +++ b/Examples/test-suite/go/catches_strings_runme.go @@ -0,0 +1,17 @@ +package main + +import "strings" +import . "swigtests/catches_strings" + +func main() { + exception_thrown := false + func() { + defer func() { + exception_thrown = strings.Index(recover().(string), "charstring message") == 0 + }() + StringsThrowerCharstring() + }() + if !exception_thrown { + panic(0) + } +} diff --git a/Examples/test-suite/guile/catches_strings_runme.scm b/Examples/test-suite/guile/catches_strings_runme.scm new file mode 100644 index 000000000..376f235a3 --- /dev/null +++ b/Examples/test-suite/guile/catches_strings_runme.scm @@ -0,0 +1,3 @@ +(dynamic-call "scm_init_catches_strings_module" (dynamic-link "./libcatches_strings")) +(load "testsuite.scm") +(load "../schemerunme/catches_strings.scm") diff --git a/Examples/test-suite/java/catches_strings_runme.java b/Examples/test-suite/java/catches_strings_runme.java new file mode 100644 index 000000000..0029327d4 --- /dev/null +++ b/Examples/test-suite/java/catches_strings_runme.java @@ -0,0 +1,28 @@ +import catches_strings.*; + +public class catches_strings_runme { + static { + try { + System.loadLibrary("catches_strings"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) throws Throwable + { + { + boolean exception_thrown = false; + try { + StringsThrower.charstring(); + } catch (RuntimeException e) { + if (!e.getMessage().contains("charstring message")) + throw new RuntimeException("incorrect exception message"); + exception_thrown = true; + } + if (!exception_thrown) + throw new RuntimeException("Should have thrown an exception"); + } + } +} diff --git a/Examples/test-suite/javascript/catches_strings_runme.js b/Examples/test-suite/javascript/catches_strings_runme.js new file mode 100644 index 000000000..be37c8710 --- /dev/null +++ b/Examples/test-suite/javascript/catches_strings_runme.js @@ -0,0 +1,15 @@ +var catches_strings = require("catches_strings"); + +exception_thrown = false; +try { + catches_strings.StringsThrower.charstring(); +} catch (e) { + console.log(typeof(e)) + console.log(e.constructor.name) + console.log(typeof(e.message)) + if (!e.message.includes("charstring message")) + throw new Error("incorrect exception message " + e.message); + exception_thrown = true; +} +if (!exception_thrown) + throw new Error("Should have thrown an exception"); diff --git a/Examples/test-suite/lua/catches_strings_runme.lua b/Examples/test-suite/lua/catches_strings_runme.lua new file mode 100644 index 000000000..b23609f11 --- /dev/null +++ b/Examples/test-suite/lua/catches_strings_runme.lua @@ -0,0 +1,10 @@ +require("import") -- the import fn +import("catches_strings") -- import code + +-- catch "undefined" global variables +local env = _ENV -- Lua 5.2 +if not env then env = getfenv () end -- Lua 5.1 +setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end}) + +s, msg = pcall(function() catches_strings.StringsThrower.charstring() end) +assert(s == false and msg:find("charstring message", 1, true)) diff --git a/Examples/test-suite/mzscheme/catches_strings_runme.scm b/Examples/test-suite/mzscheme/catches_strings_runme.scm new file mode 100644 index 000000000..43d313de0 --- /dev/null +++ b/Examples/test-suite/mzscheme/catches_strings_runme.scm @@ -0,0 +1,11 @@ +(load-extension "catches_strings.so") +(require (lib "defmacro.ss")) + +(define exception_thrown "no exception thrown for kin") +(with-handlers ([exn:fail? (lambda (exn) + (set! exception_thrown (exn-message exn)))]) + (StringsThrower-charstring)) +(unless (string-contains? exception_thrown "charstring message") + (error (format "incorrect exception message: ~a" exception_thrown))) + +(exit 0) diff --git a/Examples/test-suite/ocaml/catches_strings_runme.ml b/Examples/test-suite/ocaml/catches_strings_runme.ml new file mode 100644 index 000000000..610f23bd9 --- /dev/null +++ b/Examples/test-suite/ocaml/catches_strings_runme.ml @@ -0,0 +1,8 @@ +open Swig +open Catches_strings + +let _ = + try + ignore (_StringsThrower_charstring (C_void)); assert false + with Failure s -> + assert (s = "charstring message") diff --git a/Examples/test-suite/octave/catches_strings_runme.m b/Examples/test-suite/octave/catches_strings_runme.m new file mode 100644 index 000000000..75ff6c10b --- /dev/null +++ b/Examples/test-suite/octave/catches_strings_runme.m @@ -0,0 +1,19 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + +catches_strings + +exception_thrown = false; +try + StringsThrower.charstring(); +catch e + if (isempty(strfind(e.message, "charstring message"))) + error("incorrect exception message: %s", e.message) + endif + exception_thrown = true; +end_try_catch +if (!exception_thrown) + error("Should have thrown an exception"); +endif diff --git a/Examples/test-suite/perl5/catches_strings_runme.pl b/Examples/test-suite/perl5/catches_strings_runme.pl new file mode 100644 index 000000000..a35095f02 --- /dev/null +++ b/Examples/test-suite/perl5/catches_strings_runme.pl @@ -0,0 +1,10 @@ +use strict; +use warnings; +use Test::More tests => 3; +BEGIN { use_ok('catches_strings') } +require_ok('catches_strings'); + +eval { + catches_strings::StringsThrower::charstring(); +}; +like($@, qr/\bcharstring message/, "Should have thrown an exception"); diff --git a/Examples/test-suite/php/catches_strings_runme.php b/Examples/test-suite/php/catches_strings_runme.php new file mode 100644 index 000000000..ef945f0b5 --- /dev/null +++ b/Examples/test-suite/php/catches_strings_runme.php @@ -0,0 +1,14 @@ +getMessage(), "charstring message", "incorrect exception message: {$e->getMessage()}"); + $exception_thrown = true; +} +check::equal($exception_thrown, true, "Should have thrown an exception"); + +check::done(); diff --git a/Examples/test-suite/python/catches_strings_runme.py b/Examples/test-suite/python/catches_strings_runme.py new file mode 100644 index 000000000..16ad6b056 --- /dev/null +++ b/Examples/test-suite/python/catches_strings_runme.py @@ -0,0 +1,11 @@ +from catches_strings import * + +exception_thrown = False +try: + StringsThrower.charstring() +except RuntimeError as e: + if "charstring message" not in str(e): + raise RuntimeError("incorrect exception message:" + str(e)) + exception_thrown = True +if not exception_thrown: + raise RuntimeError("Should have thrown an exception") diff --git a/Examples/test-suite/r/catches_strings_runme.R b/Examples/test-suite/r/catches_strings_runme.R new file mode 100644 index 000000000..2eb4f3c83 --- /dev/null +++ b/Examples/test-suite/r/catches_strings_runme.R @@ -0,0 +1,15 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + +dyn.load(paste("catches_strings", .Platform$dynlib.ext, sep="")) +source("catches_strings.R") +cacheMetaData(1) + +exception_thrown = FALSE +tryCatch({ + StringsThrower_charstring() +}, error = function(e) { + exception_thrown <<- grepl(e$message, "charstring message", fixed=TRUE) +} +) +unittest(exception_thrown, TRUE) diff --git a/Examples/test-suite/ruby/catches_strings_runme.rb b/Examples/test-suite/ruby/catches_strings_runme.rb new file mode 100644 index 000000000..5af873ef7 --- /dev/null +++ b/Examples/test-suite/ruby/catches_strings_runme.rb @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby + +require 'swig_assert' + +require 'catches_strings' + +exception_thrown = false +begin + Catches_strings::StringsThrower.charstring() +rescue RuntimeError => e + if (!e.to_s.include? "charstring message") + raise RuntimeError, "incorrect exception message: #{e.to_s}" + end + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "Should have thrown an exception" +end diff --git a/Examples/test-suite/schemerunme/catches_strings.scm b/Examples/test-suite/schemerunme/catches_strings.scm new file mode 100644 index 000000000..5be2d2345 --- /dev/null +++ b/Examples/test-suite/schemerunme/catches_strings.scm @@ -0,0 +1,5 @@ +(expect-throw 'swig-exception + (StringsThrower-charstring)) +; TODO: check the exception message + +(exit 0) diff --git a/Examples/test-suite/scilab/catches_strings_runme.sci b/Examples/test-suite/scilab/catches_strings_runme.sci new file mode 100644 index 000000000..4c6718a49 --- /dev/null +++ b/Examples/test-suite/scilab/catches_strings_runme.sci @@ -0,0 +1,10 @@ +exec("swigtest.start", -1); + +ierr = execstr("StringsThrower_charstring()", 'errcatch'); +checkequal(ierr, 20000, "wrong/no exception thrown") +if (strstr(lasterror(), "charstring message") == '') + printf("Should have thrown an exception") + exit(1) +end + +exec("swigtest.quit", -1); diff --git a/Examples/test-suite/tcl/catches_strings_runme.tcl b/Examples/test-suite/tcl/catches_strings_runme.tcl new file mode 100644 index 000000000..1ada351e6 --- /dev/null +++ b/Examples/test-suite/tcl/catches_strings_runme.tcl @@ -0,0 +1,18 @@ + +if [ catch { load ./catches_strings[info sharedlibextension] catches_strings} err_msg ] { + puts stderr "Could not load shared object:\n$err_msg" +} + + +set exception_thrown 0 +if [ catch { + StringsThrower_charstring +} e ] { + if {[string first "charstring message" $e] == -1} { + error "incorrect exception message: $e" + } + set exception_thrown 1 +} +if {!$exception_thrown} { + error "Should have thrown an exception" +} From ed333b6b9720e0569cd3c7ccee8f1fc1b60da9f8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 18 Sep 2022 20:20:21 +0100 Subject: [PATCH 017/217] std::string throws typemaps Go, Guile, Racket, Scilab: Add throws typemaps for std::string so that thrown string exception messages can be seen. Test all language for std::string throws typemaps --- CHANGES.current | 8 +++++ Examples/test-suite/catches_strings.i | 4 +++ .../csharp/catches_strings_runme.cs | 12 +++++++ .../test-suite/d/catches_strings_runme.1.d | 12 +++++++ .../test-suite/d/catches_strings_runme.2.d | 12 +++++++ .../test-suite/go/catches_strings_runme.go | 31 ++++++++++++++----- .../java/catches_strings_runme.java | 13 ++++++++ .../javascript/catches_strings_runme.js | 14 +++++++-- .../test-suite/lua/catches_strings_runme.lua | 3 ++ .../mzscheme/catches_strings_runme.scm | 7 +++++ .../test-suite/ocaml/catches_strings_runme.ml | 6 ++++ .../test-suite/octave/catches_strings_runme.m | 13 ++++++++ .../test-suite/perl5/catches_strings_runme.pl | 7 ++++- .../test-suite/php/catches_strings_runme.php | 9 ++++++ .../python/catches_strings_runme.py | 10 ++++++ Examples/test-suite/r/catches_strings_runme.R | 9 ++++++ .../test-suite/ruby/catches_strings_runme.rb | 13 ++++++++ .../schemerunme/catches_strings.scm | 4 +++ .../scilab/catches_strings_runme.sci | 7 +++++ .../test-suite/tcl/catches_strings_runme.tcl | 13 ++++++++ Lib/go/std_string.i | 6 ++++ Lib/guile/std_string.i | 9 ++++++ Lib/mzscheme/std_string.i | 7 +++++ Lib/scilab/std_string.i | 8 +++++ 24 files changed, 225 insertions(+), 12 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 3731b7561..bb96c581f 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,14 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-09-17: wsfulton + [Go, Guile, Racket, Scilab] Add throws typemaps for std::string so that thrown + string exception messages can be seen. + +2022-09-17: wsfulton + [Racket] Add throws typemaps for char * so that thrown string exception + messages can be seen from Racket. + 2022-09-17: wsfulton [Javascript, Octave, R] Improve exceptions for %catches and exception specifications for native types. String exception messages are shown as diff --git a/Examples/test-suite/catches_strings.i b/Examples/test-suite/catches_strings.i index 843246e23..818a62285 100644 --- a/Examples/test-suite/catches_strings.i +++ b/Examples/test-suite/catches_strings.i @@ -3,11 +3,15 @@ %include %catches(const char *) StringsThrower::charstring; +%catches(std::string) StringsThrower::stdstring; %inline %{ struct StringsThrower { static void charstring() { throw "charstring message"; } + static void stdstring() { + throw std::string("stdstring message"); + } }; %} diff --git a/Examples/test-suite/csharp/catches_strings_runme.cs b/Examples/test-suite/csharp/catches_strings_runme.cs index 6eb159141..e2e336443 100644 --- a/Examples/test-suite/csharp/catches_strings_runme.cs +++ b/Examples/test-suite/csharp/catches_strings_runme.cs @@ -16,5 +16,17 @@ public class catches_strings_runme { if (!exception_thrown) throw new ApplicationException("Should have thrown an exception"); } + { + bool exception_thrown = false; + try { + StringsThrower.stdstring(); + } catch (ApplicationException e) { + if (!e.Message.Contains("stdstring message")) + throw new ApplicationException("incorrect exception message:" + e); + exception_thrown = true; + } + if (!exception_thrown) + throw new ApplicationException("Should have thrown an exception"); + } } } diff --git a/Examples/test-suite/d/catches_strings_runme.1.d b/Examples/test-suite/d/catches_strings_runme.1.d index d42035100..89108355b 100644 --- a/Examples/test-suite/d/catches_strings_runme.1.d +++ b/Examples/test-suite/d/catches_strings_runme.1.d @@ -17,4 +17,16 @@ void main() { if (!exception_thrown) throw new Exception("Should have thrown an exception"); } + { + bool exception_thrown = false; + try { + StringsThrower.stdstring(); + } catch (Exception e) { + if (!canFind(e.msg, "stdstring message")) + throw new Exception("incorrect exception message:" ~ e.msg); + exception_thrown = true; + } + if (!exception_thrown) + throw new Exception("Should have thrown an exception"); + } } diff --git a/Examples/test-suite/d/catches_strings_runme.2.d b/Examples/test-suite/d/catches_strings_runme.2.d index d42035100..89108355b 100644 --- a/Examples/test-suite/d/catches_strings_runme.2.d +++ b/Examples/test-suite/d/catches_strings_runme.2.d @@ -17,4 +17,16 @@ void main() { if (!exception_thrown) throw new Exception("Should have thrown an exception"); } + { + bool exception_thrown = false; + try { + StringsThrower.stdstring(); + } catch (Exception e) { + if (!canFind(e.msg, "stdstring message")) + throw new Exception("incorrect exception message:" ~ e.msg); + exception_thrown = true; + } + if (!exception_thrown) + throw new Exception("Should have thrown an exception"); + } } diff --git a/Examples/test-suite/go/catches_strings_runme.go b/Examples/test-suite/go/catches_strings_runme.go index 6f0be2c9b..b31565c24 100644 --- a/Examples/test-suite/go/catches_strings_runme.go +++ b/Examples/test-suite/go/catches_strings_runme.go @@ -4,14 +4,29 @@ import "strings" import . "swigtests/catches_strings" func main() { - exception_thrown := false - func() { - defer func() { - exception_thrown = strings.Index(recover().(string), "charstring message") == 0 + { + exception_thrown := false + func() { + defer func() { + exception_thrown = strings.Index(recover().(string), "charstring message") == 0 + }() + StringsThrowerCharstring() }() - StringsThrowerCharstring() - }() - if !exception_thrown { - panic(0) + if !exception_thrown { + panic(0) + } + } + + { + exception_thrown := false + func() { + defer func() { + exception_thrown = strings.Index(recover().(string), "stdstring message") == 0 + }() + StringsThrowerStdstring() + }() + if !exception_thrown { + panic(0) + } } } diff --git a/Examples/test-suite/java/catches_strings_runme.java b/Examples/test-suite/java/catches_strings_runme.java index 0029327d4..75e0cf043 100644 --- a/Examples/test-suite/java/catches_strings_runme.java +++ b/Examples/test-suite/java/catches_strings_runme.java @@ -24,5 +24,18 @@ public class catches_strings_runme { if (!exception_thrown) throw new RuntimeException("Should have thrown an exception"); } + + { + boolean exception_thrown = false; + try { + StringsThrower.stdstring(); + } catch (RuntimeException e) { + if (!e.getMessage().contains("stdstring message")) + throw new RuntimeException("incorrect exception message"); + exception_thrown = true; + } + if (!exception_thrown) + throw new RuntimeException("Should have thrown an exception"); + } } } diff --git a/Examples/test-suite/javascript/catches_strings_runme.js b/Examples/test-suite/javascript/catches_strings_runme.js index be37c8710..c99e9a05f 100644 --- a/Examples/test-suite/javascript/catches_strings_runme.js +++ b/Examples/test-suite/javascript/catches_strings_runme.js @@ -4,12 +4,20 @@ exception_thrown = false; try { catches_strings.StringsThrower.charstring(); } catch (e) { - console.log(typeof(e)) - console.log(e.constructor.name) - console.log(typeof(e.message)) if (!e.message.includes("charstring message")) throw new Error("incorrect exception message " + e.message); exception_thrown = true; } if (!exception_thrown) throw new Error("Should have thrown an exception"); + +exception_thrown = false; +try { + catches_strings.StringsThrower.stdstring(); +} catch (e) { + if (!e.message.includes("stdstring message")) + throw new Error("incorrect exception message " + e.message); + exception_thrown = true; +} +if (!exception_thrown) + throw new Error("Should have thrown an exception"); diff --git a/Examples/test-suite/lua/catches_strings_runme.lua b/Examples/test-suite/lua/catches_strings_runme.lua index b23609f11..b0dbaee0e 100644 --- a/Examples/test-suite/lua/catches_strings_runme.lua +++ b/Examples/test-suite/lua/catches_strings_runme.lua @@ -8,3 +8,6 @@ setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i s, msg = pcall(function() catches_strings.StringsThrower.charstring() end) assert(s == false and msg:find("charstring message", 1, true)) + +s, msg = pcall(function() catches_strings.StringsThrower.stdstring() end) +assert(s == false and msg:find("stdstring message", 1, true)) diff --git a/Examples/test-suite/mzscheme/catches_strings_runme.scm b/Examples/test-suite/mzscheme/catches_strings_runme.scm index 43d313de0..745a7cf0a 100644 --- a/Examples/test-suite/mzscheme/catches_strings_runme.scm +++ b/Examples/test-suite/mzscheme/catches_strings_runme.scm @@ -8,4 +8,11 @@ (unless (string-contains? exception_thrown "charstring message") (error (format "incorrect exception message: ~a" exception_thrown))) +(define exception_thrown "no exception thrown for kin") +(with-handlers ([exn:fail? (lambda (exn) + (set! exception_thrown (exn-message exn)))]) + (StringsThrower-stdstring)) +(unless (string-contains? exception_thrown "stdstring message") + (error (format "incorrect exception message: ~a" exception_thrown))) + (exit 0) diff --git a/Examples/test-suite/ocaml/catches_strings_runme.ml b/Examples/test-suite/ocaml/catches_strings_runme.ml index 610f23bd9..901aed0ec 100644 --- a/Examples/test-suite/ocaml/catches_strings_runme.ml +++ b/Examples/test-suite/ocaml/catches_strings_runme.ml @@ -6,3 +6,9 @@ let _ = ignore (_StringsThrower_charstring (C_void)); assert false with Failure s -> assert (s = "charstring message") + +let _ = + try + ignore (_StringsThrower_stdstring (C_void)); assert false + with Failure s -> + assert (s = "stdstring message") diff --git a/Examples/test-suite/octave/catches_strings_runme.m b/Examples/test-suite/octave/catches_strings_runme.m index 75ff6c10b..7e323cc13 100644 --- a/Examples/test-suite/octave/catches_strings_runme.m +++ b/Examples/test-suite/octave/catches_strings_runme.m @@ -17,3 +17,16 @@ end_try_catch if (!exception_thrown) error("Should have thrown an exception"); endif + +exception_thrown = false; +try + StringsThrower.stdstring(); +catch e + if (isempty(strfind(e.message, "stdstring message"))) + error("incorrect exception message: %s", e.message) + endif + exception_thrown = true; +end_try_catch +if (!exception_thrown) + error("Should have thrown an exception"); +endif diff --git a/Examples/test-suite/perl5/catches_strings_runme.pl b/Examples/test-suite/perl5/catches_strings_runme.pl index a35095f02..742b5bcab 100644 --- a/Examples/test-suite/perl5/catches_strings_runme.pl +++ b/Examples/test-suite/perl5/catches_strings_runme.pl @@ -1,6 +1,6 @@ use strict; use warnings; -use Test::More tests => 3; +use Test::More tests => 4; BEGIN { use_ok('catches_strings') } require_ok('catches_strings'); @@ -8,3 +8,8 @@ eval { catches_strings::StringsThrower::charstring(); }; like($@, qr/\bcharstring message/, "Should have thrown an exception"); + +eval { + catches_strings::StringsThrower::stdstring(); +}; +like($@, qr/\bstdstring message/, "Should have thrown an exception"); diff --git a/Examples/test-suite/php/catches_strings_runme.php b/Examples/test-suite/php/catches_strings_runme.php index ef945f0b5..f727ea26a 100644 --- a/Examples/test-suite/php/catches_strings_runme.php +++ b/Examples/test-suite/php/catches_strings_runme.php @@ -11,4 +11,13 @@ try { } check::equal($exception_thrown, true, "Should have thrown an exception"); +$exception_thrown = false; +try { + StringsThrower::stdstring(); +} catch (Exception $e) { + check::str_contains($e->getMessage(), "stdstring message", "incorrect exception message: {$e->getMessage()}"); + $exception_thrown = true; +} +check::equal($exception_thrown, true, "Should have thrown an exception"); + check::done(); diff --git a/Examples/test-suite/python/catches_strings_runme.py b/Examples/test-suite/python/catches_strings_runme.py index 16ad6b056..95b55a264 100644 --- a/Examples/test-suite/python/catches_strings_runme.py +++ b/Examples/test-suite/python/catches_strings_runme.py @@ -9,3 +9,13 @@ except RuntimeError as e: exception_thrown = True if not exception_thrown: raise RuntimeError("Should have thrown an exception") + +exception_thrown = False +try: + StringsThrower.stdstring() +except RuntimeError as e: + if "stdstring message" not in str(e): + raise RuntimeError("incorrect exception message:" + str(e)) + exception_thrown = True +if not exception_thrown: + raise RuntimeError("Should have thrown an exception") diff --git a/Examples/test-suite/r/catches_strings_runme.R b/Examples/test-suite/r/catches_strings_runme.R index 2eb4f3c83..db6783d91 100644 --- a/Examples/test-suite/r/catches_strings_runme.R +++ b/Examples/test-suite/r/catches_strings_runme.R @@ -13,3 +13,12 @@ tryCatch({ } ) unittest(exception_thrown, TRUE) + +exception_thrown = FALSE +tryCatch({ + StringsThrower_stdstring() +}, error = function(e) { + exception_thrown <<- grepl(e$message, "stdstring message", fixed=TRUE) +} +) +unittest(exception_thrown, TRUE) diff --git a/Examples/test-suite/ruby/catches_strings_runme.rb b/Examples/test-suite/ruby/catches_strings_runme.rb index 5af873ef7..fb7466765 100644 --- a/Examples/test-suite/ruby/catches_strings_runme.rb +++ b/Examples/test-suite/ruby/catches_strings_runme.rb @@ -16,3 +16,16 @@ end if (!exception_thrown) raise RuntimeError, "Should have thrown an exception" end + +exception_thrown = false +begin + Catches_strings::StringsThrower.stdstring() +rescue RuntimeError => e + if (!e.to_s.include? "stdstring message") + raise RuntimeError, "incorrect exception message: #{e.to_s}" + end + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "Should have thrown an exception" +end diff --git a/Examples/test-suite/schemerunme/catches_strings.scm b/Examples/test-suite/schemerunme/catches_strings.scm index 5be2d2345..8a83db07c 100644 --- a/Examples/test-suite/schemerunme/catches_strings.scm +++ b/Examples/test-suite/schemerunme/catches_strings.scm @@ -2,4 +2,8 @@ (StringsThrower-charstring)) ; TODO: check the exception message +(expect-throw 'swig-exception + (StringsThrower-stdstring)) +; TODO: check the exception message + (exit 0) diff --git a/Examples/test-suite/scilab/catches_strings_runme.sci b/Examples/test-suite/scilab/catches_strings_runme.sci index 4c6718a49..f9226c728 100644 --- a/Examples/test-suite/scilab/catches_strings_runme.sci +++ b/Examples/test-suite/scilab/catches_strings_runme.sci @@ -7,4 +7,11 @@ if (strstr(lasterror(), "charstring message") == '') exit(1) end +ierr = execstr("StringsThrower_stdstring()", 'errcatch'); +checkequal(ierr, 20000, "wrong/no exception thrown") +if (strstr(lasterror(), "stdstring message") == '') + printf("Should have thrown an exception") + exit(1) +end + exec("swigtest.quit", -1); diff --git a/Examples/test-suite/tcl/catches_strings_runme.tcl b/Examples/test-suite/tcl/catches_strings_runme.tcl index 1ada351e6..e60b660d7 100644 --- a/Examples/test-suite/tcl/catches_strings_runme.tcl +++ b/Examples/test-suite/tcl/catches_strings_runme.tcl @@ -16,3 +16,16 @@ if [ catch { if {!$exception_thrown} { error "Should have thrown an exception" } + +set exception_thrown 0 +if [ catch { + StringsThrower_stdstring +} e ] { + if {[string first "stdstring message" $e] == -1} { + error "incorrect exception message: $e" + } + set exception_thrown 1 +} +if {!$exception_thrown} { + error "Should have thrown an exception" +} diff --git a/Lib/go/std_string.i b/Lib/go/std_string.i index 3abf04cae..35b4a5e46 100644 --- a/Lib/go/std_string.i +++ b/Lib/go/std_string.i @@ -52,6 +52,9 @@ class string; %typemap(godirectorin,fragment="CopyString") string %{ $result = swigCopyString($input) %} +%typemap(throws) string +%{ _swig_gopanic($1.c_str()); %} + %typemap(in) const string & %{ $*1_ltype $1_str($input.p, $input.n); @@ -88,6 +91,9 @@ class string; %typemap(godirectorin,fragment="CopyString") const string & %{ $result = swigCopyString($input) %} +%typemap(throws) const string & +%{ _swig_gopanic($1.c_str()); %} + %typemap(gotype) string * "*string" diff --git a/Lib/guile/std_string.i b/Lib/guile/std_string.i index fbd27547f..c49bfcb07 100644 --- a/Lib/guile/std_string.i +++ b/Lib/guile/std_string.i @@ -83,4 +83,13 @@ namespace std { $result = SWIG_str02scm($1.c_str()); } + %typemap(throws) string { + scm_throw(scm_from_locale_symbol((char *) "swig-exception"), + scm_list_n(SWIG_str02scm($1.c_str()), SCM_UNDEFINED)); + } + + %typemap(throws) const string & { + scm_throw(scm_from_locale_symbol((char *) "swig-exception"), + scm_list_n(SWIG_str02scm($1.c_str()), SCM_UNDEFINED)); + } } diff --git a/Lib/mzscheme/std_string.i b/Lib/mzscheme/std_string.i index b19e8567a..70673eadf 100644 --- a/Lib/mzscheme/std_string.i +++ b/Lib/mzscheme/std_string.i @@ -52,6 +52,13 @@ namespace std { $result = scheme_make_string($1->c_str()); } + %typemap(throws) string { + scheme_signal_error("%s: %s", FUNC_NAME, $1.c_str()); + } + + %typemap(throws) const string & { + scheme_signal_error("%s: %s", FUNC_NAME, $1.c_str()); + } } diff --git a/Lib/scilab/std_string.i b/Lib/scilab/std_string.i index 71ac6d2f4..8736c2a28 100644 --- a/Lib/scilab/std_string.i +++ b/Lib/scilab/std_string.i @@ -37,3 +37,11 @@ SWIG_From_dec(std::string)(std::string pstValue) { } %include + +%typemap(throws, noblock=1) std::string { + SWIG_Scilab_Raise_Ex($1.c_str(), "$type", $&descriptor); +} + +%typemap(throws, noblock=1) const std::string & { + SWIG_Scilab_Raise_Ex($1.c_str(), "$type", $descriptor); +} From e407ccd4fe53400d250d00e0c144b1def2966a2d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 19 Sep 2022 14:48:33 +0100 Subject: [PATCH 018/217] Move SWIG_Octave_Raise into a function For efficiency and to fix some warnings --- Lib/octave/octtypemaps.swg | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Lib/octave/octtypemaps.swg b/Lib/octave/octtypemaps.swg index 8962d1b71..652112312 100644 --- a/Lib/octave/octtypemaps.swg +++ b/Lib/octave/octtypemaps.swg @@ -32,8 +32,15 @@ #define SWIG_SetConstant(name, obj) SWIG_Octave_SetConstant(module_ns,name,obj) // raise -#define SWIG_Octave_Raise(OBJ, TYPE, DESC) error(OBJ.is_string() ? OBJ.string_value().c_str() : "C++ side threw an exception of type " TYPE) -#define SWIG_Raise(obj, type, desc) SWIG_Octave_Raise(obj, type, desc) +%runtime %{ +void SWIG_Octave_Raise(const octave_value &obj, const char *type) { + if (obj.is_string()) + error("%s", obj.string_value().c_str()); + else + error("C++ side threw an exception of type %s", type); +} +%} +#define SWIG_Raise(obj, type, desc) SWIG_Octave_Raise(obj, type) // Include the unified typemap library %include From 623b7d97a79baea923f3a64825d3afbd94c1b24d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 19 Sep 2022 18:19:32 +0100 Subject: [PATCH 019/217] Remove swig.spec file Discussion #2316 --- .gitignore | 1 - CHANGES.current | 5 ++++ Makefile.in | 11 +------- configure.ac | 1 - swig.spec.in | 70 ------------------------------------------------- 5 files changed, 6 insertions(+), 82 deletions(-) delete mode 100644 swig.spec.in diff --git a/.gitignore b/.gitignore index 4fee29d54..307def526 100644 --- a/.gitignore +++ b/.gitignore @@ -81,7 +81,6 @@ Tools/javascript/Makefile config.log config.status preinst-swig -swig.spec # Build Artifacts .dirstamp diff --git a/CHANGES.current b/CHANGES.current index bb96c581f..fd180c31c 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-09-19: wsfulton + #2316 Remove swig.spec file and srcrpm makefile target. These are very out of date + and don't seem to be used by RPM based Linux distributions which have their + own version of swig.spec. + 2022-09-17: wsfulton [Go, Guile, Racket, Scilab] Add throws typemaps for std::string so that thrown string exception messages can be seen. diff --git a/Makefile.in b/Makefile.in index f4cb794d8..a1cb423e4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -340,7 +340,7 @@ clean-ccache: # DISTCLEAN - clean what configure built ##################################################################### -DISTCLEAN-DEAD = config.status config.log config.cache swig.spec Makefile mkmf.log preinst-swig +DISTCLEAN-DEAD = config.status config.log config.cache Makefile mkmf.log preinst-swig distclean-helper: distclean-test-suite distclean-examples distclean-tools distclean-dead @@ -505,15 +505,6 @@ dist: @echo "Tools/mkdist.py @VERSION@ master" @false -srcrpm: - rm -fr $(srpm) $(srpm).src.rpm - echo "TODO: update to use git instead of cvs" - cvs export -d $(srpm) -r HEAD SWIG - cp swig.spec $(srpm) - tar -cf - $(srpm) | gzip --best > $(srpm).tar.gz - rm -fr $(srpm) - rpmbuild -ts $(srpm).tar.gz - # Update the autoconf files for detecting host/targets. Automake will do this in # version 1.10 for our case of not having a top level Makefile.am. Until then we # can fetch them manually and will have to commit them to Git. diff --git a/configure.ac b/configure.ac index b3b1a8e48..db0856dcd 100644 --- a/configure.ac +++ b/configure.ac @@ -2837,7 +2837,6 @@ AC_SUBST(SWIG_LIB_SET) AC_CONFIG_FILES([ Makefile - swig.spec Examples/Makefile Examples/d/example.mk Examples/xml/Makefile diff --git a/swig.spec.in b/swig.spec.in deleted file mode 100644 index 140b96206..000000000 --- a/swig.spec.in +++ /dev/null @@ -1,70 +0,0 @@ -# You can build the package from Git using something like: -# tar -czf swig-@PACKAGE_VERSION@.tar.gz swig-@PACKAGE_VERSION@ && rpmbuild -tb swig-@PACKAGE_VERSION@.tar.gz -# @configure_input@ - -%define ver @PACKAGE_VERSION@ -%define rel 1 -%define prefix /usr -%define home_page http://www.swig.org -%define docprefix %{prefix}/share - -###################################################################### -# Usually, nothing needs to be changed below here between releases -###################################################################### -Summary: Simplified Wrapper and Interface Generator -Name: swig -Version: %{ver} -Release: %{rel} -URL: %{home_page} -Source0: %{name}-%{version}.tar.gz -License: BSD -Group: Development/Tools -BuildRoot: %{_tmppath}/%{name}-root - -%description -SWIG is a software development tool that connects programs written in C and C++ -with a variety of high-level programming languages. SWIG is primarily used with -common scripting languages such as Perl, Python, Tcl/Tk, and Ruby, however the -list of supported languages also includes non-scripting languages such as Java, -OCAML and C#. Also several interpreted and compiled Scheme implementations -(Guile, MzScheme) are supported. SWIG is most commonly used to create -high-level interpreted or compiled programming environments, user interfaces, -and as a tool for testing and prototyping C/C++ software. SWIG can also export -its parse tree in the form of XML. - -%prep -%setup -q -n %{name}-%{version} - -%build -# so we can build package from Git source too -[ ! -r configure ] && ./autogen.sh -%configure -make - -%install -rm -rf ${RPM_BUILD_ROOT} -make DESTDIR=$RPM_BUILD_ROOT install - -%clean -rm -rf ${RPM_BUILD_ROOT} - -%files -%defattr(-,root,root) -%doc ANNOUNCE CHANGES INSTALL LICENSE LICENSE-GPL LICENSE-UNIVERSITIES README RELEASENOTES -%doc Doc/* -%{_bindir}/* -%{prefix}/share/* - -%changelog -* Thu Sep 16 2004 Marcelo Matus -- Small fixes needed after removing the runtime package -* Tue Jul 20 2004 William Fulton -- Update for SWIG-1.3.22 - Removed runtime package -* Wed Mar 03 2004 Robert H De Vries -- Update to work with Fedora Core 1 rpm 4.2.1 -* Wed Jul 24 2002 Sam Liddicott -- Added runtime package of runtime libs -* Mon Sep 10 2001 Tony Seward -- Merge Red Hat's and Dustin Mitchell's .spec files. -- Install all of the examples in the documentation directory. -- Auto create the list of installed files. From ee9e43697149de9c46676370f8a391f9a609fd76 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 20 Sep 2022 22:30:29 +0100 Subject: [PATCH 020/217] Fix -Wmisleading-indentation in Octave wrappers --- Source/Modules/octave.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index e6c55fb0b..e427e60a7 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -835,7 +835,7 @@ public: String *setwname = Swig_name_wrapper(setname); Octave_begin_function(n, setf->def, setname, setwname, true); - Printf(setf->code, "if (!SWIG_check_num_args(\"%s_set\",args.length(),1,1,0)) return octave_value_list();", iname); + Printf(setf->code, "if (!SWIG_check_num_args(\"%s_set\",args.length(),1,1,0)) return octave_value_list();\n", iname); if (is_assignable(n)) { Setattr(n, "wrap:name", setname); if ((tm = Swig_typemap_lookup("varin", n, name, 0))) { From fa00622614d35716b429b12aa9dc1bde8e4b586d Mon Sep 17 00:00:00 2001 From: Frank Schlimbach Date: Wed, 21 Sep 2022 22:00:37 +0100 Subject: [PATCH 021/217] Fixes for classes with the same name in different namespaces Includes the majority of patch #1484. Excludes changes in typepass.cxx for specializations which have no effect on the duplicate_class_name_in_ns testcase, nor the rest of the test-suite. --- CHANGES.current | 7 ++ Examples/test-suite/common.mk | 1 + .../test-suite/duplicate_class_name_in_ns.i | 88 +++++++++++++++++++ Source/CParse/templ.c | 18 ++-- 4 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 Examples/test-suite/duplicate_class_name_in_ns.i diff --git a/CHANGES.current b/CHANGES.current index fd180c31c..6df9d6c5f 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,13 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-09-19: wsfulton + #1484 Fixes for class inheritance with the same name in different namespaces + such as: + + namespace A { class Bar {}; } + namespace B { template class Bar : public A::Bar {}; } + 2022-09-19: wsfulton #2316 Remove swig.spec file and srcrpm makefile target. These are very out of date and don't seem to be used by RPM based Linux distributions which have their diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 64057fbcb..da90dd9fd 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -223,6 +223,7 @@ CPP_TEST_CASES += \ director_void \ director_wombat \ disown \ + duplicate_class_name_in_ns \ dynamic_cast \ empty \ enum_ignore \ diff --git a/Examples/test-suite/duplicate_class_name_in_ns.i b/Examples/test-suite/duplicate_class_name_in_ns.i new file mode 100644 index 000000000..8071f08b7 --- /dev/null +++ b/Examples/test-suite/duplicate_class_name_in_ns.i @@ -0,0 +1,88 @@ +%module duplicate_class_name_in_ns + +%rename(XA) A::X; +%rename(XB) B::X; + +%inline %{ + +namespace A +{ + class X + { + public: + X(){}; + }; + + template + class Foo + { + public: + Foo(){}; + }; + + class Bar + { + public: + Bar(){}; + }; + + template + class Baz + { + public: + Baz(){}; + }; +} + +namespace B +{ + // non-template derived from non-template + class X : public A::X + { + public: + X(){}; + A::X do_x(){return A::X();} + }; + + // template derived from template with different template args + template + class Foo : public A::Foo + { + public: + Foo(){}; + A::Foo do_foo(){return A::Foo();} + }; + + // template derived from non-template + template + class Bar : public A::Bar + { + public: + Bar(){}; + A::Bar do_bar(){return A::Bar();} + }; + + // template derived from template with same template args + template + class Baz : public A::Baz + { + public: + Baz(){}; + A::Baz do_baz(){return A::Baz();} + }; +} + +%} + +%template(AFoo) A::Foo; +%template(ABaz) A::Baz; +%template(BFoo) B::Foo; +%template(BBar) B::Bar; +%template(BBaz) B::Baz; + +%inline %{ + A::X get_a_x() {B::X x; return x.do_x();} + A::Foo get_a_foo() {B::Foo x; return x.do_foo();} + A::Bar get_a_bar() {B::Bar x; return x.do_bar();} + A::Baz get_a_baz() {B::Baz x; return x.do_baz();} +%} diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index 44a606299..8dc6a7315 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -335,6 +335,7 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab if (tp) { Symtab *tsdecl = Getattr(n, "sym:symtab"); + String *tsname = Getattr(n, "sym:name"); while (p && tp) { String *name, *value, *valuestr, *tmp, *tmpr; int sz, i; @@ -376,11 +377,18 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab sz = Len(typelist); for (i = 0; i < sz; i++) { String *s = Getitem(typelist, i); - /* Replace(s,name,value, DOH_REPLACE_ID); */ - /* Printf(stdout,"name = '%s', value = '%s', tbase = '%s', iname='%s' s = '%s' --> ", name, dvalue, tbase, iname, s); */ - SwigType_typename_replace(s, name, dvalue); - SwigType_typename_replace(s, tbase, iname); - /* Printf(stdout,"'%s'\n", s); */ + /* + The approach of 'trivially' replacing template arguments is kind of fragile. + In particular if types with similar name in different namespaces appear. + We will not replace template args if a type/class exists with the same + name which is not a template. + */ + Node * tynode = Swig_symbol_clookup(s, 0); + String *tyname = tynode ? Getattr(tynode, "sym:name") : 0; + if (!tyname || !tsname || !Equal(tyname, tsname) || Getattr(tynode, "templatetype")) { + SwigType_typename_replace(s, name, dvalue); + SwigType_typename_replace(s, tbase, iname); + } } tmp = NewStringf("#%s", name); From eaf468e9e8d3ef17f397ef6bc5e73807a2bf3594 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 22 Sep 2022 18:54:49 +0100 Subject: [PATCH 022/217] C# CreateWStringFromUTF32 optimisation Avoid UTF-32 to UTF-8 conversion then get string from UTF-8 Issue #2369 --- Lib/csharp/wchar.i | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/csharp/wchar.i b/Lib/csharp/wchar.i index 2ada4df75..39b99ee22 100644 --- a/Lib/csharp/wchar.i +++ b/Lib/csharp/wchar.i @@ -49,8 +49,7 @@ static void * SWIG_csharp_wstring_callback(const wchar_t *s) { byte[] buffer = new byte[length * 4]; global::System.Runtime.InteropServices.Marshal.Copy(cString, buffer, 0, buffer.Length); - byte[] utf8buffer = global::System.Text.Encoding.Convert(global::System.Text.Encoding.UTF32, global::System.Text.Encoding.UTF8, buffer); - return global::System.Text.Encoding.Default.GetString(utf8buffer); + return global::System.Text.Encoding.UTF32.GetString(buffer); } static SWIGWStringHelper() { From 95d255e16e1272fb6898ed9fe330f1d66c1f18da Mon Sep 17 00:00:00 2001 From: sethg Date: Tue, 27 Sep 2022 09:48:19 +0200 Subject: [PATCH 023/217] Switch Action and docs to use PowerShell --- .github/workflows/nuget.yml | 21 ++++++++++++++------- Doc/Manual/Windows.html | 32 +++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 02100ab94..f664d306c 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -25,23 +25,30 @@ jobs: submodules: recursive - name: Install Dependencies + shell: powershell run: | nuget install CMake-win64 -Version 3.15.5 -OutputDirectory C:\Tools\CMake nuget install Bison -Version 3.7.4 -OutputDirectory C:\Tools\bison nuget install PCRE2 -Version 10.39 -OutputDirectory C:\Tools\pcre2 - name: Build - shell: cmd + shell: powershell run: | - SET PATH=C:\Tools\CMake\CMake-win64.3.15.5\bin;C:\Tools\bison\Bison.3.7.4\bin;%PATH% - SET PCRE_ROOT=C:\Tools\pcre2\PCRE2.10.39.0 - SET PCRE_PLATFORM=x64 - cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_PREFIX="%CD:\=/%/install2" -DCMAKE_C_FLAGS="/DPCRE2_STATIC" ^ - -DCMAKE_CXX_FLAGS="/DPCRE2_STATIC" -DPCRE2_INCLUDE_DIR=%PCRE_ROOT%/include -DPCRE2_LIBRARY=%PCRE_ROOT%/lib/pcre2-8-static.lib -S . -B build + $env:PATH="C:\Tools\CMake\CMake-win64.3.15.5\bin;C:\Tools\bison\Bison.3.7.4\bin;" + $env:PATH + $PCRE_ROOT="C:\Tools\pcre2\PCRE2.10.39.0" + $PCRE_PLATFORM="x64" + $WORKING_DIR=(Get-Location).ToString() -replace "\\","/" + cmake -G "Visual Studio 16 2019" -A "x64" ` + -DCMAKE_INSTALL_PREFIX="$WORKING_DIR/install2" ` + -DCMAKE_C_FLAGS="/DPCRE2_STATIC" ` + -DCMAKE_CXX_FLAGS="/DPCRE2_STATIC" ` + -DPCRE2_INCLUDE_DIR="$PCRE_ROOT/include" ` + -DPCRE2_LIBRARY="$PCRE_ROOT/lib/pcre2-8-static.lib" ` + -S . -B build cmake --build build --config Release --target install - name: Test - shell: cmd + shell: powershell working-directory: install2/bin run: | swig.exe -version diff --git a/Doc/Manual/Windows.html b/Doc/Manual/Windows.html index 106319687..96518c464 100644 --- a/Doc/Manual/Windows.html +++ b/Doc/Manual/Windows.html @@ -230,7 +230,7 @@ SWIG can also be compiled and run using MSYS2 SWIG can be built using CMake and Visual Studio rather than autotools. As with the other approaches to building SWIG the dependencies need to be installed. The steps below are one of a number of ways of installing the dependencies without requiring Cygwin or MinGW. -For fully working build steps always check the Continuous Integration (CI) setups currently detailed in the Appveyor YAML file. +For fully working build steps always check the Continuous Integration (CI) setups currently detailed in the GitHub Actions YAML file.

      @@ -240,6 +240,7 @@ For fully working build steps always check the Continuous Integration (CI) setup
    1. Install CMake-win64 Nuget package using the following command:
      C:\Tools\nuget install CMake-win64 -Version 3.15.5 -OutputDirectory C:\Tools\CMake
      + Using PowerShell the equivalent syntax is:
      &"C:\Tools\nuget" install CMake-win64 -Version 3.15.5 -OutputDirectory C:\Tools\CMake
      Alternatively you can download CMake from https://cmake.org/download/.
    2. @@ -248,18 +249,18 @@ For fully working build steps always check the Continuous Integration (CI) setup and save to a folder e.g. C:\Tools\Bison
    3. - Install the PCRE2 Nuget package using the following command:
      C:\Tools\nuget install PCRE2 -Version 10.39 -OutputDirectory C:\Tools\pcre2
      . + Install the PCRE2 Nuget package using the following command:
      C:\Tools\nuget install PCRE2 -Version 10.39 -OutputDirectory C:\Tools\pcre2
      Note this is a x64 build, if this is not suitable PCRE2 can be built from source using https://github.com/PhilipHazel/pcre2/. Alternatively, set WITH_PCRE=OFF to disable PCRE2 support if you are sure you do not require it.
    4. We will also need the SWIG source code. Either download a zipped archive from GitHub, or if git is installed clone the latest codebase - using
      git clone https://github.com/swig/swig.git
      + using:
      git clone https://github.com/swig/swig.git
      In this example we are assuming the source code is available at C:\swig
    5. - Now we have all the required dependencies we can build SWIG using the commands below. We are assuming Visual Studio 2019 is installed. For other versions of Visual Studio change "Visual Studio 16 2019 -A x64" to the relevant + Now we have all the required dependencies we can build SWIG using PowerShell and the commands below. We are assuming Visual Studio 2019 is installed. For other versions of Visual Studio change "Visual Studio 16 2019 -A x64" to the relevant Visual Studio Generator and architecture. We add the required build tools to the system PATH, and then build a Release version of SWIG. If all runs successfully a new swig.exe should be generated in the C:/swig/install2/bin folder. @@ -268,16 +269,25 @@ For fully working build steps always check the Continuous Integration (CI) setup

     cd C:\swig
    -SET PATH=C:\Tools\CMake\CMake-win64.3.15.5\bin;C:\Tools\bison\Bison.3.7.4\bin;%PATH%
    -SET PCRE_ROOT=C:\Tools\pcre2\PCRE2.10.39.0
    -SET PCRE_PLATFORM=x64
    -cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_PREFIX="%CD:\=/%/install2" -DCMAKE_C_FLAGS="/DPCRE2_STATIC" ^
    --DCMAKE_CXX_FLAGS="/DPCRE2_STATIC" -DPCRE2_INCLUDE_DIR=%PCRE_ROOT%/include -DPCRE2_LIBRARY=%PCRE_ROOT%/lib/pcre2-8-static.lib -S . -B build
    +
    +$env:PATH="C:\Tools\CMake\CMake-win64.3.15.5\bin;C:\Tools\bison\Bison.3.7.4\bin;" + $env:PATH
    +$PCRE_ROOT="C:\Tools\pcre2\PCRE2.10.39.0"
    +$PCRE_PLATFORM="x64"
    +
    +cmake -G "Visual Studio 16 2019" -A "x64" `
    +-DCMAKE_INSTALL_PREFIX="C:/swig/install2" `
    +-DCMAKE_C_FLAGS="/DPCRE2_STATIC" `
    +-DCMAKE_CXX_FLAGS="/DPCRE2_STATIC" `
    +-DPCRE2_INCLUDE_DIR="$PCRE_ROOT/include" `
    +-DPCRE2_LIBRARY="$PCRE_ROOT/lib/pcre2-8-static.lib" `
    +-S . -B build
    +
     cmake --build build --config Release --target install
     
    -REM to test the exe
    +# to test the exe built correctly
     cd install2/bin
    -swig.exe -help
    +./swig.exe -version
    +./swig.exe -help
     

    From 730e49d379cad28dcbafe63c1d51b1a9bc68b9ee Mon Sep 17 00:00:00 2001 From: sethg Date: Tue, 27 Sep 2022 10:32:16 +0200 Subject: [PATCH 024/217] Move install to separate step --- .github/workflows/nuget.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index f664d306c..706344964 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -45,6 +45,10 @@ jobs: -DPCRE2_INCLUDE_DIR="$PCRE_ROOT/include" ` -DPCRE2_LIBRARY="$PCRE_ROOT/lib/pcre2-8-static.lib" ` -S . -B build + + - name: Install + shell: powershell + run: | cmake --build build --config Release --target install - name: Test From 1d47e11da960af502a09cd9d22a5832fa9413143 Mon Sep 17 00:00:00 2001 From: sethg Date: Tue, 27 Sep 2022 11:01:35 +0200 Subject: [PATCH 025/217] Build and Install are in the same command --- .github/workflows/nuget.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 706344964..ca858b439 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -31,7 +31,7 @@ jobs: nuget install Bison -Version 3.7.4 -OutputDirectory C:\Tools\bison nuget install PCRE2 -Version 10.39 -OutputDirectory C:\Tools\pcre2 - - name: Build + - name: Build and Install shell: powershell run: | $env:PATH="C:\Tools\CMake\CMake-win64.3.15.5\bin;C:\Tools\bison\Bison.3.7.4\bin;" + $env:PATH @@ -45,10 +45,6 @@ jobs: -DPCRE2_INCLUDE_DIR="$PCRE_ROOT/include" ` -DPCRE2_LIBRARY="$PCRE_ROOT/lib/pcre2-8-static.lib" ` -S . -B build - - - name: Install - shell: powershell - run: | cmake --build build --config Release --target install - name: Test From e45d8d0efd26ec5109229074fe5154b9dd47c927 Mon Sep 17 00:00:00 2001 From: sethg Date: Tue, 27 Sep 2022 15:02:58 +0200 Subject: [PATCH 026/217] Split build and install --- .github/workflows/nuget.yml | 9 +++++++-- Doc/Manual/Windows.html | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index ca858b439..7b8174a1e 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -31,7 +31,7 @@ jobs: nuget install Bison -Version 3.7.4 -OutputDirectory C:\Tools\bison nuget install PCRE2 -Version 10.39 -OutputDirectory C:\Tools\pcre2 - - name: Build and Install + - name: Build shell: powershell run: | $env:PATH="C:\Tools\CMake\CMake-win64.3.15.5\bin;C:\Tools\bison\Bison.3.7.4\bin;" + $env:PATH @@ -45,7 +45,12 @@ jobs: -DPCRE2_INCLUDE_DIR="$PCRE_ROOT/include" ` -DPCRE2_LIBRARY="$PCRE_ROOT/lib/pcre2-8-static.lib" ` -S . -B build - cmake --build build --config Release --target install + cmake --build build --config Release + + - name: Install + shell: powershell + run: | + cmake --install build --config Release - name: Test shell: powershell diff --git a/Doc/Manual/Windows.html b/Doc/Manual/Windows.html index 96518c464..c822d2ca3 100644 --- a/Doc/Manual/Windows.html +++ b/Doc/Manual/Windows.html @@ -282,7 +282,8 @@ cmake -G "Visual Studio 16 2019" -A "x64" ` -DPCRE2_LIBRARY="$PCRE_ROOT/lib/pcre2-8-static.lib" ` -S . -B build -cmake --build build --config Release --target install +cmake --build build --config Release +cmake --install build --config Release # to test the exe built correctly cd install2/bin From c3ae2aaafcbdc8391e7c13ec2c7a2527375d4f81 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 28 Sep 2022 11:10:45 +1300 Subject: [PATCH 027/217] [ci] Fix CI to actually test PHP 8.0; add PHP 8.2 The CI job for PHP 8.0 was relying on not specifying a version giving us PHP 8.0, but actually it gives us 8.1 currently. This seems too brittle, so always specify the version explicitly as at worst it means uninstalling and reinstalling PHP packages in a case we could avoid. Also add PHP 8.2 testing. See #2383 --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6fd1ff8b9..35c6d31cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,8 +118,11 @@ jobs: - SWIGLANG: php VER: '7.4' - SWIGLANG: php + VER: '8.0' - SWIGLANG: php VER: '8.1' + - SWIGLANG: php + VER: '8.2' - SWIGLANG: python PY2: 2 - SWIGLANG: python From 303cf392f7b6261f5c6906210057bb21d015ac9e Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 28 Sep 2022 18:50:08 +1300 Subject: [PATCH 028/217] [ci] Temporarily allow PHP 8.0 and 8.2 to fail I'm actively working on fixing them, but meanwhile we don't want PR jobs failing on these. --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35c6d31cb..8722d0d3e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,10 +119,12 @@ jobs: VER: '7.4' - SWIGLANG: php VER: '8.0' + continue-on-error: true # Working on fixing - SWIGLANG: php VER: '8.1' - SWIGLANG: php VER: '8.2' + continue-on-error: true # Working on fixing - SWIGLANG: python PY2: 2 - SWIGLANG: python From e789c9e79994f69b4e411aaee373bcfe8cf6d948 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 28 Sep 2022 18:51:53 +1300 Subject: [PATCH 029/217] [php] Avoid deprecated interpolation syntax Avoid syntax deprecated in PHP 8.2. --- Examples/test-suite/php/director_classes_runme.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Examples/test-suite/php/director_classes_runme.php b/Examples/test-suite/php/director_classes_runme.php index f50544024..d187ed82e 100644 --- a/Examples/test-suite/php/director_classes_runme.php +++ b/Examples/test-suite/php/director_classes_runme.php @@ -90,23 +90,23 @@ function makeCalls($caller, $base) { check::equal($caller->PtrCall($dh)->val, $dh->val, "$bname.Ptr"); check::equal($caller->ConstPtrRefCall($dh)->val, $dh->val, "$bname.ConstPtrRef"); check::equal($caller->FullyOverloadedCall(1), - "${bname}::FullyOverloaded(int)", + "{$bname}::FullyOverloaded(int)", "$bname.FullyOverloaded(int)"); check::equal($caller->FullyOverloadedCall(false), - "${bname}::FullyOverloaded(bool)", + "{$bname}::FullyOverloaded(bool)", "$bname.FullyOverloaded(bool)"); // This next one is TODO for Perl with PerlDerived. check::equal($caller->SemiOverloadedCall(-678), - "${bname}::SemiOverloaded(int)", + "{$bname}::SemiOverloaded(int)", "$bname.SemiOverloaded(int)"); check::equal($caller->SemiOverloadedCall(false), "Base::SemiOverloaded(bool)", "$bname.SemiOverloaded(bool)"); check::equal($caller->DefaultParmsCall(10, 2.2), - "${bname}::DefaultParms(int, double)", + "{$bname}::DefaultParms(int, double)", "$bname.DefaultParms(int, double)"); check::equal($caller->DefaultParmsCall(10), - "${bname}::DefaultParms(int)", + "{$bname}::DefaultParms(int)", "$bname.DefaultParms(int)"); $caller->reset(); } From 91887a10cd6450b5def7a9cb4845533114c7f47b Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 28 Sep 2022 18:53:04 +1300 Subject: [PATCH 030/217] [php] Avoid creating dynamic properties in testsuite This gives a deprecation warning with PHP 8.2. --- Examples/test-suite/php/director_detect_runme.php | 2 ++ Examples/test-suite/php/director_exception_runme.php | 2 ++ Examples/test-suite/php/director_string_runme.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Examples/test-suite/php/director_detect_runme.php b/Examples/test-suite/php/director_detect_runme.php index ae92f7a0c..b9d0a6e0a 100644 --- a/Examples/test-suite/php/director_detect_runme.php +++ b/Examples/test-suite/php/director_detect_runme.php @@ -10,6 +10,8 @@ check::classes(array('A','Foo','Bar')); check::globals(array()); class MyBar extends Bar { + public $val; + function __construct($val = 2) { parent::__construct(); $this->val = $val; diff --git a/Examples/test-suite/php/director_exception_runme.php b/Examples/test-suite/php/director_exception_runme.php index a8f95997f..6f33df028 100644 --- a/Examples/test-suite/php/director_exception_runme.php +++ b/Examples/test-suite/php/director_exception_runme.php @@ -10,6 +10,8 @@ check::classes(array('director_exception','Foo','Exception1','Exception2','Base' check::globals(array()); class MyException extends Exception { + public $msg; + function __construct($a, $b) { $this->msg = $a . $b; } diff --git a/Examples/test-suite/php/director_string_runme.php b/Examples/test-suite/php/director_string_runme.php index 3127f13fb..f146898c3 100644 --- a/Examples/test-suite/php/director_string_runme.php +++ b/Examples/test-suite/php/director_string_runme.php @@ -10,6 +10,8 @@ check::classes(array('A','StringVector')); check::globals(array()); class B extends A { + public $smem; + function get_first() { return parent::get_first() . " world!"; } From 55c95d475cc0deebdc35564aa39875fe03d72c35 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 28 Sep 2022 18:59:31 +1300 Subject: [PATCH 031/217] [php] Adapt swig_ptr_cast_object for PHP 8.2 The required return type has changed from int to an enum, which gives a compiler warning when we assign a function pointer. --- Source/Modules/php.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 964456c08..37a58d752 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -148,6 +148,8 @@ static void SwigPHP_emit_pointer_type_registrations() { Printf(s_wrappers, "/* Implement __toString equivalent, since that worked for the old-style resource wrapped pointers. */\n"); Append(s_wrappers, "#if PHP_MAJOR_VERSION < 8\n"); Printf(s_wrappers, "static int swig_ptr_cast_object(zval *z, zval *retval, int type) {\n"); + Append(s_wrappers, "#elif PHP_MAJOR_VERSION > 8 || PHP_MINOR_VERSION >= 2\n"); + Printf(s_wrappers, "static ZEND_RESULT_CODE swig_ptr_cast_object(zend_object *zobj, zval *retval, int type) {\n"); Append(s_wrappers, "#else\n"); Printf(s_wrappers, "static int swig_ptr_cast_object(zend_object *zobj, zval *retval, int type) {\n"); Append(s_wrappers, "#endif\n"); From 246dd2d787ffe7fda72598415e0768482acf053e Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 28 Sep 2022 19:01:01 +1300 Subject: [PATCH 032/217] [php] Workaround PHP 8.2 header problem We need to include php.h before stdio.h (and probably before most other libc headers). --- Lib/php/phprun.swg | 2 -- Source/Modules/php.cxx | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index a81baf001..538b7e165 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -10,8 +10,6 @@ extern "C" { #endif -#include "php.h" - #if PHP_MAJOR_VERSION < 7 # error These bindings need PHP 7 or later - to generate PHP5 bindings use: SWIG < 4.0.0 and swig -php5 #endif diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 37a58d752..a661a0a91 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -545,6 +545,14 @@ public: Swig_banner(f_begin); + // We need to include php.h before string.h gets included, at least with + // PHP 8.2. Otherwise string.h is included without _GNU_SOURCE being + // included and memrchr() doesn't get declared, and then inline code in + // the PHP headers defines _GNU_SOURCE, includes string.h (which is a + // no op thanks to the include gaurds), then tries to use memrchr() and + // fails. + Append(f_runtime, "#include \"php.h\"\n\n"); + Printf(f_runtime, "\n\n#ifndef SWIGPHP\n#define SWIGPHP\n#endif\n\n"); if (directorsEnabled()) { From cb9c96011a42fb763e447da5869655f50d19f914 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 29 Sep 2022 11:06:56 +1300 Subject: [PATCH 033/217] [php] Suppress -Wdeclaration-after-statement in php.h In PHP 8.2 zend_operators.h contains inline code which triggers this warning and our testsuite uses with option and -Werror. I don't see a good way to only do this within our testsuite, but disabling it globally like this shouldn't be problematic. --- Source/Modules/php.cxx | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index a661a0a91..3f12c0448 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -551,9 +551,28 @@ public: // the PHP headers defines _GNU_SOURCE, includes string.h (which is a // no op thanks to the include gaurds), then tries to use memrchr() and // fails. - Append(f_runtime, "#include \"php.h\"\n\n"); + // + // We also need to suppress -Wdeclaration-after-statement if enabled + // since with PHP 8.2 zend_operators.h contains inline code which triggers + // this warning and our testsuite uses with option and -Werror. I don't + // see a good way to only do this within our testsuite, but disabling + // it globally like this shouldn't be problematic. + Append(f_runtime, + "\n" + "#if defined __GNUC__ && !defined __cplusplus\n" + "# if __GNUC__ >= 4\n" + "# pragma GCC diagnostic push\n" + "# pragma GCC diagnostic ignored \"-Wdeclaration-after-statement\"\n" + "# endif\n" + "#endif\n" + "#include \"php.h\"\n" + "#if defined __GNUC__ && !defined __cplusplus\n" + "# if __GNUC__ >= 4\n" + "# pragma GCC diagnostic pop\n" + "# endif\n" + "#endif\n\n"); - Printf(f_runtime, "\n\n#ifndef SWIGPHP\n#define SWIGPHP\n#endif\n\n"); + Printf(f_runtime, "#ifndef SWIGPHP\n#define SWIGPHP\n#endif\n\n"); if (directorsEnabled()) { Printf(f_runtime, "#define SWIG_DIRECTORS\n"); From 9908f9f310aeadb129b41d14d40de9f2163ffa24 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 29 Sep 2022 13:13:52 +1300 Subject: [PATCH 034/217] [php] Fix testcase segfaults with PHP 8.0 These testcases were segfaulting: prefix director_using_member_scopes virtual_poly The fix here is admittedly a hack - we perform the initialisation of EG(class_table) from CG(class_table) which PHP will do, but hasn't yet. PHP doesn't seem to clearly document which API calls are actually valid in minit or other initialisation contexts, but the code we're generating works with all PHP 7.x and PHP 8.x versions aside from PHP 8.0 so it seems this is a bug in PHP 8.0 rather than that we're doing something invalid, and we need to work with existing PHP 8.0 releases so this hack seems a necessary evil. It will at least have a limited life as PHP 8.0 is only in active support until 2022-11-26, with security support ending a year later. Fixes #2383. --- Lib/php/phpinit.swg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/php/phpinit.swg b/Lib/php/phpinit.swg index 40f7b0766..ae72a10ae 100644 --- a/Lib/php/phpinit.swg +++ b/Lib/php/phpinit.swg @@ -9,4 +9,8 @@ SWIG_php_minit { zend_class_entry SWIGUNUSED internal_ce; SWIG_InitializeModule((void*)&module_number); +#if PHP_MAJOR_VERSION == 8 && PHP_MINOR_VERSION == 0 + /* This hack is needed to avoid segfaults. */ + EG(class_table) = CG(class_table); +#endif %} From 20ed76a27b9419cb7e07c1a4adb444a087555fb4 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 29 Sep 2022 14:09:01 +1300 Subject: [PATCH 035/217] [ci] Revert continue-on-error for PHP 8.0 Tests are now passing there. --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8722d0d3e..5d23a920f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,7 +119,6 @@ jobs: VER: '7.4' - SWIGLANG: php VER: '8.0' - continue-on-error: true # Working on fixing - SWIGLANG: php VER: '8.1' - SWIGLANG: php From 9a4dea06c81448f86187c115912b4062ad1b3031 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 29 Sep 2022 18:14:23 +1300 Subject: [PATCH 036/217] [php] Add php:allowdynamicproperties feature This follows PHP 8.2 deprecating dynamic features. The new feature also provides a clean way to fix the remaining PHP test case failure under PHP 8.2. --- CHANGES.current | 23 ++++++++++++++++ Doc/Manual/Php.html | 48 +++++++++++++++++++++++++++++++++ Examples/test-suite/cpp_basic.i | 2 ++ Source/Modules/php.cxx | 17 +++++++++--- 4 files changed, 86 insertions(+), 4 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 6df9d6c5f..bbdcdfb3b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,29 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-09-29: olly + [PHP] Dynamic class properties are no longer supported by default. + + Historically PHP has supported dynamic class properties and SWIG + has implemented them too (because we implement the magic __get(), + __set() and __isset() methods we need to include explicit + handling). + + PHP 8.2 deprecates dynamic class properties - initially they'll + warn, and apparently they'll not work by default in PHP 9.0: + https://wiki.php.net/rfc/deprecate_dynamic_properties + + In PHP code dynamic properties can be enabled for a class by + marking that class with the attribute `#[AllowDynamicProperties]`. + + To follow this PHP change, in SWIG you now need to specify + `%feature("php:allowdynamicproperties", 1) Foo;` (or + `%feature("php:allowdynamicproperties", 1)` to enable it for + all wrapped classes). Unknown features are ignored, so you can add + it unconditionally and it'll work with older SWIG too. + + *** POTENTIAL INCOMPATIBILITY *** + 2022-09-19: wsfulton #1484 Fixes for class inheritance with the same name in different namespaces such as: diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 72c914656..49d0474f7 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -30,6 +30,7 @@

  • Static Member Variables
  • Static Member Functions
  • Specifying Implemented Interfaces +
  • Dynamic Properties
  • PHP Pragmas, Startup and Shutdown code @@ -843,6 +844,53 @@ so: If there are multiple interfaces, just list them separated by commas.

    + +

    32.2.6.6 Dynamic Properties

    + + +

    +Historically PHP has supported dynamic class properties and SWIG +has implemented them too (because we implement the magic __get(), +__set() and __isset() methods we need to include explicit +handling). +

    + +

    +PHP 8.2 deprecates +dynamic class properties - initially they'll warn, and apparently they'll +not work by default in PHP 9.0. +

    + +

    +In PHP code dynamic properties can be enabled for a class by +marking that class with the attribute #[AllowDynamicProperties]. +

    + +

    +To follow this PHP change, as of SWIG 4.1.0 you now need enable dynamic +properties for any classes you want to support them. To enable for class +Foo: +

    + +
    +%feature("php:allowdynamicproperties", 1) Foo;
    +
    + +

    +or to enable them for all wrapped classes: +

    + +
    +%feature("php:allowdynamicproperties", 1);
    +
    + +

    +Note that unknown features are ignored, so you can add use these +unconditionally in your interface file and it'll work with older SWIG too. +

    + +

    32.2.7 PHP Pragmas, Startup and Shutdown code

    diff --git a/Examples/test-suite/cpp_basic.i b/Examples/test-suite/cpp_basic.i index c39206b13..8c31a9cf0 100644 --- a/Examples/test-suite/cpp_basic.i +++ b/Examples/test-suite/cpp_basic.i @@ -4,6 +4,8 @@ %warnfilter(SWIGWARN_RUBY_WRONG_NAME) global_cint; /* Ruby, wrong constant name */ +%feature("php:allowdynamicproperties", 1) Foo; /* Allow PHP-specific custom property testing in _runme.php */ + %module cpp_basic %newobject Bar::testFoo; diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 3f12c0448..e6b9e991a 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1056,12 +1056,12 @@ public: " if (director) director->swig_disown();\n", "}\n", NIL); } - Printf(f->code, "} else {\n"); if (swig_base) { - Printf(f->code, "PHP_MN(%s%s___set)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", prefix, swig_base); - } else { - Printf(f->code, "add_property_zval_ex(ZEND_THIS, ZSTR_VAL(arg2), ZSTR_LEN(arg2), &args[1]);\n}\n"); + Printf(f->code, "} else {\nPHP_MN(%s%s___set)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n", prefix, swig_base); + } else if (Getattr(class_node, "feature:php:allowdynamicproperties")) { + Printf(f->code, "} else {\nadd_property_zval_ex(ZEND_THIS, ZSTR_VAL(arg2), ZSTR_LEN(arg2), &args[1]);\n"); } + Printf(f->code, "}\n"); Printf(f->code, "fail:\n"); Printf(f->code, "return;\n"); @@ -1777,6 +1777,15 @@ public: if (Getattr(n, "abstracts") && !GetFlag(n, "feature:notabstract")) { Printf(s_oinit, " SWIG_Php_ce_%s->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;\n", class_name); } + if (Getattr(n, "feature:php:allowdynamicproperties")) { + Append(s_oinit, "#ifdef ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES\n"); + Printf(s_oinit, " SWIG_Php_ce_%s->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES;\n", class_name); + Append(s_oinit, "#endif\n"); + } else { + Append(s_oinit, "#ifdef ZEND_ACC_NO_DYNAMIC_PROPERTIES\n"); + Printf(s_oinit, " SWIG_Php_ce_%s->ce_flags |= ZEND_ACC_NO_DYNAMIC_PROPERTIES;\n", class_name); + Append(s_oinit, "#endif\n"); + } String *swig_wrapped = swig_wrapped_interface_ce(); Printv(s_oinit, " zend_do_implement_interface(SWIG_Php_ce_", class_name, ", &", swig_wrapped, ");\n", NIL); From 3bf1da4298a31bf5bd18f1ec1cd07e8725b2d54a Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 29 Sep 2022 18:17:32 +1300 Subject: [PATCH 037/217] Fix a few documentation typos --- CHANGES | 4 ++-- CHANGES.current | 6 +++--- Doc/Manual/R.html | 2 +- Examples/python/import_packages/split_modules/README | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index 3ddd94d2b..1dc87f93e 100644 --- a/CHANGES +++ b/CHANGES @@ -115,7 +115,7 @@ Version 4.0.2 (8 Jun 2020) 2020-01-13: wsfulton [Python] #1595 Python -builtin constructors silently ignored keyword arguments. - Instead of silenty ignoring them, now a "TypeError: f() takes no keyword arguments" + Instead of silently ignoring them, now a "TypeError: f() takes no keyword arguments" exception is thrown if keyword arguments are used. Hence constructors and normal methods/ functions behave in the same way. Note, -keyword should be used with -builtin to obtain keyword argument support. @@ -200,7 +200,7 @@ Version 4.0.1 (21 Aug 2019) VectorOverload(std::vector< Number,std::allocator< Number > >) VectorOverload(std::vector< int,std::allocator< int > >) - The problem was due to some error handling that was not cleared during typehecking. + The problem was due to some error handling that was not cleared during typechecking. In this case an error was not cleared when the elements in the list failed the typecheck for converting to X. Only occurs in Python 3+. diff --git a/CHANGES.current b/CHANGES.current index bbdcdfb3b..2475aa5f4 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -75,17 +75,17 @@ Version 4.1.0 (in progress) the rvalue reference parameter has been moved. The parameter's proxy class that owns the C++ object thus has the underlying pointer set to null so that the (moved from, but still valid) C++ object cannot be used again - and the the object is additionally deleted. + and the object is additionally deleted. *** POTENTIAL INCOMPATIBILITY *** 2022-08-28: wsfulton - [Octave] SWIG now marshalls a C/C++ NULL pointer into the null matrix, []. + [Octave] SWIG now marshals a C/C++ NULL pointer into the null matrix, []. SWIG has always marshalled the null matrix into a NULL pointer; this remains and now we have consistency in representing a NULL pointer. 2022-08-26: wsfulton - [Racket] SWIG now marshalls a C/C++ NULL pointer into a null value by calling + [Racket] SWIG now marshals a C/C++ NULL pointer into a null value by calling scheme_make_null(), so that scheme's null? is true for a NULL C/C++ pointer value. 2022-08-18: wsfulton diff --git a/Doc/Manual/R.html b/Doc/Manual/R.html index 9b05922fd..25d86bdeb 100644 --- a/Doc/Manual/R.html +++ b/Doc/Manual/R.html @@ -321,7 +321,7 @@ and forth between integers.

    The details of enumeration names and contents are stored in hidden R -environments, which are named according the the enumeration name - for +environments, which are named according to the enumeration name - for example, an enumeration colour:

    diff --git a/Examples/python/import_packages/split_modules/README b/Examples/python/import_packages/split_modules/README index d2ca15e7a..41de834c1 100644 --- a/Examples/python/import_packages/split_modules/README +++ b/Examples/python/import_packages/split_modules/README @@ -4,7 +4,7 @@ and the C/C++ part is not in any package at all. Historically SWIG has supported this sort of thing. From SWIG 4.0.0 onwards, split modules are not supported by default. The %module directive needs to be customised with the moduleimport attribute -in order to import the a global C/C++ module. +in order to import a global C/C++ module. vanilla # "plane Jane" module both halves in pkg1 vanilla_split # python 1/2 in pkg1 C 1/2 in global namespace From acbe8ed49ce7ea9cb6bc9310557b433d646174bb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 23 Sep 2022 18:24:06 +0100 Subject: [PATCH 038/217] Runtime tables deterministic ordering (1) Many parts of the runtime tables are alphabetically sorted before for the generated code. This patch sorts the elements within the swig_cast_info lists. Order now is first the elements without a converter then the elements with a converter. For example: new: static swig_cast_info _swigc__p_Foo[] = { {&_swigt__p_Foo, 0, 0, 0}, {&_swigt__p_Bar, _p_BarTo_p_Foo, 0, 0}, {&_swigt__p_Spam, _p_SpamTo_p_Foo, 0, 0}, {0, 0, 0, 0}}; old: static swig_cast_info _swigc__p_Foo[] = { {&_swigt__p_Bar, _p_BarTo_p_Foo, 0, 0}, {&_swigt__p_Foo, 0, 0, 0}, {&_swigt__p_Spam, _p_SpamTo_p_Foo, 0, 0}, {0, 0, 0, 0}}; Previously the order was roughly in the order that the types were parsed, but not necessarily due to the use of internal hash tables which do not have an ordering guarantee. --- Source/Swig/typesys.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 464b89f28..860eafbcf 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -2170,8 +2170,10 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Hash *lthash; Iterator ltiter; Hash *nthash; + String *cast_temp_conv; cast_temp = NewStringEmpty(); + cast_temp_conv = NewStringEmpty(); Printv(types, "static swig_type_info _swigt_", ki.item, " = {", NIL); Append(table_list, ki.item); @@ -2227,13 +2229,14 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Printf(types, "\"%s\", \"%s\", 0, 0, (void*)%s, 0};\n", ki.item, nt, cd); el = SwigType_equivalent_mangle(ki.item, 0, 0); + SortList(el, SwigType_compare_mangled); 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, " {&_swigt_%s, %s, 0, 0},", ei.item, conv); + Printf(cast_temp_conv, " {&_swigt_%s, %s, 0, 0},", ei.item, conv); } else { Printf(cast_temp, " {&_swigt_%s, 0, 0, 0},", ei.item); } @@ -2250,7 +2253,8 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { } } Delete(el); - Printf(cast, "%s{0, 0, 0, 0}};\n", cast_temp); + Printf(cast, "%s%s{0, 0, 0, 0}};\n", cast_temp, cast_temp_conv); + Delete(cast_temp_conv); Delete(cast_temp); Delete(nt); Delete(rt); From 04af10257894607e6dbc7012b241fce6751e709a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 23 Sep 2022 19:58:48 +0100 Subject: [PATCH 039/217] Runtime tables deterministic ordering (2) Output conversion functions used in the type tables in sorted order. Sorted order in this case is the type being converted to. So _p_BarTo_p_Foo comes before _p_BarTo_p_Zoo. Previously the order was roughly in the order that the types were parsed, but not necessarily due to the use of internal hash tables which do not have an ordering guarantee. --- Source/Swig/typesys.c | 63 +++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 860eafbcf..230aa0705 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1963,6 +1963,26 @@ int SwigType_issubtype(const SwigType *t1, const SwigType *t2) { return r; } +/* ----------------------------------------------------------------------------- + * compare_strings() + * + * Helper function to sort a list of strings + * ----------------------------------------------------------------------------- */ +static int compare_strings(const DOH *a, const DOH *b) { + return strcmp((char *) Data(a), (char *) Data(b)); +} + +/* ----------------------------------------------------------------------------- + * sorted_list_from_hash() + * + * Returns a sorted list of the keys in the given hash + * ----------------------------------------------------------------------------- */ +static List *sorted_list_from_hash(Hash *h) { + List *l = Keys(h); + SortList(l, compare_strings); + return l; +} + /* ----------------------------------------------------------------------------- * SwigType_inherit_equiv() * @@ -1976,6 +1996,7 @@ void SwigType_inherit_equiv(File *out) { Hash *sub; Hash *rh; List *rlist; + List *r_resolved_sorted_keys; Iterator rk, bk, ck; if (!conversions) @@ -1983,10 +2004,11 @@ void SwigType_inherit_equiv(File *out) { if (!subclass) subclass = NewHash(); - rk = First(r_resolved); - while (rk.key) { + r_resolved_sorted_keys = sorted_list_from_hash(r_resolved); + rk = First(r_resolved_sorted_keys); + while (rk.item) { /* 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.key); + base = SwigType_base(rk.item); /* Check to see whether the base is recorded in the subclass table */ sub = Getattr(subclass, base); Delete(base); @@ -1997,26 +2019,26 @@ void SwigType_inherit_equiv(File *out) { /* This type has subclasses. We now need to walk through these subtypes and generate pointer conversion functions */ - rh = Getattr(r_resolved, rk.key); + rh = Getattr(r_resolved, rk.item); rlist = NewList(); for (ck = First(rh); ck.key; ck = Next(ck)) { Append(rlist, ck.key); } - /* Printf(stdout,"rk.key = '%s'\n", rk.key); + /* Printf(stdout,"rk.item = '%s'\n", rk.item); Printf(stdout,"rh = %p '%s'\n", rh,rh); */ bk = First(sub); while (bk.key) { - prefix = SwigType_prefix(rk.key); + prefix = SwigType_prefix(rk.item); Append(prefix, bk.key); /* Printf(stdout,"set %p = '%s' : '%s'\n", rh, SwigType_manglestr(prefix),prefix); */ mprefix = SwigType_manglestr(prefix); Setattr(rh, mprefix, prefix); - mkey = SwigType_manglestr(rk.key); + 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.key, 0); + String *lkey = SwigType_lstr(rk.item, 0); String *lprefix = SwigType_lstr(prefix, 0); Hash *subhash = Getattr(sub, bk.key); String *convcode = Getattr(subhash, "convcode"); @@ -2082,26 +2104,9 @@ void SwigType_inherit_equiv(File *out) { rk = Next(rk); Delete(rlist); } + Delete(r_resolved_sorted_keys); } -/* Helper function to sort the mangled list */ -static int SwigType_compare_mangled(const DOH *a, const DOH *b) { - return strcmp((char *) Data(a), (char *) Data(b)); -} - -/* ----------------------------------------------------------------------------- - * SwigType_get_sorted_mangled_list() - * - * Returns the sorted list of mangled type names that should be exported into the - * wrapper file. - * ----------------------------------------------------------------------------- */ -List *SwigType_get_sorted_mangled_list(void) { - List *l = Keys(r_mangled); - SortList(l, SwigType_compare_mangled); - return l; -} - - /* ----------------------------------------------------------------------------- * SwigType_type_table() * @@ -2157,7 +2162,7 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Printf(f_forward, "\n/* -------- TYPES TABLE (BEGIN) -------- */\n\n"); - mangled_list = SwigType_get_sorted_mangled_list(); + mangled_list = sorted_list_from_hash(r_mangled); for (ki = First(mangled_list); ki.item; ki = Next(ki)) { List *el; Iterator ei; @@ -2229,7 +2234,7 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Printf(types, "\"%s\", \"%s\", 0, 0, (void*)%s, 0};\n", ki.item, nt, cd); el = SwigType_equivalent_mangle(ki.item, 0, 0); - SortList(el, SwigType_compare_mangled); + SortList(el, compare_strings); for (ei = First(el); ei.item; ei = Next(ei)) { String *ckey; String *conv; @@ -2260,7 +2265,7 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Delete(rt); } /* print the tables in the proper order */ - SortList(table_list, SwigType_compare_mangled); + SortList(table_list, compare_strings); 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++); From 5fdb591a62c7427b8a503ff43d1943c38b41a19f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 23 Sep 2022 20:12:23 +0100 Subject: [PATCH 040/217] Runtime tables deterministic ordering (3) Output conversion functions used in the type tables in sorted order. Sorted order in this case is the type being converted from. So _p_BarTo_p_Foo comes before _p_ZarTo_p_Foo. Previously the order was roughly in the order that the types were parsed, but not necessarily due to the use of internal hash tables which do not have an ordering guarantee. --- Source/Swig/typesys.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 230aa0705..f7fc73026 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -2007,6 +2007,7 @@ void SwigType_inherit_equiv(File *out) { r_resolved_sorted_keys = sorted_list_from_hash(r_resolved); 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 */ @@ -2027,10 +2028,11 @@ void SwigType_inherit_equiv(File *out) { /* Printf(stdout,"rk.item = '%s'\n", rk.item); Printf(stdout,"rh = %p '%s'\n", rh,rh); */ - bk = First(sub); - while (bk.key) { + sub_sorted_keys = sorted_list_from_hash(sub); + bk = First(sub_sorted_keys); + while (bk.item) { prefix = SwigType_prefix(rk.item); - Append(prefix, bk.key); + Append(prefix, bk.item); /* Printf(stdout,"set %p = '%s' : '%s'\n", rh, SwigType_manglestr(prefix),prefix); */ mprefix = SwigType_manglestr(prefix); Setattr(rh, mprefix, prefix); @@ -2040,7 +2042,7 @@ void SwigType_inherit_equiv(File *out) { 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.key); + 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 */ @@ -2101,6 +2103,7 @@ void SwigType_inherit_equiv(File *out) { Delete(mkey); bk = Next(bk); } + Delete(sub_sorted_keys); rk = Next(rk); Delete(rlist); } From 15b2ec53e33e375d0c8976571087331aa7012817 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 26 Sep 2022 18:14:19 +0100 Subject: [PATCH 041/217] Runtime tables deterministic ordering (4) Output C/C++ type strings (| separated) in swig_type_info tables in fixed order. The types are output in alphabetically sorted order, with an exception. The final type is a fully resolved type, but does not necessarily include default template parameters. This type is the one used by SWIG_TypePrettyName which is commonly used to display a type when the wrong type is passed in as a parameter. Previously the order was not very deterministic due to the use of internal hash tables which do not have an ordering guarantee. --- CHANGES.current | 7 ++++++ Lib/swigrun.swg | 6 ++--- Source/Swig/typesys.c | 55 ++++++++++++++++++++++++++++++------------- 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 2475aa5f4..ac2c2d099 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,13 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-09-29: wsfulton + #2303 Type tables are now output in a fixed order whereas previously + the order may change with any minor input code change. This shouldn't + affect users except SWIG_TypePrettyName may output a different C/C++ + typedef to a type - it's used mostly for showing errors when the type + passed to a function is wrong. + 2022-09-29: olly [PHP] Dynamic class properties are no longer supported by default. diff --git a/Lib/swigrun.swg b/Lib/swigrun.swg index 9ec98ccf2..f632c4cb6 100644 --- a/Lib/swigrun.swg +++ b/Lib/swigrun.swg @@ -358,9 +358,9 @@ SWIG_TypeName(const swig_type_info *ty) { SWIGRUNTIME const char * SWIG_TypePrettyName(const swig_type_info *type) { /* The "str" field contains the equivalent pretty names of the - type, separated by vertical-bar characters. We choose - to print the last name, as it is often (?) the most - specific. */ + type, separated by vertical-bar characters. Choose the last + name. It should be the most specific; a fully resolved name + but not necessarily with default template parameters expanded. */ if (!type) return NULL; if (type->str != NULL) { const char *last_name = type->str; diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index f7fc73026..cadceb3eb 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -2136,22 +2136,22 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { /*#define DEBUG 1*/ #ifdef DEBUG Printf(stdout, "---r_mangled---\n"); - Printf(stdout, "%s\n", r_mangled); + Swig_print(r_mangled, 2); Printf(stdout, "---r_resolved---\n"); - Printf(stdout, "%s\n", r_resolved); + Swig_print(r_resolved, 2); Printf(stdout, "---r_ltype---\n"); - Printf(stdout, "%s\n", r_ltype); + Swig_print(r_ltype, 2); Printf(stdout, "---subclass---\n"); - Printf(stdout, "%s\n", subclass); + Swig_print(subclass, 2); Printf(stdout, "---conversions---\n"); - Printf(stdout, "%s\n", conversions); + Swig_print(conversions, 2); Printf(stdout, "---r_clientdata---\n"); - Printf(stdout, "%s\n", r_clientdata); + Swig_print(r_clientdata, 2); #endif table = NewStringEmpty(); @@ -2169,8 +2169,6 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { for (ki = First(mangled_list); ki.item; ki = Next(ki)) { List *el; Iterator ei; - SwigType *lt; - SwigType *rt = 0; String *nt; String *ln; String *rn; @@ -2179,6 +2177,8 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Iterator ltiter; Hash *nthash; String *cast_temp_conv; + String *resolved_lstr = 0; + List *ntlist; cast_temp = NewStringEmpty(); cast_temp_conv = NewStringEmpty(); @@ -2197,8 +2197,8 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { nthash = NewHash(); ltiter = First(lthash); while (ltiter.key) { - lt = ltiter.key; - rt = SwigType_typedef_resolve_all(lt); + 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); @@ -2208,6 +2208,12 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { 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); @@ -2217,22 +2223,38 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Delete(dt); Delete(dn); } + Delete(rt); + Delete(rn); + Delete(ln); ltiter = Next(ltiter); } /* now build nt */ - ltiter = First(nthash); + ntlist = sorted_list_from_hash(nthash); + ltiter = First(ntlist); nt = 0; - while (ltiter.key) { - if (nt) { - Printf(nt, "|%s", ltiter.key); - } else { - nt = NewString(ltiter.key); + 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); @@ -2265,7 +2287,6 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Delete(cast_temp_conv); Delete(cast_temp); Delete(nt); - Delete(rt); } /* print the tables in the proper order */ SortList(table_list, compare_strings); From cd46d65bebf3dc38b0ef885aafff652cd9c1345b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 29 Sep 2022 19:29:30 +0100 Subject: [PATCH 042/217] Testcase overloading warning fix --- Examples/test-suite/cpp11_type_traits.i | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Examples/test-suite/cpp11_type_traits.i b/Examples/test-suite/cpp11_type_traits.i index 715ce99fa..45077f728 100644 --- a/Examples/test-suite/cpp11_type_traits.i +++ b/Examples/test-suite/cpp11_type_traits.i @@ -4,6 +4,8 @@ // This doesn't really directly test functionality in type_traits as it doesn't provide // much for use by target languages, rather it tests usage of it. +%warnfilter(509) elaborate; + %inline %{ #include From eaaf89360548af67f3c53137e9817a21cd9575aa Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 7 Jul 2022 11:50:00 +1200 Subject: [PATCH 043/217] Adjust the DOH string hash function The one we're currently using only considers the last five characters plus the least significant bit of the last-but-sixth character, which unsurprisingly generates a lot of many-way collisions. This change seems to give about a 4% reduction in wallclock time for processing li_std_list_wrap.i from the testsuite for Python. The hash collision rate for this example drops from 39% to 0! Closes #2303 --- CHANGES.current | 11 +++++++++++ Source/DOH/string.c | 20 ++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index ac2c2d099..bfe3f8b0a 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,17 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-09-29: olly + #2303 SWIG's internal hash tables now use a better hash function. + + The old hash function only considerd the last five characters + plus the least significant bit of the last-but-sixth character, + which as you might guess generated a lot of many-way collisions. + + This change seems to give about a 4% reduction in wallclock time + for processing li_std_list_wrap.i from the testsuite for Python. + The hash collision rate for this example drops from 39% to 0! + 2022-09-29: wsfulton #2303 Type tables are now output in a fixed order whereas previously the order may change with any minor input code change. This shouldn't diff --git a/Source/DOH/string.c b/Source/DOH/string.c index 543c3e3f8..8f321508e 100644 --- a/Source/DOH/string.c +++ b/Source/DOH/string.c @@ -180,19 +180,27 @@ static int String_hash(DOH *so) { if (s->hashkey >= 0) { return s->hashkey; } else { - char *c = s->str; + /* We use the djb2 hash function: https://theartincode.stanis.me/008-djb2/ + * + * One difference is we use initial seed 0. It seems the usual seed value + * is intended to help spread out hash values, which is beneficial if + * linear probing is used but DOH Hash uses a chain of buckets instead, and + * grouped hash values are probably more cache friendly. In tests using + * 0 seems slightly faster anyway. + */ + const char *c = s->str; unsigned int len = s->len > 50 ? 50 : s->len; unsigned int h = 0; unsigned int mlen = len >> 2; unsigned int i = mlen; for (; i; --i) { - h = (h << 5) + *(c++); - h = (h << 5) + *(c++); - h = (h << 5) + *(c++); - h = (h << 5) + *(c++); + h = h + (h << 5) + *(c++); + h = h + (h << 5) + *(c++); + h = h + (h << 5) + *(c++); + h = h + (h << 5) + *(c++); } for (i = len - (mlen << 2); i; --i) { - h = (h << 5) + *(c++); + h = h + (h << 5) + *(c++); } h &= 0x7fffffff; s->hashkey = (int)h; From 216b47320b1bed4588b9166bd0b29b2d2784236f Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 30 Sep 2022 09:20:19 +1300 Subject: [PATCH 044/217] [ci] Revert continue-on-error for PHP 8.2 Tests are now passing there. --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d23a920f..35c6d31cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,7 +123,6 @@ jobs: VER: '8.1' - SWIGLANG: php VER: '8.2' - continue-on-error: true # Working on fixing - SWIGLANG: python PY2: 2 - SWIGLANG: python From 77b08daca7df1ec04a886983c634a6e2ba545031 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 30 Sep 2022 22:48:04 +0100 Subject: [PATCH 045/217] Add DohSortedKeys function Returns a list of sorted keys in a DOH Hash. --- Doc/Manual/Extending.html | 8 ++++++++ Source/DOH/base.c | 12 ++++++++++++ Source/DOH/doh.h | 3 +++ Source/Swig/typesys.c | 32 ++++++-------------------------- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/Doc/Manual/Extending.html b/Doc/Manual/Extending.html index cbb78bef8..27e2fcc65 100644 --- a/Doc/Manual/Extending.html +++ b/Doc/Manual/Extending.html @@ -1244,6 +1244,14 @@ if an object was removed, 0 otherwise. Returns the list of hash table keys. +

    +List *SortedKeys(Hash *h, int (*cmp) (const DOH *, const DOH *)) +

    + +
    +Returns the list of sorted hash table keys. +
    +

    40.5.3 Lists

    diff --git a/Source/DOH/base.c b/Source/DOH/base.c index 442ea3934..602c79087 100644 --- a/Source/DOH/base.c +++ b/Source/DOH/base.c @@ -374,6 +374,18 @@ DOH *DohKeys(DOH *obj) { return 0; } +/* ----------------------------------------------------------------------------- + * DohSortedKeys() + * ----------------------------------------------------------------------------- */ + +DOH *DohSortedKeys(DOH *obj, int (*cmp) (const DOH *, const DOH *)) { + DOHList *keys = DohKeys(obj); + if (keys) { + DohSortList(keys, cmp); + } + return keys; +} + /* ----------------------------------------------------------------------------- * DohGetInt() * ----------------------------------------------------------------------------- */ diff --git a/Source/DOH/doh.h b/Source/DOH/doh.h index 4ee0dfffa..13e9cc23d 100644 --- a/Source/DOH/doh.h +++ b/Source/DOH/doh.h @@ -52,6 +52,7 @@ #define DohSetattr DOH_NAMESPACE(Setattr) #define DohDelattr DOH_NAMESPACE(Delattr) #define DohKeys DOH_NAMESPACE(Keys) +#define DohSortedKeys DOH_NAMESPACE(SortedKeys) #define DohGetInt DOH_NAMESPACE(GetInt) #define DohGetDouble DOH_NAMESPACE(GetDouble) #define DohGetChar DOH_NAMESPACE(GetChar) @@ -201,6 +202,7 @@ extern int DohSetattr(DOH *obj, const DOHString_or_char *name, const DOHObj_or_c extern int DohDelattr(DOH *obj, const DOHString_or_char *name); extern int DohCheckattr(DOH *obj, const DOHString_or_char *name, const DOHString_or_char *value); extern DOH *DohKeys(DOH *obj); +extern DOH *DohSortedKeys(DOH *obj, int (*cmp) (const DOH *, const DOH *)); extern int DohGetInt(DOH *obj, const DOHString_or_char *name); extern void DohSetInt(DOH *obj, const DOHString_or_char *name, int); extern double DohGetDouble(DOH *obj, const DOHString_or_char *name); @@ -444,6 +446,7 @@ extern void DohMemoryDebug(void); #define FileErrorDisplay DohFileErrorDisplay #define NewVoid DohNewVoid #define Keys DohKeys +#define SortedKeys DohSortedKeys #define Strcmp DohStrcmp #define Strncmp DohStrncmp #define Strstr DohStrstr diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index cadceb3eb..02137d8bd 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1963,26 +1963,6 @@ int SwigType_issubtype(const SwigType *t1, const SwigType *t2) { return r; } -/* ----------------------------------------------------------------------------- - * compare_strings() - * - * Helper function to sort a list of strings - * ----------------------------------------------------------------------------- */ -static int compare_strings(const DOH *a, const DOH *b) { - return strcmp((char *) Data(a), (char *) Data(b)); -} - -/* ----------------------------------------------------------------------------- - * sorted_list_from_hash() - * - * Returns a sorted list of the keys in the given hash - * ----------------------------------------------------------------------------- */ -static List *sorted_list_from_hash(Hash *h) { - List *l = Keys(h); - SortList(l, compare_strings); - return l; -} - /* ----------------------------------------------------------------------------- * SwigType_inherit_equiv() * @@ -2004,7 +1984,7 @@ void SwigType_inherit_equiv(File *out) { if (!subclass) subclass = NewHash(); - r_resolved_sorted_keys = sorted_list_from_hash(r_resolved); + r_resolved_sorted_keys = SortedKeys(r_resolved, Strcmp); rk = First(r_resolved_sorted_keys); while (rk.item) { List *sub_sorted_keys; @@ -2028,7 +2008,7 @@ void SwigType_inherit_equiv(File *out) { /* Printf(stdout,"rk.item = '%s'\n", rk.item); Printf(stdout,"rh = %p '%s'\n", rh,rh); */ - sub_sorted_keys = sorted_list_from_hash(sub); + sub_sorted_keys = SortedKeys(sub, Strcmp); bk = First(sub_sorted_keys); while (bk.item) { prefix = SwigType_prefix(rk.item); @@ -2165,7 +2145,7 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Printf(f_forward, "\n/* -------- TYPES TABLE (BEGIN) -------- */\n\n"); - mangled_list = sorted_list_from_hash(r_mangled); + mangled_list = SortedKeys(r_mangled, Strcmp); for (ki = First(mangled_list); ki.item; ki = Next(ki)) { List *el; Iterator ei; @@ -2231,7 +2211,7 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { } /* now build nt */ - ntlist = sorted_list_from_hash(nthash); + ntlist = SortedKeys(nthash, Strcmp); ltiter = First(ntlist); nt = 0; while (ltiter.item) { @@ -2259,7 +2239,7 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Printf(types, "\"%s\", \"%s\", 0, 0, (void*)%s, 0};\n", ki.item, nt, cd); el = SwigType_equivalent_mangle(ki.item, 0, 0); - SortList(el, compare_strings); + SortList(el, Strcmp); for (ei = First(el); ei.item; ei = Next(ei)) { String *ckey; String *conv; @@ -2289,7 +2269,7 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Delete(nt); } /* print the tables in the proper order */ - SortList(table_list, compare_strings); + 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++); From e147f2af69dac2d4085a55fc9a12532639b990c4 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 30 Sep 2022 23:04:06 +0100 Subject: [PATCH 046/217] Generate richcompare switch statements in sorted order --- Source/Modules/python.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 2d2ac4f5f..9352424f2 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -4073,14 +4073,16 @@ public: Printf(f, " PyTuple_SET_ITEM(tuple, 0, other);\n"); Printf(f, " Py_XINCREF(other);\n"); } - Iterator rich_iter = First(richcompare); + List *richcompare_list = SortedKeys(richcompare, 0); + Iterator rich_iter = First(richcompare_list); if (rich_iter.item) { Printf(f, " switch (op) {\n"); for (; rich_iter.item; rich_iter = Next(rich_iter)) - Printf(f, " case %s : result = %s(self, %s); break;\n", rich_iter.key, rich_iter.item, funpack ? "other" : "tuple"); + Printf(f, " case %s : result = %s(self, %s); break;\n", rich_iter.item, Getattr(richcompare, rich_iter.item), funpack ? "other" : "tuple"); Printv(f, " default : break;\n", NIL); Printf(f, " }\n"); } + Delete(richcompare_list); Printv(f, " if (!result) {\n", NIL); Printv(f, " if (SwigPyObject_Check(self) && SwigPyObject_Check(other)) {\n", NIL); Printv(f, " result = SwigPyObject_richcompare((SwigPyObject *)self, (SwigPyObject *)other, op);\n", NIL); From 929cfde883eac37bf2c2f439a0d9163dcf570376 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 30 Sep 2022 23:21:39 +0100 Subject: [PATCH 047/217] C# CreateWStringFromUTF32 optimisation Avoid UTF-32 to UTF-8 conversion then get string from UTF-8 Missing change that should have gone into eaf468e9e8d3ef17f397ef6bc5e73807a2bf3594 --- Lib/csharp/wchar.i | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Lib/csharp/wchar.i b/Lib/csharp/wchar.i index 39b99ee22..f1e0d5a26 100644 --- a/Lib/csharp/wchar.i +++ b/Lib/csharp/wchar.i @@ -101,9 +101,7 @@ static SWIG_CSharpWStringExceptionHelperCallback SWIG_csharp_ApplicationExceptio return string.Empty; byte[] buffer = new byte[length * 4]; - global::System.Runtime.InteropServices.Marshal.Copy(cString, buffer, 0, buffer.Length); - byte[] utf8buffer = global::System.Text.Encoding.Convert(global::System.Text.Encoding.UTF32, global::System.Text.Encoding.UTF8, buffer); - return global::System.Text.Encoding.Default.GetString(utf8buffer); + return global::System.Text.Encoding.UTF32.GetString(buffer); } static void SetPendingApplicationExceptionUTF16([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { From c7e1e64538d568ce66c6ac261fb63d2ef9bb2239 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sat, 23 Jul 2022 14:51:10 +1200 Subject: [PATCH 048/217] Prefer !Equal() to Cmp() != 0 --- Source/Modules/php.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index e6b9e991a..d392e3a89 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -869,7 +869,7 @@ public: void create_command(String *cname, String *fname, Node *n, bool dispatch, String *modes = NULL) { // This is for the single main zend_function_entry record ParmList *l = Getattr(n, "parms"); - if (cname && Cmp(Getattr(n, "storage"), "friend") != 0) { + if (cname && !Equal(Getattr(n, "storage"), "friend")) { Printf(f_h, "static PHP_METHOD(%s%s,%s);\n", prefix, cname, fname); if (wrapperType != staticmemberfn && wrapperType != staticmembervar && @@ -891,7 +891,7 @@ public: String *arginfo_id = phptypes->get_arginfo_id(); String *s = cs_entry; if (!s) s = s_entry; - if (cname && Cmp(Getattr(n, "storage"), "friend") != 0) { + if (cname && !Equal(Getattr(n, "storage"), "friend")) { Printf(all_cs_entry, " PHP_ME(%s%s,%s,swig_arginfo_%s,%s)\n", prefix, cname, fname, arginfo_id, modes); } else { if (dispatch) { @@ -961,7 +961,7 @@ public: create_command(class_name, wname, n, true, modes); - if (class_name && Cmp(Getattr(n, "storage"), "friend") != 0) { + if (class_name && !Equal(Getattr(n, "storage"), "friend")) { Printv(f->def, "static PHP_METHOD(", prefix, class_name, ",", wname, ") {\n", NIL); } else { Printv(f->def, "static ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL); @@ -1251,7 +1251,7 @@ public: if (is_getter_method(n)) { // This is to overcome types that can't be set and hence no setter. - if (Cmp(Getattr(n, "feature:immutable"), "1") != 0) + if (!Equal(Getattr(n, "feature:immutable"), "1")) static_getter = true; } } else if (wrapperType == staticmemberfn) { @@ -1329,7 +1329,7 @@ public: if (!overloaded) { if (!static_getter) { - if (class_name && Cmp(Getattr(n, "storage"), "friend") != 0) { + if (class_name && !Equal(Getattr(n, "storage"), "friend")) { Printv(f->def, "static PHP_METHOD(", prefix, class_name, ",", wname, ") {\n", NIL); } else { if (wrap_nonclass_global) { From abc1c59c4e67f912c409a2bb6b8f70f0e2809c9e Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 21 Jul 2022 16:01:32 +1200 Subject: [PATCH 049/217] [php] Fix emitted PHP type declarations in corner cases See #2151 --- Source/Modules/php.cxx | 298 +++++++++++++++++++++++++++++------------ 1 file changed, 215 insertions(+), 83 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index d392e3a89..2f1c6c326 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -16,6 +16,7 @@ #include #include #include +#include static const char *usage = "\ PHP Options (available with -php7)\n\ @@ -218,6 +219,10 @@ static Hash *php_parent_class = NewHash(); // php_class + ":" + php_method -> boolean (using SetFlag()/GetFlag()). static Hash *has_directed_descendent = NewHash(); +// Track required return type for parent class methods. +// php_class + ":" + php_method -> List of php types. +static Hash *parent_class_method_return_type = NewHash(); + // Class encapsulating the machinery to add PHP type declarations. class PHPTypes { // List with an entry for each parameter and one for the return type. @@ -252,10 +257,21 @@ class PHPTypes { return std::max(Len(merged_types), Len(byref)); } - String *get_phptype(int key, String *classtypes) { + String *get_phptype(int key, String *classtypes, List *more_return_types = NULL) { Clear(classtypes); + // We want to minimise the list of class types by not redundantly listing + // a class for which a super-class is also listed. This canonicalisation + // allows for more sharing of arginfo (which reduces module size), makes + // for a cleaner list if it's shown to the user, and also will speed up + // module load a bit. + Hash *classes = NewHash(); DOH *types = Getitem(merged_types, key); String *result = NewStringEmpty(); + if (more_return_types) { + if (types != None) { + merge_type_lists(types, more_return_types); + } + } if (types != None) { SortList(types, NULL); String *prev = NULL; @@ -269,13 +285,36 @@ class PHPTypes { if (Len(result) > 0) Append(result, "|"); Append(result, c); } else { - if (Len(classtypes) > 0) Append(classtypes, "|"); - Append(classtypes, prefix); - Append(classtypes, i.item); + SetFlag(classes, i.item); } prev = i.item; } } + + // Remove entries for which a super-class is also listed. + Iterator i = First(classes); + while (i.key) { + String *this_class = i.key; + // We must advance the iterator early so we don't delete the element it + // points to. + i = Next(i); + String *parent = this_class; + while ((parent = Getattr(php_parent_class, parent)) != NULL) { + if (GetFlag(classes, parent)) { + Delattr(classes, this_class); + break; + } + } + } + + List *sorted_classes = SortedKeys(classes, Strcmp); + for (i = First(sorted_classes); i.item; i = Next(i)) { + if (Len(classtypes) > 0) Append(classtypes, "|"); + Append(classtypes, prefix); + Append(classtypes, i.item); + } + Delete(sorted_classes); + // Make the mask 0 if there are only class names specified. if (Len(result) == 0) { Append(result, "0"); @@ -283,7 +322,11 @@ class PHPTypes { return result; } - void init(Node *n) { +public: + PHPTypes(Node *n) + : merged_types(NewList()), + byref(NULL), + num_required(INT_MAX) { String *php_type_feature = Getattr(n, "feature:php:type"); php_type_flag = 0; if (php_type_feature != NULL) { @@ -297,21 +340,6 @@ class PHPTypes { has_director_node = (Getattr(n, "directorNode") != NULL); } -public: - PHPTypes(Node *n, int num_required_) - : merged_types(NewList()), - byref(NULL), - num_required(num_required_) { - init(n); - } - - PHPTypes(Node *n, const PHPTypes *o) - : merged_types(Copy(o->merged_types)), - byref(Copy(o->byref)), - num_required(o->num_required) { - init(n); - } - ~PHPTypes() { Delete(merged_types); Delete(byref); @@ -331,7 +359,15 @@ public: } // key is 0 for return type, or >= 1 for parameters numbered from 1 - void process_phptype(Node *n, int key, const String_or_char *attribute_name); + List *process_phptype(Node *n, int key, const String_or_char *attribute_name); + + // Merge entries from o_merge_list into merge_list, skipping any entries + // already present. + // + // Both merge_list and o_merge_list should be in sorted order. + static void merge_type_lists(List *merge_list, List *o_merge_list); + + void merge_from(const PHPTypes* o); void set_byref(int key) { if (!byref) { @@ -346,7 +382,34 @@ public: Setitem(byref, key, ""); // Just needs to be something != None. } - void emit_arginfo(String *key) { + void emit_arginfo(DOH *item, String *key) { + Setmark(item, 1); + char *colon_ptr = Strchr(key, ':'); + assert(colon_ptr); + int colon = colon_ptr - Char(key); + if (colon > 0 && Strcmp(colon_ptr + 1, "__construct") != 0) { + // See if there's a parent class which implements this method, and if so + // emit its arginfo and then merge its PHPTypes into ours as we need to + // be compatible with it (whether it is virtual or not). + String *this_class = NewStringWithSize(Char(key), colon); + String *parent = this_class; + while ((parent = Getattr(php_parent_class, parent)) != NULL) { + String *k = NewStringf("%s%s", parent, colon_ptr); + DOH *item = Getattr(all_phptypes, k); + if (item) { + PHPTypes *p = (PHPTypes*)Data(item); + if (!Getmark(item)) { + p->emit_arginfo(item, k); + } + merge_from(p); + Delete(k); + break; + } + Delete(k); + } + Delete(this_class); + } + // We want to only emit each different arginfo once, as that reduces the // size of both the generated source code and the compiled extension // module. The parameters at this level are just named arg1, arg2, etc @@ -359,27 +422,28 @@ public: // arginfo_used Hash to see if we've already generated it. String *out_phptype = NULL; String *out_phpclasses = NewStringEmpty(); - if (php_type_flag && - (php_type_flag > 0 || !has_director_node) && - !GetFlag(has_directed_descendent, key)) { - // We provide a simple way to generate PHP return type declarations - // except for directed methods. The point of directors is to allow - // subclassing in the target language, and if the wrapped method has - // a return type declaration then an overriding method in user code - // needs to have a compatible declaration. - // - // The upshot of this is that enabling return type declarations for - // existing bindings would break compatibility with user code written - // for an older version. For parameters however the situation is - // different because if the parent class declares types for parameters - // a subclass overriding the function will be compatible whether it - // declares them or not. - // - // directorNode being present seems to indicate if this method or one - // it inherits from is directed, which is what we care about here. - // Using (!is_member_director(n)) would get it wrong for testcase - // director_frob. - out_phptype = get_phptype(0, out_phpclasses); + + // We provide a simple way to generate PHP return type declarations + // except for directed methods. The point of directors is to allow + // subclassing in the target language, and if the wrapped method has + // a return type declaration then an overriding method in user code + // needs to have a compatible declaration. + // + // The upshot of this is that enabling return type declarations for + // existing bindings would break compatibility with user code written + // for an older version. For parameters however the situation is + // different because if the parent class declares types for parameters + // a subclass overriding the function will be compatible whether it + // declares them or not. + // + // directorNode being present seems to indicate if this method or one + // it inherits from is directed, which is what we care about here. + // Using (!is_member_director(n)) would get it wrong for testcase + // director_frob. + if (php_type_flag && (php_type_flag > 0 || !has_director_node)) { + if (!GetFlag(has_directed_descendent, key)) { + out_phptype = get_phptype(0, out_phpclasses, Getattr(parent_class_method_return_type, key)); + } } // ### in arginfo_code will be replaced with the id once that is known. @@ -660,10 +724,19 @@ public: /* Emit all of the code */ Language::top(n); - /* Emit all the arginfo */ - for (Iterator ki = First(all_phptypes); ki.key; ki = Next(ki)) { - PHPTypes *p = (PHPTypes*)Data(ki.item); - p->emit_arginfo(ki.key); + /* Emit all the arginfo. We sort the keys so the output order doesn't depend on + * hashkey order. + */ + { + List *sorted_keys = SortedKeys(all_phptypes, Strcmp); + for (Iterator k = First(sorted_keys); k.item; k = Next(k)) { + DOH *val = Getattr(all_phptypes, k.item); + if (!Getmark(val)) { + PHPTypes *p = (PHPTypes*)Data(val); + p->emit_arginfo(val, k.item); + } + } + Delete(sorted_keys); } SwigPHP_emit_pointer_type_registrations(); @@ -1277,9 +1350,8 @@ public: return SWIG_OK; } - if (!Getattr(n, "sym:previousSibling") && !static_getter) { - // First function of an overloaded group or a function which isn't part - // of a group so reset the phptype information. + if (!static_getter) { + // Create or find existing PHPTypes. phptypes = NULL; String *key; @@ -1291,29 +1363,11 @@ public: PHPTypes *p = (PHPTypes*)GetVoid(all_phptypes, key); if (p) { - // We already have an entry - this happens when overloads are created - // by %extend, for instance. + // We already have an entry so use it. phptypes = p; Delete(key); } else { - if (class_name) { - // See if there's a parent class which implements this method, and if - // so copy the PHPTypes of that method as a starting point as we need - // to be compatible with it (whether it is virtual or not). - String *parent = class_name; - while ((parent = Getattr(php_parent_class, parent)) != NULL) { - String *k = NewStringf("%s:%s", parent, wname); - PHPTypes *p = (PHPTypes*)GetVoid(all_phptypes, k); - Delete(key); - if (p) { - phptypes = new PHPTypes(n, p); - break; - } - } - } - if (!phptypes) { - phptypes = new PHPTypes(n, emit_num_required(l)); - } + phptypes = new PHPTypes(n); SetVoid(all_phptypes, key, phptypes); } } @@ -1462,15 +1516,6 @@ public: Append(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n"); Wrapper_add_local(f, "upcall", "bool upcall = false"); Printf(f->code, "upcall = (director && (director->swig_get_self()==Z_OBJ_P(ZEND_THIS)));\n"); - - if (class_name && !Equal(Getattr(n, "storage"), "friend")) { - String *parent = class_name; - while ((parent = Getattr(php_parent_class, parent)) != NULL) { - // Mark this method name as having a directed descendent for all - // classes we're derived from. - SetFlag(has_directed_descendent, NewStringf("%s:%s", parent, wname)); - } - } } Swig_director_emit_dynamic_cast(n, f); @@ -1530,7 +1575,33 @@ public: } emit_return_variable(n, d, f); - phptypes->process_phptype(n, 0, "tmap:out:phptype"); + List *return_types = phptypes->process_phptype(n, 0, "tmap:out:phptype"); + + if (class_name && !Equal(Getattr(n, "storage"), "friend")) { + if (is_member_director(n)) { + String *parent = class_name; + while ((parent = Getattr(php_parent_class, parent)) != NULL) { + // Mark this method name as having no return type declaration for all + // classes we're derived from. + SetFlag(has_directed_descendent, NewStringf("%s:%s", parent, wname)); + } + } else if (return_types) { + String *parent = class_name; + while ((parent = Getattr(php_parent_class, parent)) != NULL) { + String *key = NewStringf("%s:%s", parent, wname); + // The parent class method needs to have a superset of the possible + // return types of methods with the same name in subclasses. + List *v = Getattr(parent_class_method_return_type, key); + if (!v) { + // New entry. + Setattr(parent_class_method_return_type, key, Copy(return_types)); + } else { + // Update existing entry. + PHPTypes::merge_type_lists(v, return_types); + } + } + } + } if (outarg) { Printv(f->code, outarg, NIL); @@ -2451,7 +2522,7 @@ public: static PHP *maininstance = 0; -void PHPTypes::process_phptype(Node *n, int key, const String_or_char *attribute_name) { +List *PHPTypes::process_phptype(Node *n, int key, const String_or_char *attribute_name) { while (Len(merged_types) <= key) { Append(merged_types, NewList()); @@ -2465,11 +2536,11 @@ void PHPTypes::process_phptype(Node *n, int key, const String_or_char *attribute // declaration for this parameter/return value (you can't store NULL as a // value in a DOH List). Setitem(merged_types, key, None); - return; + return NULL; } DOH *merge_list = Getitem(merged_types, key); - if (merge_list == None) return; + if (merge_list == None) return NULL; List *types = Split(phptype, '|', -1); String *first_type = Getitem(types, 0); @@ -2525,6 +2596,67 @@ void PHPTypes::process_phptype(Node *n, int key, const String_or_char *attribute } prev = i.item; } + SortList(merge_list, NULL); + return merge_list; +} + +void PHPTypes::merge_type_lists(List *merge_list, List *o_merge_list) { + int i = 0, j = 0; + while (j < Len(o_merge_list)) { + String *candidate = Getitem(o_merge_list, j); + while (i < Len(merge_list)) { + int cmp = Cmp(Getitem(merge_list, i), candidate); + if (cmp == 0) + goto handled; + if (cmp > 0) + break; + ++i; + } + Insert(merge_list, i, candidate); + ++i; +handled: + ++j; + } +} + +void PHPTypes::merge_from(const PHPTypes* o) { + num_required = std::min(num_required, o->num_required); + + if (o->byref) { + if (byref == NULL) { + byref = Copy(o->byref); + } else { + int len = std::min(Len(byref), Len(o->byref)); + // Start at 1 because we only want to merge parameter types, and key 0 is + // the return type. + for (int key = 1; key < len; ++key) { + if (Getitem(byref, key) == None && + Getitem(o->byref, key) != None) { + Setitem(byref, key, ""); + } + } + for (int key = len; key < Len(o->byref); ++key) { + Append(byref, Getitem(o->byref, key)); + } + } + } + + int len = std::min(Len(merged_types), Len(o->merged_types)); + for (int key = 0; key < len; ++key) { + DOH *merge_list = Getitem(merged_types, key); + // None trumps anything else in the merge. + if (merge_list == None) continue; + DOH *o_merge_list = Getitem(o->merged_types, key); + if (o_merge_list == None) { + Setitem(merged_types, key, None); + continue; + } + merge_type_lists(merge_list, o_merge_list); + } + // Copy over any additional entries. + for (int key = len; key < Len(o->merged_types); ++key) { + Append(merged_types, Copy(Getitem(o->merged_types, key))); + } } // Collect non-class pointer types from the type table so we can set up PHP From 4ac3c87a299368e22151bac3cae11e62cf23c730 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 20 Jul 2022 15:05:21 +1200 Subject: [PATCH 050/217] Sort out predefined SWIG-specific macros Ensure that SWIG_VERSION is defined both at SWIG-time and in the generated C/C++ wrapper code (it was only defined in the wrapper for some target languages previously). SWIGGO and SWIGJAVASCRIPT are now defined in the generated wrappers to match behaviour for all other target languages. Stop defining SWIGVERSION in the wrapper. This only happened as a side-effect of how SWIG_VERSION was defined but was never documented and is redundant. The new testcase also checks that SWIG is defined at SWIG-time but not in the generated wrapper, and that exactly one of a list of target-language specific macros is defined. Fixes #1050 --- CHANGES.current | 11 +++++++ Doc/Manual/Preprocessor.html | 8 +++++ Examples/test-suite/common.mk | 1 + Examples/test-suite/preproc_predefined.h | 27 ++++++++++++++++ Examples/test-suite/preproc_predefined.i | 40 ++++++++++++++++++++++++ Lib/csharp/csharp.swg | 2 ++ Lib/go/go.swg | 2 ++ Lib/guile/guile.i | 2 ++ Lib/java/java.swg | 2 ++ Lib/lua/lua.swg | 2 ++ Lib/mzscheme/mzscheme.swg | 2 ++ Lib/ocaml/ocaml.i | 2 ++ Lib/php/php.swg | 2 ++ Lib/typemaps/README | 1 + Lib/typemaps/swigmacros.swg | 10 +----- Lib/typemaps/swigversion.swg | 17 ++++++++++ Source/Modules/go.cxx | 2 ++ Source/Modules/javascript.cxx | 4 +++ 18 files changed, 128 insertions(+), 9 deletions(-) create mode 100644 Examples/test-suite/preproc_predefined.h create mode 100644 Examples/test-suite/preproc_predefined.i create mode 100644 Lib/typemaps/swigversion.swg diff --git a/CHANGES.current b/CHANGES.current index bfe3f8b0a..921441645 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,17 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-04: olly + #1050 Consistently define SWIG_VERSION both at SWIG-time and in + the generated wrapper. Best practice remains to check at SWIG-time + where possible because that results in smaller generated wrapper + sources. + + SWIGGO and SWIGJAVASCRIPT are now defined in the generated wrappers + to match behaviour for all other target languages. + + The undocumented SWIGVERSION macro is no longer defined. + 2022-09-29: olly #2303 SWIG's internal hash tables now use a better hash function. diff --git a/Doc/Manual/Preprocessor.html b/Doc/Manual/Preprocessor.html index 0d5cc6300..c612c56ce 100644 --- a/Doc/Manual/Preprocessor.html +++ b/Doc/Manual/Preprocessor.html @@ -147,6 +147,14 @@ SWIGTCL Defined when using Tcl SWIGXML Defined when using XML +

    +SWIG also defines SWIG_VERSION and a target language macro in +the generated wrapper file (since SWIG 4.2.0 - in older versions these +were defined for some target languages but this wasn't consistent). Best +practice is to use SWIG-time conditional checks because that results in smaller +generated wrapper sources. +

    +

    In addition, SWIG defines the following set of standard C/C++ macros:

    diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index da90dd9fd..a308d53c2 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -788,6 +788,7 @@ C_TEST_CASES += \ preproc_gcc_output \ preproc_include \ preproc_line_file \ + preproc_predefined \ register_par \ ret_by_value \ simple_array \ diff --git a/Examples/test-suite/preproc_predefined.h b/Examples/test-suite/preproc_predefined.h new file mode 100644 index 000000000..8d6b6ee28 --- /dev/null +++ b/Examples/test-suite/preproc_predefined.h @@ -0,0 +1,27 @@ +/* This list will need updating when new target languages are added. */ +#if (0\ + +defined(SWIGCSHARP)\ + +defined(SWIGD)\ + +defined(SWIGGO)\ + +defined(SWIGGUILE)\ + +defined(SWIGJAVA)\ + +defined(SWIGJAVASCRIPT)\ + +defined(SWIGLUA)\ + +defined(SWIGMZSCHEME)\ + +defined(SWIGOCAML)\ + +defined(SWIGOCTAVE)\ + +defined(SWIGPERL)\ + +defined(SWIGPHP)\ + +defined(SWIGPYTHON)\ + +defined(SWIGR)\ + +defined(SWIGRUBY)\ + +defined(SWIGSCILAB)\ + +defined(SWIGTCL)\ + +defined(SWIGXML)\ + ) != 1 +# ifdef SWIG +# error Did not detect exactly one target-language-specific macro defined at SWIG time. +# else +# error Did not detect exactly one target-language-specific macro defined in the generated wrapper. +# endif +#endif diff --git a/Examples/test-suite/preproc_predefined.i b/Examples/test-suite/preproc_predefined.i new file mode 100644 index 000000000..7db5352f5 --- /dev/null +++ b/Examples/test-suite/preproc_predefined.i @@ -0,0 +1,40 @@ +%module preproc_predefined + +/* Test that SWIG_VERSION is defined at SWIG-time and in the wrapper. */ +#ifndef SWIG_VERSION +# error SWIG_VERSION not defined at SWIG-time +#endif +%{ +#ifndef SWIG_VERSION +# error SWIG_VERSION not defined in the generated wrapper +#endif +%} + +/* Test that SWIGVERSION is NOT defined at SWIG-time or in the wrapper. + * It used to be defined in the wrapper as a side-effect of how SWIG_VERSION + * was defined in the wrapper but was never documented and is redundant. + */ +#ifdef SWIGVERSION +# error SWIGVERSION should not be defined at SWIG-time +#endif +%{ +#ifdef SWIGVERSION +# error SWIGVERSION should not be defined in the generated wrapper +#endif +%} + +/* Test that SWIG is defined at SWIG-time but not in the wrapper. */ +#ifndef SWIG +# error SWIG not defined at SWIG-time +#endif +%{ +#ifdef SWIG +# error SWIG should not be defined in the generated wrapper +#endif +%} + +/* Test that SWIGxxx is defined at SWIG-time and in the wrapper. */ +%include "preproc_predefined.h" +%{ +#include "preproc_predefined.h" +%} diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg index 1f80d12a1..8514a7705 100644 --- a/Lib/csharp/csharp.swg +++ b/Lib/csharp/csharp.swg @@ -4,6 +4,8 @@ * C# typemaps * ----------------------------------------------------------------------------- */ +%include + %include /* The ctype, imtype and cstype typemaps work together and so there should be one of each. diff --git a/Lib/go/go.swg b/Lib/go/go.swg index 348ae5f0d..47486ab75 100644 --- a/Lib/go/go.swg +++ b/Lib/go/go.swg @@ -4,6 +4,8 @@ * Go configuration module. * ------------------------------------------------------------ */ +%include + %include /* Code insertion directives */ diff --git a/Lib/guile/guile.i b/Lib/guile/guile.i index ef270d74b..10438f483 100644 --- a/Lib/guile/guile.i +++ b/Lib/guile/guile.i @@ -4,6 +4,8 @@ * SWIG Configuration File for Guile. * ----------------------------------------------------------------------------- */ +%include + /* Macro for inserting Scheme code into the stub */ #define %scheme %insert("scheme") #define %goops %insert("goops") diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 8719818bb..28eb8fd0d 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -4,6 +4,8 @@ * Java typemaps * ----------------------------------------------------------------------------- */ +%include + %include /* The jni, jtype and jstype typemaps work together and so there should be one of each. diff --git a/Lib/lua/lua.swg b/Lib/lua/lua.swg index 12c635d77..263c3966f 100644 --- a/Lib/lua/lua.swg +++ b/Lib/lua/lua.swg @@ -5,6 +5,8 @@ * This file is parsed by SWIG before reading any other interface file. * ----------------------------------------------------------------------------- */ +%include + /* ----------------------------------------------------------------------------- * includes * ----------------------------------------------------------------------------- */ diff --git a/Lib/mzscheme/mzscheme.swg b/Lib/mzscheme/mzscheme.swg index f45c87250..8ded91f3e 100644 --- a/Lib/mzscheme/mzscheme.swg +++ b/Lib/mzscheme/mzscheme.swg @@ -5,6 +5,8 @@ * This file is parsed by SWIG before reading any other interface file. * ----------------------------------------------------------------------------- */ +%include + /* Include headers */ %runtime "swigrun.swg" // Common C API type-checking code %runtime "swigerrors.swg" // SWIG errors diff --git a/Lib/ocaml/ocaml.i b/Lib/ocaml/ocaml.i index cc26d1859..117d0a9b5 100644 --- a/Lib/ocaml/ocaml.i +++ b/Lib/ocaml/ocaml.i @@ -4,6 +4,8 @@ * SWIG Configuration File for Ocaml * ----------------------------------------------------------------------------- */ +%include + /* Insert common stuff */ %insert(runtime) "swigrun.swg" diff --git a/Lib/php/php.swg b/Lib/php/php.swg index 04b7075b7..b22166593 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -4,6 +4,8 @@ * PHP configuration file * ----------------------------------------------------------------------------- */ +%include + // Default to generating PHP type declarations (for PHP >= 8) except for // cases which are liable to cause compatibility issues with existing // bindings. diff --git a/Lib/typemaps/README b/Lib/typemaps/README index 65134578d..22a0fc0bb 100644 --- a/Lib/typemaps/README +++ b/Lib/typemaps/README @@ -48,6 +48,7 @@ std_strings.swg Common macros to implemented the std::string/std::wstring typem strings.swg Common macros and typemaps for string and wstring (char *, wchar_t *) swigmacros.swg Basic macros +swigversion.swg Define SWIG_VERSION fragments.swg Macros for fragment manipulations diff --git a/Lib/typemaps/swigmacros.swg b/Lib/typemaps/swigmacros.swg index 687b0680e..7db6871d4 100644 --- a/Lib/typemaps/swigmacros.swg +++ b/Lib/typemaps/swigmacros.swg @@ -109,15 +109,7 @@ nocppval #endif %enddef -/* insert the SWIGVERSION in the interface and the wrapper code */ -#if SWIG_VERSION -%insert("header") { -%define_as(SWIGVERSION, SWIG_VERSION) -%#define SWIG_VERSION SWIGVERSION -} -#endif - - +%include /* ----------------------------------------------------------------------------- * Casting operators diff --git a/Lib/typemaps/swigversion.swg b/Lib/typemaps/swigversion.swg new file mode 100644 index 000000000..18f897cad --- /dev/null +++ b/Lib/typemaps/swigversion.swg @@ -0,0 +1,17 @@ +/* ----------------------------------------------------------------------------- + * Define SWIG_VERSION + * ----------------------------------------------------------------------------- */ + +/* Define SWIG_VERSION in the interface and the wrapper code. + * + * Best practice is to use SWIG-time checks for SWIG_VERSION, but SWIG_VERSION + * was unintentionally defined like this for many years, and while it was never + * documented there are likely user interface files which rely on it. + */ +%define %define_swig_version_()%#define SWIG_VERSION_ SWIG_VERSION %enddef +%insert("header") { +%define_swig_version_() +%#define SWIG_VERSION SWIG_VERSION_ +%#undef SWIG_VERSION_ +} +#undef %define_swig_version_ diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index 1692e905a..7f0ccbe8b 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -515,6 +515,8 @@ private: } Printf(f_c_runtime, "#define SWIGMODULE %s\n", module); + Printf(f_c_runtime, "#ifndef SWIGGO\n#define SWIGGO\n#endif\n\n"); + if (gccgo_flag) { Printf(f_c_runtime, "#define SWIGGO_PREFIX %s\n", go_prefix); } diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx index b17c5e503..e6e47e3f3 100644 --- a/Source/Modules/javascript.cxx +++ b/Source/Modules/javascript.cxx @@ -1615,6 +1615,8 @@ int JSCEmitter::initialize(Node *n) { Swig_banner(f_wrap_cpp); + Printf(f_runtime, "#ifndef SWIGJAVASCRIPT\n#define SWIGJAVASCRIPT\n#endif\n\n"); + return SWIG_OK; } @@ -1945,6 +1947,8 @@ int V8Emitter::initialize(Node *n) { Swig_banner(f_wrap_cpp); + Printf(f_runtime, "#ifndef SWIGJAVASCRIPT\n#define SWIGJAVASCRIPT\n#endif\n\n"); + return SWIG_OK; } From 3096e8aa00db7ac9ab7c63ce8c8d23b65800f4c9 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 5 Oct 2022 12:41:34 +1300 Subject: [PATCH 051/217] Fix doc typo --- Doc/Manual/Warnings.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index bb20db38b..6140dd21a 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -211,7 +211,7 @@ You can of course also enable all warnings and suppress a select few, for exampl

    -The warnings on the right take precedence over the warnings on the left, so in the above example -Wextra adds numerous warnings including 452, but then -w309,452 overrides this and so 452 is suppressesed. +The warnings on the right take precedence over the warnings on the left, so in the above example -Wextra adds numerous warnings including 452, but then -w309,452 overrides this and so 452 is suppressed.

    From befcd1bf586dfd2bb2d54ddb177f1e30a78e4e11 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 5 Oct 2022 13:48:21 +1300 Subject: [PATCH 052/217] Fix SWIG version reference in recent doc change The upcoming release is 4.1.0 not 4.2.0. --- Doc/Manual/Preprocessor.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/Manual/Preprocessor.html b/Doc/Manual/Preprocessor.html index c612c56ce..659cb6fa2 100644 --- a/Doc/Manual/Preprocessor.html +++ b/Doc/Manual/Preprocessor.html @@ -149,7 +149,7 @@ SWIGXML Defined when using XML

    SWIG also defines SWIG_VERSION and a target language macro in -the generated wrapper file (since SWIG 4.2.0 - in older versions these +the generated wrapper file (since SWIG 4.1.0 - in older versions these were defined for some target languages but this wasn't consistent). Best practice is to use SWIG-time conditional checks because that results in smaller generated wrapper sources. From 06296a71281f049cfc438b4a7fb05127a0474144 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 5 Oct 2022 13:23:49 +1300 Subject: [PATCH 053/217] Report errors in preprocessor expressions by default Until now SWIG quietly ignored such errors unless -Wextra (or -Wall which implies -Wextra) was passed, but this is unhelpful as it hides problems. To illustrate this point, enabling this warning by default revealled a typo in the preproc_defined.i testcase in SWIG's own testsuite. If you really don't want to see this warning, you can suppress it with command line option -w202 or by using this in your interface file: %warnfilter(SWIGWARN_PP_EVALUATION); Both will work with older versions of SWIG too. Fixes #1465 Fixes #2389 --- CHANGES.current | 17 +++++++++++++++++ Doc/Manual/SWIG.html | 2 +- Doc/Manual/Warnings.html | 9 +++++++++ .../test-suite/errors/cpp_pp_expressions_bad.i | 2 +- Examples/test-suite/errors/pp_expressions_bad.i | 2 +- Examples/test-suite/preproc_defined.i | 2 +- Source/Modules/main.cxx | 7 ++++--- 7 files changed, 34 insertions(+), 7 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 921441645..5d79c9084 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,23 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-05: olly + #1465 Report errors in preprocessor expressions by default + + Until now SWIG quietly ignored such errors unless -Wextra (or -Wall + which implies -Wextra) was passed, but this is unhelpful as it tends + to hide genuine problems. To illustrate this point, enabling this + warning by default revealed a typo in the preproc_defined.i + testcase in SWIG's own testsuite. + + If you really don't want to see this warning, you can suppress it + with command line option -w202 or by using this in your interface + file: + + %warnfilter(SWIGWARN_PP_EVALUATION); + + Both will work with older versions of SWIG too. + 2022-10-04: olly #1050 Consistently define SWIG_VERSION both at SWIG-time and in the generated wrapper. Best practice remains to check at SWIG-time diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index b7021c468..e3e11841d 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -219,7 +219,7 @@ General Options -Wall - Remove all warning suppression, also implies -Wextra -Wallkw - Enable keyword warnings for all the supported languages -Werror - Treat warnings as errors - -Wextra - Adds the following additional warnings: 202,309,403,405,512,321,322 + -Wextra - Adds the following additional warnings: 309,403,405,512,321,322 -w<list> - Suppress/add warning messages, eg -w401,+321 - see Warnings.html -xmlout <file> - Write XML version of the parse tree to <file> after normal processing diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index 6140dd21a..b20b69cef 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -164,6 +164,15 @@ to provide additional diagnostics. These warnings can be turned on using the +

    +Preprocessor warning 202 ("Could not evaluate expression expr.") was +formally off by default and enabled by -Wextra, but since SWIG 4.1.0 +this warning is on by default because suppressing it tends to hide genuine +problems. If you really don't want to see it, you can suppress it with +-w202 or using %warnfilter as described below. Both will work +with older versions of SWIG too. +

    +

    To selectively turn on extra warning messages, you can use the directives and options in the previous section--simply add a "+" to all warning numbers. For example: diff --git a/Examples/test-suite/errors/cpp_pp_expressions_bad.i b/Examples/test-suite/errors/cpp_pp_expressions_bad.i index c95b9bfc4..2f71232fe 100644 --- a/Examples/test-suite/errors/cpp_pp_expressions_bad.i +++ b/Examples/test-suite/errors/cpp_pp_expressions_bad.i @@ -1,5 +1,5 @@ %module xxx -/* Note: needs -Wextra to see these warnings */ + /* Spaceship operator doesn't seem to be allowed in preprocessor expressions. */ #if (4 <=> 2) < 0 diff --git a/Examples/test-suite/errors/pp_expressions_bad.i b/Examples/test-suite/errors/pp_expressions_bad.i index 0e67c78f8..eea178388 100644 --- a/Examples/test-suite/errors/pp_expressions_bad.i +++ b/Examples/test-suite/errors/pp_expressions_bad.i @@ -1,5 +1,5 @@ %module xxx -/* Note: needs -Wextra to see these warnings */ + /* Divide by zero */ #define ZERO 0 diff --git a/Examples/test-suite/preproc_defined.i b/Examples/test-suite/preproc_defined.i index e1958515d..5ebf0a099 100644 --- a/Examples/test-suite/preproc_defined.i +++ b/Examples/test-suite/preproc_defined.i @@ -86,7 +86,7 @@ struct Defined { void defined_not(TYPE); #endif -#if !( defined(AAA) \ +#if !( defined(AAA) &&\ defined(BBB) \\ && defined(CCC) ) void bumpf_not(TYPE); diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 44d30e893..8a3259db8 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -41,8 +41,9 @@ extern "C" { int UseWrapperSuffix = 0; // If 1, append suffix to non-overloaded functions too. } -/* Suppress warning messages for private inheritance, preprocessor evaluation etc... - WARN_PP_EVALUATION 202 +/* Suppress warning messages for private inheritance, etc by default. + These are enabled by command line option -Wextra. + WARN_PARSE_PRIVATE_INHERIT 309 WARN_PARSE_BUILTIN_NAME 321 WARN_PARSE_REDUNDANT 322 @@ -50,7 +51,7 @@ extern "C" { WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405 WARN_LANG_OVERLOAD_CONST 512 */ -#define EXTRA_WARNINGS "202,309,403,405,512,321,322" +#define EXTRA_WARNINGS "309,403,405,512,321,322" extern "C" { extern String *ModuleName; From 6f1532e35a605bc52c85892d3094be552ca6483a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 5 Oct 2022 20:15:21 +0100 Subject: [PATCH 054/217] Warning fix for OCaml test --- Examples/test-suite/cpp11_move_only.i | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Examples/test-suite/cpp11_move_only.i b/Examples/test-suite/cpp11_move_only.i index 28aaf05e5..b7db92b3b 100644 --- a/Examples/test-suite/cpp11_move_only.i +++ b/Examples/test-suite/cpp11_move_only.i @@ -2,6 +2,10 @@ %include "cpp11_move_only_helper.i" +#if defined(SWIGOCAML) +%rename(valu) val; +#endif + %ignore MoveOnly::operator=; //%valuewrapper MoveOnly; // SWIG sets %valuewrapper by default for move-only types From 76f5670fa47d85ddc1a4a87cf94b2c8b568d3f11 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 5 Oct 2022 21:33:06 +0100 Subject: [PATCH 055/217] Fix OCaml %rename for enum items --- CHANGES.current | 3 +++ Examples/test-suite/ocaml/enum_rename_runme.ml | 10 ++++++++++ Source/Modules/ocaml.cxx | 9 +++++---- 3 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 Examples/test-suite/ocaml/enum_rename_runme.ml diff --git a/CHANGES.current b/CHANGES.current index 5d79c9084..8a0f628b4 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-05: wsfulton + [OCaml] Fix %rename for enum items. Previously the rename had no effect. + 2022-10-05: olly #1465 Report errors in preprocessor expressions by default diff --git a/Examples/test-suite/ocaml/enum_rename_runme.ml b/Examples/test-suite/ocaml/enum_rename_runme.ml new file mode 100644 index 000000000..4aef31bac --- /dev/null +++ b/Examples/test-suite/ocaml/enum_rename_runme.ml @@ -0,0 +1,10 @@ +open Swig +open Enum_rename + +let mydec = C_enum `M_Dec +let _ = assert (((enum_to_int `Month mydec)) = C_int 2) +let _ = assert (((int_to_enum `Month 2)) = C_enum `M_Dec) + +let mymay = C_enum `May +let _ = assert (((enum_to_int `Month mymay)) = C_int 1) +let _ = assert (((int_to_enum `Month 1)) = C_enum `May) diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx index 84f16aa99..6955cdced 100644 --- a/Source/Modules/ocaml.cxx +++ b/Source/Modules/ocaml.cxx @@ -1238,6 +1238,7 @@ public: int enumvalueDeclaration(Node *n) { String *name = Getattr(n, "name"); + String *symname = Getattr(n, "sym:name"); SwigType *qtype = 0; if (name_qualifier_type) { @@ -1245,8 +1246,8 @@ public: Printv(qtype, name, NIL); } - if (const_enum && qtype && name && !Getattr(seen_enumvalues, name)) { - Setattr(seen_enumvalues, name, "true"); + if (const_enum && qtype && symname && !Getattr(seen_enumvalues, symname)) { + Setattr(seen_enumvalues, symname, "true"); SetFlag(n, "feature:immutable"); Setattr(n, "feature:enumvalue", "1"); // this does not appear to be used @@ -1255,10 +1256,10 @@ public: String *evname = SwigType_manglestr(qtype); Insert(evname, 0, "SWIG_ENUM_"); - Setattr(n, "feature:enumvname", name); + Setattr(n, "feature:enumvname", symname); Setattr(n, "feature:symname", evname); Delete(evname); - Printf(f_enumtypes_value, "| `%s\n", name); + Printf(f_enumtypes_value, "| `%s\n", symname); return Language::enumvalueDeclaration(n); } else From ba279ae9392b36e2de857a08a4f5266c27b5c930 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 2 Oct 2022 13:47:15 +0100 Subject: [PATCH 056/217] Add support for parsing C++11 final classes Such as: class X final {}; This no longer gives a syntax error. This change has introduced one more shift-reduce conflict in the parser. with a conflict with a C style variable declaration with name final: class X final; resulting in a syntax error (for C++ not C). This is an an unusual style for C++ code and more typical declarations do work: X final; Closes #672 --- CHANGES.current | 7 + Doc/Manual/CPlusPlus11.html | 13 ++ Examples/test-suite/common.mk | 2 + Examples/test-suite/cpp11_final_class.i | 129 ++++++++++++++++++ Examples/test-suite/cpp11_final_override.i | 2 +- Examples/test-suite/final_c.i | 11 ++ .../python/cpp11_final_class_runme.py | 62 +++++++++ Examples/test-suite/python/final_c_runme.py | 6 + Source/CParse/parser.y | 59 ++++---- 9 files changed, 267 insertions(+), 24 deletions(-) create mode 100644 Examples/test-suite/cpp11_final_class.i create mode 100644 Examples/test-suite/final_c.i create mode 100644 Examples/test-suite/python/cpp11_final_class_runme.py create mode 100644 Examples/test-suite/python/final_c_runme.py diff --git a/CHANGES.current b/CHANGES.current index 8a0f628b4..ef6fe9fde 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,13 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-05: olly, wsfulton + #672 Add support for parsing C++11 final classes such as: + + class X final {}; + + This no longer gives a syntax error. + 2022-10-05: wsfulton [OCaml] Fix %rename for enum items. Previously the rename had no effect. diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index 861b80048..a84ca5f51 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -891,6 +891,19 @@ struct DerivedStruct : BaseStruct { }; +

    +Classes can also be marked as final, such as +

    + +
    +struct FinalDerivedStruct final : BaseStruct {
    +  virtual void ab() const override;
    +};
    +
    + +

    +Compatibility note: Final methods were supported much earlier than final classes. SWIG-4.1.0 was the first version to support classes marked as final. +

    7.2.12 Null pointer constant

    diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index a308d53c2..091293016 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -592,6 +592,7 @@ CPP11_TEST_CASES += \ cpp11_director_enums \ cpp11_directors \ cpp11_explicit_conversion_operators \ + cpp11_final_class \ cpp11_final_directors \ cpp11_final_override \ cpp11_function_objects \ @@ -755,6 +756,7 @@ C_TEST_CASES += \ enum_macro \ enum_missing \ extern_declaration \ + final_c \ funcptr \ function_typedef \ global_functions \ diff --git a/Examples/test-suite/cpp11_final_class.i b/Examples/test-suite/cpp11_final_class.i new file mode 100644 index 000000000..e6a29e988 --- /dev/null +++ b/Examples/test-suite/cpp11_final_class.i @@ -0,0 +1,129 @@ +%module cpp11_final_class + +%warnfilter(SWIGWARN_PARSE_KEYWORD) final; // 'final' is a java keyword, renaming to '_final' +%warnfilter(SWIGWARN_PARSE_KEYWORD) override; // 'override' is a C# keyword, renaming to '_override' + +%ignore Space1::final::operator=; +#if defined(SWIGPHP) +%rename(Space1_final) Space1::final::final; +#endif +#if defined(SWIGOCAML) +%rename(finale) Space2::FinalEnum1::final; +#endif + +%inline %{ +struct FinalBase { + virtual ~FinalBase() {} +}; + +struct FinalClass1 final : FinalBase { + void method1() {} +}; + +class FinalClass2 final : public FinalBase { +public: + void method2() {} +}; + +struct FinalClass3 final { + void method3() {} +}; + +struct FinalClass4 { + void method4() {} +} final; + +struct override final { + void omethod() {} +}; +%} + +%rename(Space1_final) Space1::final; + +%inline %{ +namespace Space1 { +struct final final { + void finalmethod() {} + final() {} + final(const final &other) = default; + final& operator=(const final &other) = default; +}; +struct FinalClass5 final { + void method5() {} + final final_member_var; + final get_final_member() { return final_member_var; } + Space1::final get_final_member2() { return final_member_var; } +}; +struct FinalClass6 { + void method6() {} + virtual void final() final {} + virtual ~FinalClass6() = default; +}; +typedef final Space1_final_typedef1; +typedef struct final Space1_final_typedef2; +} +typedef Space1::final Space1_final_typedef3; +typedef struct Space1::final Space1_final_typedef4; +%} + +%inline %{ +namespace Space2 { +class Y { +public: + Y(int i=0) {} +}; + +struct FinalVar1 { + class Y notfinal; +// class Y final; // SWIG (C++ only) fails to parse (same for struct and union) +}; +struct FinalVar2 { + class Y notfinal = {}; +// class Y final = {}; // SWIG (C++ only) fails to parse (same for struct and union) +}; +struct FinalVar3 { + class Y notfinal = Y(); +// class Y final = Y(); // SWIG (C++ only) fails to parse (same for struct and union) +}; +struct FinalVar4 { + class Y* final; + FinalVar4() : final() {} +}; +struct FinalVar5 { + Y final; +}; +struct FinalVar6 { + Y final = {}; +}; +struct FinalVar7 { + Y final = Y(); +}; +struct FinalVar8 { + Y final{}; +}; +struct FinalVar9 { + Y final{9}; +}; +struct FinalVar10 { + void a10(class Y final) {} + void b10(Y final) {} +}; +struct FinalEnum1 { + enum Enum1 { one, two, final }; + void enum_in(Enum1 e) {} +}; +struct FinalEnum2 { + enum Enum2 { one, two, three, four }; + enum Enum2 final; +}; +} +%} + +%rename(Space3_final) Space3::final; +%inline %{ +namespace Space3 { + typedef struct final { + void fmethod() {} + } final; +} +%} diff --git a/Examples/test-suite/cpp11_final_override.i b/Examples/test-suite/cpp11_final_override.i index 849655b16..ac14326e5 100644 --- a/Examples/test-suite/cpp11_final_override.i +++ b/Examples/test-suite/cpp11_final_override.i @@ -27,7 +27,7 @@ struct Base { virtual ~Base() {} }; -struct Derived /*final*/ : Base { +struct Derived final : Base { virtual void stuff() const noexcept override final {} virtual void override1() const noexcept override; virtual void override2() const noexcept override; diff --git a/Examples/test-suite/final_c.i b/Examples/test-suite/final_c.i new file mode 100644 index 000000000..448d08d1e --- /dev/null +++ b/Examples/test-suite/final_c.i @@ -0,0 +1,11 @@ +%module final_c + +%inline %{ +struct Y { + int yval; +}; +struct Y final; +void init() { + final.yval = 123; +} +%} diff --git a/Examples/test-suite/python/cpp11_final_class_runme.py b/Examples/test-suite/python/cpp11_final_class_runme.py new file mode 100644 index 000000000..568a1ca1a --- /dev/null +++ b/Examples/test-suite/python/cpp11_final_class_runme.py @@ -0,0 +1,62 @@ +from cpp11_final_class import * + +fc1 = FinalClass1() +fc1.method1() + +fc2 = FinalClass2() +fc2.method2() + +fc3 = FinalClass3() +fc3.method3() + +fc4 = FinalClass4() +fc4.method4() +fc4final = cvar.final +cvar.final.method4() + +fc5 = FinalClass5() +fc5.method5() +fc5.final_member_var.finalmethod() +fc5final = fc5.get_final_member() +fc5final.finalmethod() +fc5final = fc5.get_final_member2() +fc5final.finalmethod() + +fc6 = FinalClass6() +fc6.method6() +fc6.final() + +o = override() +o.omethod(); + +y = Y() +fv4 = FinalVar4() +yy = fv4.final + +fv5 = FinalVar5() +yy = fv5.final + +fv6 = FinalVar6() +yy = fv6.final + +fv7 = FinalVar7() +yy = fv7.final + +fv8 = FinalVar8() +yy = fv8.final + +fv9 = FinalVar9() +yy = fv9.final + +fv10 = FinalVar10() +fv10.a10(y) +fv10.b10(y) + +fe1 = FinalEnum1() +fe1.enum_in(FinalEnum1.final) + +fe2 = FinalEnum2() +fe2f = fe2.final + +s3f = Space3_final() +s3f.fmethod(); diff --git a/Examples/test-suite/python/final_c_runme.py b/Examples/test-suite/python/final_c_runme.py new file mode 100644 index 000000000..9ef4ded62 --- /dev/null +++ b/Examples/test-suite/python/final_c_runme.py @@ -0,0 +1,6 @@ +import final_c + +final_c.init() +f = final_c.cvar.final +if (f.yval != 123): + raise RuntimeError("f.yval fail") diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index d9c00809b..16ccb1249 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -13,14 +13,14 @@ * some point. Beware. * ----------------------------------------------------------------------------- */ -/* There are 6 known shift-reduce conflicts in this file, fail compilation if any - more are introduced. +/* There are a small number of known shift-reduce conflicts in this file, fail + compilation if any more are introduced. Please don't increase the number of the conflicts if at all possible. And if you really have no choice but to do it, make sure you clearly document each new conflict in this file. */ -%expect 6 +%expect 7 %{ #define yylex yylex @@ -1716,6 +1716,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) %type lambda_introducer lambda_body lambda_template; %type lambda_tail; %type virt_specifier_seq virt_specifier_seq_opt; +%type class_virt_specifier_opt; %% @@ -3708,7 +3709,11 @@ cpp_declaration : cpp_class_decl { $$ = $1; } /* A simple class/struct/union definition */ -cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { + +/* Note that class_virt_specifier_opt for supporting final classes introduces one shift-reduce conflict + with C style variable declarations, such as: struct X final; */ + +cpp_class_decl: storage_class cpptype idcolon class_virt_specifier_opt inherit LBRACE { String *prefix; List *bases = 0; Node *scope = 0; @@ -3716,10 +3721,10 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { $$ = new_node("class"); Setline($$,cparse_start_line); Setattr($$,"kind",$2); - if ($4) { - Setattr($$,"baselist", Getattr($4,"public")); - Setattr($$,"protectedbaselist", Getattr($4,"protected")); - Setattr($$,"privatebaselist", Getattr($4,"private")); + if ($5) { + Setattr($$,"baselist", Getattr($5,"public")); + Setattr($$,"protectedbaselist", Getattr($5,"protected")); + Setattr($$,"privatebaselist", Getattr($5,"private")); } Setattr($$,"allows_typedef","1"); @@ -3747,8 +3752,8 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { Setattr($$, "Classprefix", $3); Classprefix = NewString($3); /* Deal with inheritance */ - if ($4) - bases = Swig_make_inherit_list($3,Getattr($4,"public"),Namespaceprefix); + if ($5) + bases = Swig_make_inherit_list($3,Getattr($5,"public"),Namespaceprefix); prefix = SwigType_istemplate_templateprefix($3); if (prefix) { String *fbase, *tbase; @@ -3828,7 +3833,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { Delattr($$, "prev_symtab"); /* Check for pure-abstract class */ - Setattr($$,"abstracts", pure_abstracts($7)); + Setattr($$,"abstracts", pure_abstracts($8)); /* This bit of code merges in a previously defined %extend directive (if any) */ { @@ -3844,12 +3849,12 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { scpname = Swig_symbol_qualifiedscopename(0); Setattr(classes, scpname, $$); - appendChild($$, $7); + appendChild($$, $8); if (am) Swig_extend_append_previous($$, am); - p = $9; + p = $10; if (p && !nscope_inner) { if (!cparse_cplusplus && currentOuterClass) appendChild(currentOuterClass, p); @@ -3873,8 +3878,8 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { } p = nextSibling(p); } - if ($9 && Cmp($1,"typedef") == 0) - add_typedef_name($$, $9, $3, cscope, scpname); + if ($10 && Cmp($1,"typedef") == 0) + add_typedef_name($$, $10, $3, cscope, scpname); Delete(scpname); if (cplus_mode != CPLUS_PUBLIC) { @@ -3896,12 +3901,12 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { if (cplus_mode == CPLUS_PRIVATE) { $$ = 0; /* skip private nested classes */ } else if (cparse_cplusplus && currentOuterClass && ignore_nested_classes && !GetFlag($$, "feature:flatnested")) { - $$ = nested_forward_declaration($1, $2, $3, Copy($3), $9); + $$ = nested_forward_declaration($1, $2, $3, Copy($3), $10); } else if (nscope_inner) { /* this is tricky */ /* we add the declaration in the original namespace */ if (Strcmp(nodeType(nscope_inner), "class") == 0 && cparse_cplusplus && ignore_nested_classes && !GetFlag($$, "feature:flatnested")) - $$ = nested_forward_declaration($1, $2, $3, Copy($3), $9); + $$ = nested_forward_declaration($1, $2, $3, Copy($3), $10); appendChild(nscope_inner, $$); Swig_symbol_setscope(Getattr(nscope_inner, "symtab")); Delete(Namespaceprefix); @@ -3913,14 +3918,14 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { Swig_symbol_setscope(cscope); Delete(Namespaceprefix); Namespaceprefix = Swig_symbol_qualifiedscopename(0); - add_symbols($9); + add_symbols($10); if (nscope) { $$ = nscope; /* here we return recreated namespace tower instead of the class itself */ - if ($9) { - appendSibling($$, $9); + if ($10) { + appendSibling($$, $10); } } else if (!SwigType_istemplate(ty) && template_parameters == 0) { /* for template we need the class itself */ - $$ = $9; + $$ = $10; } } else { Delete(yyrename); @@ -3931,7 +3936,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { outer = Getattr(outer, "nested:outer"); appendSibling(outer, $$); Swig_symbol_setscope(cscope); /* declaration goes in the parent scope */ - add_symbols($9); + add_symbols($10); set_scope_to_global(); Delete(Namespaceprefix); Namespaceprefix = Swig_symbol_qualifiedscopename(0); @@ -3944,7 +3949,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { } else { yyrename = Copy(Getattr($$, "class_rename")); add_symbols($$); - add_symbols($9); + add_symbols($10); Delattr($$, "class_rename"); } } @@ -7062,6 +7067,14 @@ virt_specifier_seq_opt : virt_specifier_seq { } ; +class_virt_specifier_opt : FINAL { + $$ = NewString("1"); + } + | empty { + $$ = 0; + } + ; + exception_specification : THROW LPAREN parms RPAREN { $$.throws = $3; $$.throwf = NewString("1"); From 564468078858a03d578c43a944fd7f1cf8dbcf41 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 6 Oct 2022 00:29:03 +0100 Subject: [PATCH 057/217] Doxygen Java fix quoting for \image command Closes #2048 --- CHANGES.current | 4 ++++ Examples/test-suite/doxygen_translate.i | 1 + .../test-suite/java/doxygen_translate_all_tags_runme.java | 2 +- Examples/test-suite/java/doxygen_translate_runme.java | 3 ++- Examples/test-suite/python/doxygen_translate_runme.py | 1 + Source/Doxygen/javadoc.cxx | 6 +++++- 6 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index bd591d430..2866a838f 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-06: wsfulton + [Java] #Fix quoting for doxygen \image command to quote the output + file name generated into the html src attribute. + 2022-10-05: benjamin-sch [Python] added an interpreter counter to fix deinitialization issues if multiple subinterpreters are used diff --git a/Examples/test-suite/doxygen_translate.i b/Examples/test-suite/doxygen_translate.i index bb0af1c14..0d11a21d0 100644 --- a/Examples/test-suite/doxygen_translate.i +++ b/Examples/test-suite/doxygen_translate.i @@ -59,6 +59,7 @@ * \endif * * \image html testImage.bmp "Hello, world!" width=10cm + * \image html "test image.jpg" "Test jpeg" width=10cm * *
      * diff --git a/Examples/test-suite/java/doxygen_translate_all_tags_runme.java b/Examples/test-suite/java/doxygen_translate_all_tags_runme.java index 56272bf84..80087c65a 100644 --- a/Examples/test-suite/java/doxygen_translate_all_tags_runme.java +++ b/Examples/test-suite/java/doxygen_translate_all_tags_runme.java @@ -81,7 +81,7 @@ public class doxygen_translate_all_tags_runme { " If not: SOMECONDITION {\n" + " This is printed if not \n" + " }\n" + - " \"Hello,\n" + + " \"Hello,\n" + " Some text \n" + " describing invariant. \n"); diff --git a/Examples/test-suite/java/doxygen_translate_runme.java b/Examples/test-suite/java/doxygen_translate_runme.java index b049a6466..c55c95150 100644 --- a/Examples/test-suite/java/doxygen_translate_runme.java +++ b/Examples/test-suite/java/doxygen_translate_runme.java @@ -69,7 +69,8 @@ public class doxygen_translate_runme { " This is printed if not}\n" + " \n" + " \n" + - " \"Hello,\n" + + " \"Hello,\n" + + " \"Test\n" + " \n" + "
        \n" + " \n" + diff --git a/Examples/test-suite/python/doxygen_translate_runme.py b/Examples/test-suite/python/doxygen_translate_runme.py index 38dca2ef9..a62df4a1d 100644 --- a/Examples/test-suite/python/doxygen_translate_runme.py +++ b/Examples/test-suite/python/doxygen_translate_runme.py @@ -58,6 +58,7 @@ If not: SOMECONDITION { } Image: testImage.bmp("Hello, world!") +Image: "test image.jpg"("Test jpeg") diff --git a/Source/Doxygen/javadoc.cxx b/Source/Doxygen/javadoc.cxx index eafa57317..9f9f2e8e7 100644 --- a/Source/Doxygen/javadoc.cxx +++ b/Source/Doxygen/javadoc.cxx @@ -463,7 +463,11 @@ void JavaDocConverter::handleTagImage(DoxygenEntity &tag, std::string &translate if (it != tag.entityList.end()) title = it->data; - translatedComment += " Date: Thu, 6 Oct 2022 00:36:59 +0100 Subject: [PATCH 058/217] Testcase warning suppression --- Examples/test-suite/final_c.i | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Examples/test-suite/final_c.i b/Examples/test-suite/final_c.i index 448d08d1e..42cac11f1 100644 --- a/Examples/test-suite/final_c.i +++ b/Examples/test-suite/final_c.i @@ -1,5 +1,7 @@ %module final_c +%warnfilter(SWIGWARN_PARSE_KEYWORD) final; // 'final' is a java keyword, renaming to '_final' + %inline %{ struct Y { int yval; From 07f265a3bf92e9bc3710cc7813c501eb751f53ba Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 6 Oct 2022 00:38:03 +0100 Subject: [PATCH 059/217] Changes file typo fix --- CHANGES.current | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 2866a838f..efb3444ec 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -8,7 +8,7 @@ Version 4.1.0 (in progress) =========================== 2022-10-06: wsfulton - [Java] #Fix quoting for doxygen \image command to quote the output + [Java] #2048 Fix quoting for doxygen \image command to quote the output file name generated into the html src attribute. 2022-10-05: benjamin-sch From bc87fe151e10ca392aa268c92b593d567b254762 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 6 Oct 2022 00:45:53 +0100 Subject: [PATCH 060/217] Fix python/c++ coding confusion! Visual c++ does not support 'and' yet. --- Source/Doxygen/javadoc.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Doxygen/javadoc.cxx b/Source/Doxygen/javadoc.cxx index 9f9f2e8e7..f594ecafa 100644 --- a/Source/Doxygen/javadoc.cxx +++ b/Source/Doxygen/javadoc.cxx @@ -464,7 +464,7 @@ void JavaDocConverter::handleTagImage(DoxygenEntity &tag, std::string &translate title = it->data; translatedComment += "= 2 && file[0] == '"' && file[file.size() - 1] == '"') translatedComment += file; else translatedComment += "\"" + file + "\""; From 6f3f4fbdf163cef537960620e48190f36ad2c08b Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 6 Oct 2022 10:56:04 +1300 Subject: [PATCH 061/217] [Python] Remove deprecated and apparently useless defarg.swg The only documentation is in the file itself and describes a Python wrapper around the C function defined here, but digging though the git history this Python wrapper doesn't seem to have ever actually been generated by SWIG. This file was also marked as deprecated in 2005. Fixes #2390 Fixes #2391 --- CHANGES.current | 11 ++++++++++- Lib/python/README | 1 - Lib/python/defarg.swg | 37 ------------------------------------- 3 files changed, 10 insertions(+), 39 deletions(-) delete mode 100644 Lib/python/defarg.swg diff --git a/CHANGES.current b/CHANGES.current index efb3444ec..b4eeaf3a2 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,16 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-06: olly + [Python] #2390 Remove deprecated and apparently useless defarg.swg + + The only documentation is in the file itself and describes a Python + wrapper around the C function defined here, but digging though the + git history this Python wrapper doesn't seem to have ever actually + been generated by SWIG. + + This file was also marked as deprecated in 2005. + 2022-10-06: wsfulton [Java] #2048 Fix quoting for doxygen \image command to quote the output file name generated into the html src attribute. @@ -14,7 +24,6 @@ Version 4.1.0 (in progress) 2022-10-05: benjamin-sch [Python] added an interpreter counter to fix deinitialization issues if multiple subinterpreters are used - 2022-10-05: olly, wsfulton #672 Add support for parsing C++11 final classes such as: diff --git a/Lib/python/README b/Lib/python/README index fa8ef61e7..70968e7dd 100644 --- a/Lib/python/README +++ b/Lib/python/README @@ -101,4 +101,3 @@ std_container.i general common code for the STD/STL containers std_vectora.i vector + allocator (allocators are now supported in STD/STL) typemaps.i old in/out typemaps (doesn't need to be included) -defarg.swg for processing default arguments with shadow classes diff --git a/Lib/python/defarg.swg b/Lib/python/defarg.swg deleted file mode 100644 index ba5ff43d4..000000000 --- a/Lib/python/defarg.swg +++ /dev/null @@ -1,37 +0,0 @@ -/* This file defines an internal function for processing default arguments - with proxy classes. - - There seems to be no straightforward way to write proxy functions - involving default arguments. For example : - - def foo(arg1,arg2,*args): - proxyc.foo(arg1,arg2,args) - - This fails because args is now a tuple and SWIG doesn't know what to - do with it. - - This file allows a different approach : - - def foo(arg1,arg2,*args): - proxyc.__call_defarg(proxyc.foo,(arg1,arg2,)+args) - - Basically, we form a new tuple from the object, call this special - __call_defarg method and it passes control to the real wrapper function. - An ugly hack, but it works. -*/ - -SWIGINTERN PyObject *swig_call_defargs(PyObject *self, PyObject *args) { - PyObject *func; - PyObject *parms; - - if (!PyArg_ParseTuple(args, "OO", &func, &parms)) - return NULL; - - if (!PyCallable_Check(func)) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(PyExc_TypeError, "__call_defarg : Need a callable object!"); - SWIG_PYTHON_THREAD_END_BLOCK; - return NULL; - } - return PyObject_Call(func, parms, NULL); -} From 631b41ae7b454b8593af56c65c1451db9e174a52 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 6 Oct 2022 13:16:39 +1300 Subject: [PATCH 062/217] Use https for swig.org links --- ANNOUNCE | 6 +++--- CCache/ccache.yo | 2 +- CHANGES | 4 ++-- Doc/Devel/engineering.html | 2 +- Doc/Manual/CCache.html | 2 +- Doc/Manual/Perl5.html | 2 +- Doc/Manual/Preface.html | 18 +++++++++--------- Doc/Manual/Python.html | 2 +- Doc/Manual/SWIG.html | 4 ++-- Doc/Manual/SWIGPlus.html | 4 ++-- Doc/Manual/Windows.html | 4 ++-- Examples/go/index.html | 2 +- Examples/java/index.html | 2 +- Examples/perl5/index.html | 2 +- Examples/python/index.html | 2 +- Examples/ruby/index.html | 2 +- Examples/tcl/index.html | 2 +- Examples/test-suite/global_immutable_vars.i | 2 +- .../test-suite/global_immutable_vars_cpp.i | 2 +- Lib/pointer.i | 2 +- README | 12 ++++++------ RELEASENOTES | 6 +++--- Source/CParse/cparse.h | 2 +- Source/CParse/cscanner.c | 2 +- Source/CParse/parser.y | 2 +- Source/CParse/templ.c | 2 +- Source/CParse/util.c | 2 +- Source/DOH/base.c | 2 +- Source/DOH/doh.h | 2 +- Source/DOH/dohint.h | 2 +- Source/DOH/file.c | 2 +- Source/DOH/fio.c | 2 +- Source/DOH/hash.c | 2 +- Source/DOH/list.c | 2 +- Source/DOH/memory.c | 2 +- Source/DOH/string.c | 2 +- Source/DOH/void.c | 2 +- Source/Doxygen/doxycommands.h | 2 +- Source/Doxygen/doxyentity.cxx | 2 +- Source/Doxygen/doxyentity.h | 2 +- Source/Doxygen/doxyparser.cxx | 2 +- Source/Doxygen/doxyparser.h | 2 +- Source/Doxygen/doxytranslator.cxx | 2 +- Source/Doxygen/doxytranslator.h | 2 +- Source/Doxygen/javadoc.cxx | 2 +- Source/Doxygen/javadoc.h | 2 +- Source/Doxygen/pydoc.cxx | 2 +- Source/Doxygen/pydoc.h | 2 +- Source/Include/swigwarn.h | 2 +- Source/Modules/allocate.cxx | 2 +- Source/Modules/cffi.cxx | 2 +- Source/Modules/contract.cxx | 2 +- Source/Modules/csharp.cxx | 2 +- Source/Modules/d.cxx | 2 +- Source/Modules/directors.cxx | 2 +- Source/Modules/emit.cxx | 2 +- Source/Modules/guile.cxx | 2 +- Source/Modules/interface.cxx | 2 +- Source/Modules/java.cxx | 2 +- Source/Modules/javascript.cxx | 2 +- Source/Modules/lang.cxx | 2 +- Source/Modules/lua.cxx | 2 +- Source/Modules/main.cxx | 4 ++-- Source/Modules/mzscheme.cxx | 2 +- Source/Modules/nested.cxx | 2 +- Source/Modules/ocaml.cxx | 2 +- Source/Modules/octave.cxx | 2 +- Source/Modules/overload.cxx | 2 +- Source/Modules/perl5.cxx | 2 +- Source/Modules/php.cxx | 2 +- Source/Modules/python.cxx | 2 +- Source/Modules/r.cxx | 2 +- Source/Modules/ruby.cxx | 2 +- Source/Modules/scilab.cxx | 4 ++-- Source/Modules/swigmain.cxx | 2 +- Source/Modules/swigmod.h | 2 +- Source/Modules/tcl8.cxx | 2 +- Source/Modules/typepass.cxx | 2 +- Source/Modules/utils.cxx | 2 +- Source/Modules/xml.cxx | 2 +- Source/Preprocessor/cpp.c | 2 +- Source/Preprocessor/expr.c | 2 +- Source/Preprocessor/preprocessor.h | 2 +- Source/Swig/cwrap.c | 2 +- Source/Swig/deprecate.c | 2 +- Source/Swig/error.c | 2 +- Source/Swig/extend.c | 2 +- Source/Swig/fragment.c | 2 +- Source/Swig/getopt.c | 2 +- Source/Swig/include.c | 2 +- Source/Swig/misc.c | 6 +++--- Source/Swig/naming.c | 2 +- Source/Swig/parms.c | 2 +- Source/Swig/scanner.c | 2 +- Source/Swig/stype.c | 2 +- Source/Swig/swig.h | 2 +- Source/Swig/swigfile.h | 2 +- Source/Swig/swigopt.h | 2 +- Source/Swig/swigparm.h | 2 +- Source/Swig/swigscan.h | 2 +- Source/Swig/swigtree.h | 2 +- Source/Swig/swigwrap.h | 2 +- Source/Swig/symbol.c | 2 +- Source/Swig/tree.c | 2 +- Source/Swig/typemap.c | 2 +- Source/Swig/typeobj.c | 2 +- Source/Swig/typesys.c | 2 +- Source/Swig/wrapfunc.c | 2 +- Tools/cmake/swigconfig.h.in | 2 +- configure.ac | 2 +- 110 files changed, 135 insertions(+), 135 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index e78be2268..90ac94f52 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,6 +1,6 @@ *** ANNOUNCE: SWIG 4.1.0 (in progress) *** -http://www.swig.org +https://www.swig.org We're pleased to announce SWIG-4.1.0, the latest SWIG release. @@ -19,7 +19,7 @@ and user interface development for large C/C++ systems. Release Notes ============= Detailed release notes are available with the release and are also -published on the SWIG web site at http://swig.org/release.html. +published on the SWIG web site at https://swig.org/release.html. Availability ============ @@ -32,7 +32,7 @@ A Windows version is also available at https://prdownloads.sourceforge.net/swig/swigwin-4.1.0.zip Please report problems with this release to the swig-devel mailing list, -details at http://www.swig.org/mail.html. +details at https://www.swig.org/mail.html. --- The SWIG Developers diff --git a/CCache/ccache.yo b/CCache/ccache.yo index 2477662dc..fd5ba89c3 100644 --- a/CCache/ccache.yo +++ b/CCache/ccache.yo @@ -409,7 +409,7 @@ ccache was adapted to create ccache-swig for use with SWIG by William Fulton. If you wish to report a problem or make a suggestion then please email the SWIG developers on the swig-devel mailing list, see -url(http://www.swig.org/mail.html)(http://www.swig.org/mail.html) +url(https://www.swig.org/mail.html)(https://www.swig.org/mail.html) ccache is released under the GNU General Public License version 2 or later. Please see the file COPYING for license details. diff --git a/CHANGES b/CHANGES index 1dc87f93e..8f3cb9e26 100644 --- a/CHANGES +++ b/CHANGES @@ -3302,7 +3302,7 @@ Version 3.0.0 (16 Mar 2014) project has been further extended. The C++11 support is comprehensive, but by no means complete or without limitations. Full details for each new feature in C++11 is covered in the CPlusPlus11.html chapter in the documentation which is included in SWIG and also available - online at http://www.swig.org/Doc3.0/CPlusPlus11.html. + online at https://www.swig.org/Doc3.0/CPlusPlus11.html. 2014-03-14: v-for-vandal [Lua] Numerous Lua improvements: @@ -5784,7 +5784,7 @@ Version 2.0.0 (2 June 2010) 2010-02-27: wsfulton License code changes: SWIG Source is GPL-v3 and library code license is now clearer - and is provided under a very permissive license. See http://www.swig.org/legal.html. + and is provided under a very permissive license. See https://www.swig.org/legal.html. 2010-02-13: wsfulton [Ruby] A few fixes for compiling under ruby-1.9.x including patch from 'Nibble'. diff --git a/Doc/Devel/engineering.html b/Doc/Devel/engineering.html index c12eb1328..c2cad4804 100644 --- a/Doc/Devel/engineering.html +++ b/Doc/Devel/engineering.html @@ -130,7 +130,7 @@ like this: * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * xxx.c * diff --git a/Doc/Manual/CCache.html b/Doc/Manual/CCache.html index 1a94709ae..e6935b895 100644 --- a/Doc/Manual/CCache.html +++ b/Doc/Manual/CCache.html @@ -463,7 +463,7 @@ ccache was adapted to create ccache-swig for use with SWIG by William Fulton.

        If you wish to report a problem or make a suggestion then please email the SWIG developers on the swig-devel mailing list, see -http://www.swig.org/mail.html +https://www.swig.org/mail.html

        ccache is released under the GNU General Public License version 2 or later. Please see the file COPYING for license details. diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index c130cdef4..d8f24b094 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -604,7 +604,7 @@ source has a list of macros that are known to conflict with either standard head other headers. But if you get macro type conflicts from other macros not included in Lib/perl5/noembed.h while compiling the wrapper, you will have to find the macro that conflicts and add an #undef into the .i file. Please report -any conflicting macros you find to swig-user mailing list. +any conflicting macros you find to swig-user mailing list.

        31.2.7 Compiling for 64-bit platforms

        diff --git a/Doc/Manual/Preface.html b/Doc/Manual/Preface.html index 41f21d48d..9bb8bcb99 100644 --- a/Doc/Manual/Preface.html +++ b/Doc/Manual/Preface.html @@ -80,7 +80,7 @@ Some target languages were disabled as part of a clean up and others were given

        The LICENSE file shipped with SWIG in the top level directory contains the SWIG license. For further insight into the license including the license of SWIG's output code, please visit -the SWIG legal page - http://www.swig.org/legal.html. +the SWIG legal page - https://www.swig.org/legal.html.

        @@ -98,7 +98,7 @@ The official location of SWIG related material is

        @@ -111,7 +111,7 @@ You can also subscribe to the swig-user mailing list by visiting the page

        @@ -125,7 +125,7 @@ about this can be obtained at:

        @@ -231,7 +231,7 @@ detailed release notes for previous releases and summary release notes from SWIG SWIG is an unfunded project that would not be possible without the contributions of many people working in their spare time. If you have benefitted from using SWIG, please consider -Donating to SWIG to keep development going. +Donating to SWIG to keep development going. There have been a large varied number of people who have made contributions at all levels over time. Contributors are mentioned either in the COPYRIGHT file or CHANGES files shipped with SWIG or in submitted bugs. @@ -244,8 +244,8 @@ are mentioned either in the COPYRIGHT file or CHANGES files shipped with SWIG or Although every attempt has been made to make SWIG bug-free, we are also trying to make feature improvements that may introduce bugs. To report a bug, either send mail to the SWIG developer -list at the swig-devel mailing list or report a bug -at the SWIG bug tracker. In your report, be as specific as +list at the swig-devel mailing list or report a bug +at the SWIG bug tracker. In your report, be as specific as possible, including (if applicable), error messages, tracebacks (if a core dump occurred), corresponding portions of the SWIG interface file used, and any important pieces of the SWIG generated wrapper code. We @@ -273,7 +273,7 @@ the main SWIG distribution. There is no need to download anything else. These installation instructions are for using the distributed tarball, for example, swig-3.0.8.tar.gz. If you wish to build and install from source on Github, extra steps are required. -Please see the Bleeding Edge page on the SWIG website. +Please see the Bleeding Edge page on the SWIG website.

        @@ -357,7 +357,7 @@ Note: If you checked the code out via Git, you will have to run ./autogen.sh before ./configure. In addition, a full build of SWIG requires a number of packages to be installed. Full instructions at -SWIG bleeding edge. +SWIG bleeding edge.

      diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 0496299eb..c1cc1796d 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -3504,7 +3504,7 @@ The insert code can be seen at the start of the generated .py file:
      -# This file was automatically generated by SWIG (http://www.swig.org).
      +# This file was automatically generated by SWIG (https://www.swig.org).
       # Version 4.0.0
       #
       # Do not make changes to this file unless you know what you are doing--modify
      diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html
      index e3e11841d..bc4e9ad60 100644
      --- a/Doc/Manual/SWIG.html
      +++ b/Doc/Manual/SWIG.html
      @@ -3664,8 +3664,8 @@ In the process of building an interface, SWIG may encounter syntax errors or
       other problems.  The best way to deal with this is to simply copy the offending
       code into a separate interface file and edit it.   However, the SWIG developers
       have worked very hard to improve the SWIG parser--you should report parsing errors
      -to the swig-devel mailing list or to the 
      -SWIG bug tracker.
      +to the swig-devel mailing list or to the
      +SWIG bug tracker.
       

      5.7.2 The SWIG interface file

      diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 820c5088b..b4b9acb17 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -2147,7 +2147,7 @@ This error means that the target language module supports overloading, but for some reason there is no type-checking rule that can be used to generate a working dispatch function. The resulting behavior is then undefined. You should report this as a bug to the -SWIG bug tracking database +SWIG bug tracking database if this is due to one of the typemaps supplied with SWIG.

      @@ -2324,7 +2324,7 @@ members (of all classes): Note: the *:: syntax is non-standard C++, but the '*' is meant to be a wildcard that matches any class name (we couldn't think of a better alternative so if you have a better idea, send email to -the swig-devel mailing list. +the swig-devel mailing list.

      diff --git a/Doc/Manual/Windows.html b/Doc/Manual/Windows.html index c822d2ca3..e55077893 100644 --- a/Doc/Manual/Windows.html +++ b/Doc/Manual/Windows.html @@ -60,7 +60,7 @@ Usage within the Unix like environments MinGW and Cygwin is also detailed. SWIG does not come with the usual Windows type installation program, however it is quite easy to get started. The main steps are:

        -
      • Download the swigwin zip package from the SWIG website and unzip into a directory. This is all that needs downloading for the Windows platform. +
      • Download the swigwin zip package from the SWIG website and unzip into a directory. This is all that needs downloading for the Windows platform.
      • Set environment variables as described in the SWIG Windows Examples section in order to run examples using Visual C++.
      @@ -370,7 +370,7 @@ The short abbreviated instructions follow...

      The step by step instructions to download and install MinGW and MSYS, then download and build the latest version of SWIG from Github follow... -Note that the instructions for obtaining SWIG from Github are also online at SWIG Bleeding Edge. +Note that the instructions for obtaining SWIG from Github are also online at SWIG Bleeding Edge.

      diff --git a/Examples/go/index.html b/Examples/go/index.html index 370424c54..b8af100ff 100644 --- a/Examples/go/index.html +++ b/Examples/go/index.html @@ -94,6 +94,6 @@ All of the examples were last tested with the following configuration

    Your mileage may vary. If you experience a problem, please let us know by -contacting us on the mailing lists. +contacting us on the mailing lists. diff --git a/Examples/java/index.html b/Examples/java/index.html index 007e14dbc..bebf1b1bf 100644 --- a/Examples/java/index.html +++ b/Examples/java/index.html @@ -58,7 +58,7 @@ The examples have been extensively tested on the following platforms: Your mileage may vary. If you experience a problem, please let us know by -contacting us on the mailing lists. +contacting us on the mailing lists. diff --git a/Examples/perl5/index.html b/Examples/perl5/index.html index 23c8ff658..2daabaaf9 100644 --- a/Examples/perl5/index.html +++ b/Examples/perl5/index.html @@ -72,7 +72,7 @@ Please see the Windows page in the m Due to wide variations in the Perl C API and differences between versions such as the ActivePerl release for Windows, the code generated by SWIG is extremely messy. If the code doesn't compile or work with your version of Perl, please let us know by -contacting us on the mailing lists. +contacting us on the mailing lists. Better yet, send us a patch. diff --git a/Examples/python/index.html b/Examples/python/index.html index 17d45fb7b..fcb7eace8 100644 --- a/Examples/python/index.html +++ b/Examples/python/index.html @@ -92,7 +92,7 @@ For Python 2, set the environment variable PY2=1.

    Your mileage may vary. If you experience a problem, please let us know by -contacting us on the mailing lists. +contacting us on the mailing lists. diff --git a/Examples/ruby/index.html b/Examples/ruby/index.html index 4f4aa0ad2..ceb6c925d 100644 --- a/Examples/ruby/index.html +++ b/Examples/ruby/index.html @@ -87,7 +87,7 @@ The examples have been extensively tested on the following platforms: Your mileage may vary. If you experience a problem, please let us know by -contacting us on the mailing lists. +contacting us on the mailing lists. diff --git a/Examples/tcl/index.html b/Examples/tcl/index.html index b32726002..acd90029f 100644 --- a/Examples/tcl/index.html +++ b/Examples/tcl/index.html @@ -63,7 +63,7 @@ The examples have been extensively tested on the following platforms: Your mileage may vary. If you experience a problem, please let us know by -contacting us on the mailing lists. +contacting us on the mailing lists. diff --git a/Examples/test-suite/global_immutable_vars.i b/Examples/test-suite/global_immutable_vars.i index ab0d4f7a8..9545b297a 100644 --- a/Examples/test-suite/global_immutable_vars.i +++ b/Examples/test-suite/global_immutable_vars.i @@ -1,7 +1,7 @@ %module global_immutable_vars // Test immutable and mutable global variables, -// see http://www.swig.org/Doc4.0/SWIGDocumentation.html#SWIG_readonly_variables +// see https://www.swig.org/Doc4.0/SWIGDocumentation.html#SWIG_readonly_variables %inline %{ int default_mutable_var = 40; diff --git a/Examples/test-suite/global_immutable_vars_cpp.i b/Examples/test-suite/global_immutable_vars_cpp.i index 40cc08e54..b5d5e0fd3 100644 --- a/Examples/test-suite/global_immutable_vars_cpp.i +++ b/Examples/test-suite/global_immutable_vars_cpp.i @@ -1,7 +1,7 @@ %module global_immutable_vars_cpp // Test immutable and mutable global variables, -// see http://www.swig.org/Doc4.0/SWIGDocumentation.html#SWIG_readonly_variables +// see https://www.swig.org/Doc4.0/SWIGDocumentation.html#SWIG_readonly_variables %inline %{ int default_mutable_var = 40; diff --git a/Lib/pointer.i b/Lib/pointer.i index ea8e535ab..9ac04ebfc 100644 --- a/Lib/pointer.i +++ b/Lib/pointer.i @@ -4,7 +4,7 @@ %echo "pointer.i is deprecated. Use cpointer.i instead." -%echo "See http://www.swig.org/Doc3.0/Library.html" +%echo "See https://www.swig.org/Doc3.0/Library.html" diff --git a/README b/README index ba8ded0d5..ff28090fb 100644 --- a/README +++ b/README @@ -14,7 +14,7 @@ language. Up-to-date SWIG related information can be found at - http://www.swig.org + https://www.swig.org A SWIG FAQ and other hints can be found on the SWIG Wiki: @@ -26,7 +26,7 @@ Please see the LICENSE file for details of the SWIG license. For further insight into the license including the license of SWIG's output code, please visit - http://www.swig.org/legal.html + https://www.swig.org/legal.html Release Notes ============= @@ -49,7 +49,7 @@ There is some technical developer documentation available in the Doc/Devel subdirectory. This is not necessarily up-to-date, but it has some information on SWIG internals. -Documentation is also online at http://www.swig.org/doc.html. +Documentation is also online at https://www.swig.org/doc.html. Backwards Compatibility ======================= @@ -70,7 +70,7 @@ full installation instructions for Windows, Unix and Mac OS X using the release tarball/zip file. The INSTALL file has generic build and installation instructions for Unix users. Users wishing to build and install code from Github should -visit http://swig.org/svn.html to obtain the more detailed +visit https://swig.org/svn.html to obtain the more detailed instructions required for building code obtained from Github - extra steps are required compared to building from the release tarball. @@ -92,7 +92,7 @@ will convert these old style project files into a current solution file. Known Issues ============ There are minor known bugs, details of which are in the bug tracker, see -http://www.swig.org/bugs.html. +https://www.swig.org/bugs.html. Troubleshooting =============== @@ -134,7 +134,7 @@ and Windows). All contributions help. If you would like to join the SWIG development team or contribute a language module to the distribution, please contact the swig-devel -mailing list, details at http://www.swig.org/mail.html. +mailing list, details at https://www.swig.org/mail.html. -- The SWIG Maintainers diff --git a/RELEASENOTES b/RELEASENOTES index 33f7e4c45..237afa8c9 100644 --- a/RELEASENOTES +++ b/RELEASENOTES @@ -5,7 +5,7 @@ and CHANGES files. Release Notes ============= Detailed release notes are available with the release and are also -published on the SWIG web site at http://swig.org/release.html. +published on the SWIG web site at https://swig.org/release.html. SWIG-4.1.0 summary: - Add PHP 8 support. @@ -131,7 +131,7 @@ SWIG-3.0.1 summary: SWIG-3.0.0 summary: - This is a major new release focusing primarily on C++ improvements. - C++11 support added. Please see documentation for details of supported - features: http://www.swig.org/Doc3.0/CPlusPlus11.html + features: https://www.swig.org/Doc3.0/CPlusPlus11.html - Nested class support added. This has been taken full advantage of in Java and C#. Other languages can use the nested classes, but require further work for a more natural integration into the target language. @@ -238,7 +238,7 @@ SWIG-2.0.1 summary: and Python language modules. SWIG-2.0.0 summary: -- License changes, see LICENSE file and http://www.swig.org/legal.html. +- License changes, see LICENSE file and https://www.swig.org/legal.html. - Much better nested class/struct support. - Much improved template partial specialization and explicit specialization handling. diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h index ca8127741..2b63f034d 100644 --- a/Source/CParse/cparse.h +++ b/Source/CParse/cparse.h @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * cparse.h * diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index db0e6df27..2eb3f9774 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * scanner.c * diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 16ccb1249..7f685e84e 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * parser.y * diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index 8dc6a7315..68533e633 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * templ.c * diff --git a/Source/CParse/util.c b/Source/CParse/util.c index 714bb2972..00863c035 100644 --- a/Source/CParse/util.c +++ b/Source/CParse/util.c @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * util.c * diff --git a/Source/DOH/base.c b/Source/DOH/base.c index 602c79087..8731a5f11 100644 --- a/Source/DOH/base.c +++ b/Source/DOH/base.c @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * base.c * diff --git a/Source/DOH/doh.h b/Source/DOH/doh.h index 13e9cc23d..45a1f7fc8 100644 --- a/Source/DOH/doh.h +++ b/Source/DOH/doh.h @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * doh.h * diff --git a/Source/DOH/dohint.h b/Source/DOH/dohint.h index a1974ff76..b637debd2 100644 --- a/Source/DOH/dohint.h +++ b/Source/DOH/dohint.h @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * dohint.h * diff --git a/Source/DOH/file.c b/Source/DOH/file.c index 8ec8bd6ae..4bcf5d5e1 100644 --- a/Source/DOH/file.c +++ b/Source/DOH/file.c @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * file.c * diff --git a/Source/DOH/fio.c b/Source/DOH/fio.c index 77419008c..972fb23df 100644 --- a/Source/DOH/fio.c +++ b/Source/DOH/fio.c @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * fio.c * diff --git a/Source/DOH/hash.c b/Source/DOH/hash.c index c1526cbf3..b9d501e3c 100644 --- a/Source/DOH/hash.c +++ b/Source/DOH/hash.c @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * hash.c * diff --git a/Source/DOH/list.c b/Source/DOH/list.c index 3eb30a792..cc619022d 100644 --- a/Source/DOH/list.c +++ b/Source/DOH/list.c @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * list.c * diff --git a/Source/DOH/memory.c b/Source/DOH/memory.c index d461ce392..f8081d3ae 100644 --- a/Source/DOH/memory.c +++ b/Source/DOH/memory.c @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * memory.c * diff --git a/Source/DOH/string.c b/Source/DOH/string.c index 8f321508e..c86cab0be 100644 --- a/Source/DOH/string.c +++ b/Source/DOH/string.c @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * string.c * diff --git a/Source/DOH/void.c b/Source/DOH/void.c index 6111a8c49..bbecca21b 100644 --- a/Source/DOH/void.c +++ b/Source/DOH/void.c @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * void.c * diff --git a/Source/Doxygen/doxycommands.h b/Source/Doxygen/doxycommands.h index 939b56917..782b6ab94 100644 --- a/Source/Doxygen/doxycommands.h +++ b/Source/Doxygen/doxycommands.h @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * doxycommands.h * diff --git a/Source/Doxygen/doxyentity.cxx b/Source/Doxygen/doxyentity.cxx index 8b9f65736..6fe97dd36 100644 --- a/Source/Doxygen/doxyentity.cxx +++ b/Source/Doxygen/doxyentity.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * doxyentity.cxx * diff --git a/Source/Doxygen/doxyentity.h b/Source/Doxygen/doxyentity.h index c18a59b53..e475141a3 100644 --- a/Source/Doxygen/doxyentity.h +++ b/Source/Doxygen/doxyentity.h @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * doxyentity.h * diff --git a/Source/Doxygen/doxyparser.cxx b/Source/Doxygen/doxyparser.cxx index db0fca9f5..0c445f1a0 100644 --- a/Source/Doxygen/doxyparser.cxx +++ b/Source/Doxygen/doxyparser.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * doxyparser.cxx * ----------------------------------------------------------------------------- */ diff --git a/Source/Doxygen/doxyparser.h b/Source/Doxygen/doxyparser.h index c099f23dd..a60446517 100644 --- a/Source/Doxygen/doxyparser.h +++ b/Source/Doxygen/doxyparser.h @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * doxyparser.h * ----------------------------------------------------------------------------- */ diff --git a/Source/Doxygen/doxytranslator.cxx b/Source/Doxygen/doxytranslator.cxx index fb21de75c..a638717ec 100644 --- a/Source/Doxygen/doxytranslator.cxx +++ b/Source/Doxygen/doxytranslator.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * doxytranslator.cxx * diff --git a/Source/Doxygen/doxytranslator.h b/Source/Doxygen/doxytranslator.h index eb527fc6f..f0d3b1b06 100644 --- a/Source/Doxygen/doxytranslator.h +++ b/Source/Doxygen/doxytranslator.h @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * doxytranslator.h * diff --git a/Source/Doxygen/javadoc.cxx b/Source/Doxygen/javadoc.cxx index f594ecafa..a1406b230 100644 --- a/Source/Doxygen/javadoc.cxx +++ b/Source/Doxygen/javadoc.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * javadoc.cxx * ----------------------------------------------------------------------------- */ diff --git a/Source/Doxygen/javadoc.h b/Source/Doxygen/javadoc.h index 6459f05a3..d2c956c9d 100644 --- a/Source/Doxygen/javadoc.h +++ b/Source/Doxygen/javadoc.h @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * javadoc.h * diff --git a/Source/Doxygen/pydoc.cxx b/Source/Doxygen/pydoc.cxx index 7b47a814c..28f6051a7 100644 --- a/Source/Doxygen/pydoc.cxx +++ b/Source/Doxygen/pydoc.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * pydoc.cxx * diff --git a/Source/Doxygen/pydoc.h b/Source/Doxygen/pydoc.h index 8b35d5b62..880ee3069 100644 --- a/Source/Doxygen/pydoc.h +++ b/Source/Doxygen/pydoc.h @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * pydoc.h * diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index 89df97a88..fc379c014 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * swigwarn.h * diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx index 297a4e69d..0e1262f83 100644 --- a/Source/Modules/allocate.cxx +++ b/Source/Modules/allocate.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * allocate.cxx * diff --git a/Source/Modules/cffi.cxx b/Source/Modules/cffi.cxx index 38626420d..f517ef1d3 100644 --- a/Source/Modules/cffi.cxx +++ b/Source/Modules/cffi.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * cffi.cxx * diff --git a/Source/Modules/contract.cxx b/Source/Modules/contract.cxx index 7e0eaf9e0..dfc85ebe7 100644 --- a/Source/Modules/contract.cxx +++ b/Source/Modules/contract.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * contract.cxx * diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 554c2ce56..3cebb346c 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * csharp.cxx * diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index c1f68da07..4704d8d54 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * d.cxx * diff --git a/Source/Modules/directors.cxx b/Source/Modules/directors.cxx index 4ca8b25e5..fbef70aa1 100644 --- a/Source/Modules/directors.cxx +++ b/Source/Modules/directors.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * directors.cxx * diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx index edfa57ccd..74adc5400 100644 --- a/Source/Modules/emit.cxx +++ b/Source/Modules/emit.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * emit.cxx * diff --git a/Source/Modules/guile.cxx b/Source/Modules/guile.cxx index c70896af8..874150e3a 100644 --- a/Source/Modules/guile.cxx +++ b/Source/Modules/guile.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * guile.cxx * diff --git a/Source/Modules/interface.cxx b/Source/Modules/interface.cxx index f6a57eefb..5a9242399 100644 --- a/Source/Modules/interface.cxx +++ b/Source/Modules/interface.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * interface.cxx * diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 3396a1a6e..93d623703 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * java.cxx * diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx index e6e47e3f3..bf0f471b0 100644 --- a/Source/Modules/javascript.cxx +++ b/Source/Modules/javascript.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * javascript.cxx * diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 4abb6b8b5..1e10e51d6 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * lang.cxx * diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx index 5265aa5c1..855acc69d 100644 --- a/Source/Modules/lua.cxx +++ b/Source/Modules/lua.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * lua.cxx * diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 8a3259db8..d2960e9f8 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * main.cxx * @@ -1329,7 +1329,7 @@ int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm) { if (tlm->status == Experimental) { Swig_warning(WARN_LANG_EXPERIMENTAL, "SWIG", 1, "Experimental target language. " "Target language %s specified by %s is an experimental language. " - "Please read about SWIG experimental languages, http://swig.org/Doc4.0/Introduction.html#Introduction_experimental_status.\n", + "Please read about SWIG experimental languages, https://swig.org/Doc4.0/Introduction.html#Introduction_experimental_status.\n", tlm->help ? tlm->help : "", tlm->name); } diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx index 64b699336..6e412a09c 100644 --- a/Source/Modules/mzscheme.cxx +++ b/Source/Modules/mzscheme.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * mzscheme.cxx * diff --git a/Source/Modules/nested.cxx b/Source/Modules/nested.cxx index 808ee5d05..d027eebe5 100644 --- a/Source/Modules/nested.cxx +++ b/Source/Modules/nested.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * nested.cxx * diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx index 6955cdced..7ea453132 100644 --- a/Source/Modules/ocaml.cxx +++ b/Source/Modules/ocaml.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * ocaml.cxx * diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index e427e60a7..04609b017 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * octave.cxx * diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx index 034e0e76f..b94e87ebb 100644 --- a/Source/Modules/overload.cxx +++ b/Source/Modules/overload.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * overload.cxx * diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index db47d1804..add4fd0b6 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * perl5.cxx * diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 2f1c6c326..13b3df686 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * php.cxx * diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 9352424f2..d498a3456 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * python.cxx * diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 536ee1243..3283c96ab 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -5,7 +5,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * r.cxx * diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 5a0602dea..e9d2f7b51 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * ruby.cxx * diff --git a/Source/Modules/scilab.cxx b/Source/Modules/scilab.cxx index 8c5536486..ede6e0c66 100644 --- a/Source/Modules/scilab.cxx +++ b/Source/Modules/scilab.cxx @@ -4,7 +4,7 @@ * 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 http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * scilab.cxx * @@ -957,7 +957,7 @@ public: gatewayXML = NewString(""); Printf(gatewayXML, "\n"); Printf(gatewayXML, "\n"); Printf(gatewayXML, "\n", gatewayName); diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index f89a8c977..92e45fbe0 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -69,15 +69,8 @@ const char *Swig_package_version(void) { * ----------------------------------------------------------------------------- */ void Swig_banner(File *f) { - Printf(f, "/* ----------------------------------------------------------------------------\n\ - * This file was automatically generated by SWIG (https://www.swig.org).\n\ - * Version %s\n\ - *\n\ - * This file is not intended to be easily readable and contains a number of\n\ - * coding conventions designed to improve portability and efficiency. Do not make\n\ - * changes to this file unless you know what you are doing--modify the SWIG\n\ - * interface file instead.\n", Swig_package_version()); - /* String too long for ISO compliance */ + Printf(f, "/* ----------------------------------------------------------------------------\n"); + Swig_banner_target_lang(f, " *"); Printf(f, " * ----------------------------------------------------------------------------- */\n"); } @@ -92,7 +85,7 @@ 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 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); } From 047928d670ac7c5fd530a66e76dd98597299ad4d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 6 Oct 2022 18:06:20 +1300 Subject: [PATCH 067/217] Fix comment typo --- Examples/test-suite/cpp11_move_only_valuewrapper.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/test-suite/cpp11_move_only_valuewrapper.i b/Examples/test-suite/cpp11_move_only_valuewrapper.i index a4194ea86..d9162bf3e 100644 --- a/Examples/test-suite/cpp11_move_only_valuewrapper.i +++ b/Examples/test-suite/cpp11_move_only_valuewrapper.i @@ -4,7 +4,7 @@ * This test case checks SwigValueWrapper and move assignment. * Although not necessary, the test case was developed testing with C++98 compatibility for comparing improvements. * C++11 and later is of course required for the move assignment support. - * C++98 is not actually necesary now as the test-suite only runs this test with compilers that support C++11 and later. + * C++98 is not actually necessary now as the test-suite only runs this test with compilers that support C++11 and later. */ %{ From 37c8185bd3665673151f934b55849766fa664dd3 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 6 Oct 2022 18:06:36 +1300 Subject: [PATCH 068/217] Replace reference to SWIG_POINTER_EXCEPTION in docs This has only been present for backward compatibility since 2006 and now has the value 0 so doesn't do anything, so don't use it as an example of a flag in the docs. --- Doc/Manual/Python.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index c1cc1796d..cc21bc011 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -5377,10 +5377,9 @@ int SWIG_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags)obj to a C pointer. The result of the conversion is placed into the pointer located at ptr. ty is a SWIG type descriptor structure. flags is used to handle error checking and other aspects of conversion. It is the -bitwise-or of several flag values including SWIG_POINTER_EXCEPTION and -SWIG_POINTER_DISOWN. The first flag makes the function raise an exception on type -error. The second flag additionally -steals ownership of an object. Returns 0 on success and -1 on error. +bitwise-or of several flag values including SWIG_POINTER_DISOWN (which steals +ownership of the object) and SWIG_POINTER_NO_NULL (which makes the conversion fail +if the C pointer would be NULL). Returns 0 on success and -1 on error.

    From f54c504150860e709b8db6be04ba45377c46a173 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 6 Oct 2022 18:09:08 +1300 Subject: [PATCH 069/217] Remove dead conditional code SWIG_POINTER_EXCEPTION has had the value zero since 2006 (it's only still present for backward compatibility). --- Lib/python/pyrun.swg | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index eb8ae1673..9b6dd28ee 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -1844,12 +1844,6 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(arg void *result; if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { PyErr_Clear(); -#if SWIG_POINTER_EXCEPTION - if (flags) { - SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); - SWIG_Python_ArgFail(argnum); - } -#endif } return result; } From 19a5f3f4a5adcb2f2bb9e24c20021d1ee52300f2 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 6 Oct 2022 20:36:49 +0100 Subject: [PATCH 070/217] Remove some final testing Given Visual C++ does not work with these tests (tested with VS2022 17.3 and earlier) --- Examples/test-suite/cpp11_final_class.i | 18 +++++++++++++++--- .../python/cpp11_final_class_runme.py | 15 +++++++++------ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Examples/test-suite/cpp11_final_class.i b/Examples/test-suite/cpp11_final_class.i index e6a29e988..4f2429320 100644 --- a/Examples/test-suite/cpp11_final_class.i +++ b/Examples/test-suite/cpp11_final_class.i @@ -8,7 +8,7 @@ %rename(Space1_final) Space1::final::final; #endif #if defined(SWIGOCAML) -%rename(finale) Space2::FinalEnum1::final; +%rename(finale) BrokenSpace::FinalEnum1::final; #endif %inline %{ @@ -105,9 +105,22 @@ struct FinalVar9 { Y final{9}; }; struct FinalVar10 { - void a10(class Y final) {} void b10(Y final) {} }; +} +%} + +// Unfortunately the use of final in BrokenSpace does not work with Visual C++ +// so we limit testing to parsing these by SWIG and then ignoring it all. +%ignore BrokenSpace::FinalVar11; +%ignore BrokenSpace::FinalEnum1; +%ignore BrokenSpace::FinalEnum2; + +namespace BrokenSpace { +using Space2::Y; +struct FinalVar11 { + void a11(class Y final) {} +}; struct FinalEnum1 { enum Enum1 { one, two, final }; void enum_in(Enum1 e) {} @@ -117,7 +130,6 @@ struct FinalEnum2 { enum Enum2 final; }; } -%} %rename(Space3_final) Space3::final; %inline %{ diff --git a/Examples/test-suite/python/cpp11_final_class_runme.py b/Examples/test-suite/python/cpp11_final_class_runme.py index 568a1ca1a..54e289043 100644 --- a/Examples/test-suite/python/cpp11_final_class_runme.py +++ b/Examples/test-suite/python/cpp11_final_class_runme.py @@ -49,14 +49,17 @@ fv9 = FinalVar9() yy = fv9.final fv10 = FinalVar10() -fv10.a10(y) fv10.b10(y) -fe1 = FinalEnum1() -fe1.enum_in(FinalEnum1.final) - -fe2 = FinalEnum2() -fe2f = fe2.final +# Removed due to Visual C++ compiler limitations +# fv11 = FinalVar11() +# fv11.a11(y) +# +# fe1 = FinalEnum1() +# fe1.enum_in(FinalEnum1.final) +# +# fe2 = FinalEnum2() +# fe2f = fe2.final s3f = Space3_final() s3f.fmethod(); From b975f401a935ddcfeb545e6f63db9b950aa65998 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 6 Oct 2022 21:54:03 +0100 Subject: [PATCH 071/217] Re-order language detection in configure.ac Check in alphabetical order to make looking at configure output a tad easier --- configure.ac | 3046 +++++++++++++++++++++++++------------------------- 1 file changed, 1527 insertions(+), 1519 deletions(-) diff --git a/configure.ac b/configure.ac index 78ed6f7df..f88004ab9 100644 --- a/configure.ac +++ b/configure.ac @@ -513,818 +513,415 @@ fi AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) -#-------------------------------------------------------------------- -# Look for Tcl -#-------------------------------------------------------------------- - -TCLINCLUDE= -TCLLIB= -TCLPACKAGE= -TCLLINK= - -AC_ARG_WITH(tclconfig, AS_HELP_STRING([--without-tcl], [Disable Tcl]) -AS_HELP_STRING([--with-tclconfig=path], [Set location of tclConfig.sh]), [with_tclconfig="$withval"], [with_tclconfig=]) -AC_ARG_WITH(tcl, - [ --with-tcl=path Set location of Tcl package],[ - TCLPACKAGE="$withval"], [TCLPACKAGE="$alllang_default"]) -AC_ARG_WITH(tclincl,[ --with-tclincl=path Set location of Tcl include directory],[ - TCLINCLUDE="-I$withval"], [TCLINCLUDE=]) -AC_ARG_WITH(tcllib,[ --with-tcllib=path Set location of Tcl library directory],[ - TCLLIB="-L$withval"], [TCLLIB=]) - -# First, check for "--without-tcl" or "--with-tcl=no". -if test x"${TCLPACKAGE}" = xno; then -AC_MSG_NOTICE([Disabling Tcl]) -else -AC_MSG_CHECKING([for Tcl configuration]) -# First check to see if --with-tclconfig was specified. -if test x"${with_tclconfig}" != x ; then - if test -f "${with_tclconfig}/tclConfig.sh" ; then - TCLCONFIG=`(cd ${with_tclconfig}; pwd)` - else - AC_MSG_ERROR([${with_tcl} directory does not contain tclConfig.sh]) - fi -fi -# check in a few common install locations -dirs="/usr/lib*/ /usr/lib*/tcl*/ /usr/local/lib*/ /usr/local/lib*/tcl*/" -case $host in -*-*-darwin*) - tcl_framework="/System/Library/Frameworks/Tcl.framework/" - macos_sysroot="$(xcodebuild -version -sdk macosx Path 2>/dev/null)" # For MacOSX10.14 and later - dirs="$macos_sysroot$tcl_framework $tcl_framework $dirs" - ;; -*) - ;; -esac -if test x"${TCLCONFIG}" = x ; then - for d in $dirs ; do - for i in `ls -d -r $d 2>/dev/null` ; do - if test -f $i"tclConfig.sh" ; then - TCLCONFIG=`(cd $i; pwd)` - break - fi - done - done -fi -if test x"${TCLCONFIG}" = x ; then - AC_MSG_RESULT(no) -else - AC_MSG_RESULT(found $TCLCONFIG/tclConfig.sh) - . $TCLCONFIG/tclConfig.sh - if test -z "$TCLINCLUDE"; then - TCLINCLUDE=`echo $TCL_INCLUDE_SPEC` - fi - if test -z "$TCLLIB"; then - TCLLIB=$TCL_LIB_SPEC - fi -fi - -if test -z "$TCLINCLUDE"; then - if test "x$TCLPACKAGE" != xyes; then - TCLINCLUDE="-I$TCLPACKAGE/include" - fi -fi - -if test -z "$TCLLIB"; then - if test "x$TCLPACKAGE" != xyes; then - TCLLIB="-L$TCLPACKAGE/lib -ltcl" - fi -fi - -AC_MSG_CHECKING(for Tcl header files) -if test -z "$TCLINCLUDE"; then -AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[],[TCLINCLUDE=""]) -if test -z "$TCLINCLUDE"; then - dirs="/usr/local/include /usr/include /opt/local/include" - for i in $dirs ; do - if test -r $i/tcl.h; then - AC_MSG_RESULT($i) - TCLINCLUDE="-I$i" - break - fi - done -fi -if test -z "$TCLINCLUDE"; then - AC_MSG_RESULT(not found) -fi -else - AC_MSG_RESULT($TCLINCLUDE) -fi - -AC_MSG_CHECKING(for Tcl library) -if test -z "$TCLLIB"; then -dirs="/usr/local/lib /usr/lib /opt/local/lib /opt/freeware/lib" -for i in $dirs ; do - if test -r $i/libtcl.a; then - AC_MSG_RESULT($i) - TCLLIB="-L$i -ltcl" - break - fi -done -if test -z "$TCLLIB"; then - AC_MSG_RESULT(not found) -fi -else -AC_MSG_RESULT($TCLLIB) -fi - -# Cygwin (Windows) needs the library for dynamic linking -case $host in -*-*-cygwin* | *-*-mingw*) TCLDYNAMICLINKING="$TCLLIB";; -*-*-aix*) TCLDYNAMICLINKING="$TCLLIB";; -*)TCLDYNAMICLINKING="";; -esac - -# AIX needs -ltcl for linking at test time -case $host in -*-*-aix*) TCLLINK="-ltcl";; -*)TCLLINK="";; -esac - -case $host in -*-*-darwin*) - TCLLDSHARED='$(CC) -dynamiclib -undefined suppress -flat_namespace' - TCLCXXSHARED='$(CXX) -dynamiclib -undefined suppress -flat_namespace' - ;; -*) - TCLLDSHARED='$(LDSHARED)' - TCLCXXSHARED='$(CXXSHARED)' - ;; -esac - -fi - -AC_SUBST(TCLINCLUDE) -AC_SUBST(TCLLIB) -AC_SUBST(TCLDYNAMICLINKING) -AC_SUBST(TCLLDSHARED) -AC_SUBST(TCLCXXSHARED) -AC_SUBST(TCLLINK) - #---------------------------------------------------------------- -# Look for Python +# Look for Android #---------------------------------------------------------------- -PYINCLUDE= -PYLIB= -PYLINK= -PYPACKAGE= +AC_ARG_WITH(android, AS_HELP_STRING([--without-android], [Disable Android]) +AS_HELP_STRING([--with-android=path], [Set location of android executable]),[ANDROIDBIN="$withval"], [ANDROIDBIN="$alllang_default"]) +AC_ARG_WITH(adb, [ --with-adb=path Set location of adb executable - Android Debug Bridge],[ADBBIN="$withval"], [ADBBIN=]) +AC_ARG_WITH(ant, [ --with-ant=path Set location of ant executable for Android],[ANTBIN="$withval"], [ANTBIN=]) +AC_ARG_WITH(ndk-build, [ --with-ndk-build=path Set location of Android ndk-build executable],[NDKBUILDBIN="$withval"], [NDKBUILDBIN=]) -AC_ARG_WITH(python, AS_HELP_STRING([--without-python], [Don't probe for Python 2.x]) -AS_HELP_STRING([--with-python=path], [Set location of Python 2.x executable]), [PYBIN="$withval"], [PYBIN="$alllang_default"]) - -# First, check for "--without-python" or "--with-python=no". -if test x"${PYBIN}" = xno; then - AC_MSG_NOTICE([Disabling Python 2.x probe]) +# First, check for "--without-android" or "--with-android=no". +if test x"${ANDROIDBIN}" = xno; then + AC_MSG_NOTICE([Disabling Android]) + ANDROID= else - # First figure out the name of the Python 2.x executable - if test "x$PYBIN" = xyes; then - AC_CHECK_PROGS(PYTHON, [python python2.7]) + if test "x$ANDROIDBIN" = xyes; then + AC_CHECK_PROGS(ANDROID, android) else - PYTHON="$PYBIN" + ANDROID="$ANDROIDBIN" fi - PYVER=0 - if test -n "$PYTHON"; then - AC_MSG_CHECKING([for $PYTHON major version number]) - PYVER=`($PYTHON -c "import sys; sys.stdout.write(sys.version[[0]])") 2>/dev/null` - AC_MSG_RESULT($PYVER) - if test -z "$PYVER"; then - PYVER=0 - else - AC_MSG_CHECKING(for Python 2.x os.name) - PYOSNAME=`($PYTHON -c "import sys, os; sys.stdout.write(os.name)") 2>/dev/null` - AC_MSG_RESULT($PYOSNAME) - AC_MSG_CHECKING(for Python 2.x path separator) - PYSEPARATOR=`($PYTHON -c "import sys, os; sys.stdout.write(os.sep)") 2>/dev/null` - AC_MSG_RESULT($PYSEPARATOR) - fi + if test -z "$ADBBIN"; then + AC_CHECK_PROGS(ADB, adb) + else + ADB="$ADBBIN" fi - if test $PYVER -eq 1 -o $PYVER -eq 2; then - AC_MSG_CHECKING(for Python 2.x prefix) - PYPREFIX=`($PYTHON -c "import sys; sys.stdout.write(sys.prefix)") 2>/dev/null` - AC_MSG_RESULT($PYPREFIX) - AC_MSG_CHECKING(for Python 2.x exec-prefix) - PYEPREFIX=`($PYTHON -c "import sys; sys.stdout.write(sys.exec_prefix)") 2>/dev/null` - AC_MSG_RESULT($PYEPREFIX) - - if test x"$PYOSNAME" = x"nt" -a x"$PYSEPARATOR" = x"\\"; then - # Windows installations are quite different to posix installations (MinGW path separator is a forward slash) - PYPREFIX=`echo "$PYPREFIX" | sed -e 's,\\\\,/,g'` # Forward slashes are easier to use and even work on Windows most of the time - PYTHON_SO=.pyd - - AC_MSG_CHECKING(for Python 2.x header files) - if test -r $PYPREFIX/include/Python.h; then - PYINCLUDE="-I$PYPREFIX/include" - fi - AC_MSG_RESULT($PYINCLUDE) - - AC_MSG_CHECKING(for Python 2.x library directory) - if test -d $PYPREFIX/libs; then - PYLIB=$PYPREFIX/libs - PYLINKFILE=`ls $PYLIB/python*.lib | grep "python[[0-9]][[0-9]]\+\.lib"` - if test -r "$PYLINKFILE"; then - PYLINK=-l`basename $PYLINKFILE | sed -e 's/\.lib$//'` - else - PYLIB= - fi - fi - else - # Note: I could not think of a standard way to get the version string from different versions. - # This trick pulls it out of the file location for a standard library file. - - AC_MSG_CHECKING(for Python 2.x version) - - # Need to do this hack since autoconf replaces __file__ with the name of the configure file - filehack="file__" - PYVERSION=`($PYTHON -c "import sys,string,operator,os.path; sys.stdout.write(operator.getitem(os.path.split(operator.getitem(os.path.split(string.__$filehack),0)),1))") 2>/dev/null` - AC_MSG_RESULT($PYVERSION) - - # Find the directory for libraries this is necessary to deal with - # platforms that can have apps built for multiple archs: e.g. x86_64 - AC_MSG_CHECKING(for Python 2.x lib dir) - PYLIBDIR=`($PYTHON -c "import sys; sys.stdout.write(sys.lib)") 2>/dev/null` - if test -z "$PYLIBDIR"; then - # Fedora patch Python to add sys.lib, for other distros we assume "lib". - PYLIBDIR="lib" - fi - AC_MSG_RESULT($PYLIBDIR) - - # Set the include directory - - AC_MSG_CHECKING(for Python 2.x header files) - if test -r $PYPREFIX/include/$PYVERSION/Python.h; then - PYINCLUDE="-I$PYPREFIX/include/$PYVERSION -I$PYEPREFIX/$PYLIBDIR/$PYVERSION/config" - fi - if test -z "$PYINCLUDE"; then - if test -r $PYPREFIX/include/Py/Python.h; then - PYINCLUDE="-I$PYPREFIX/include/Py -I$PYEPREFIX/$PYLIBDIR/python/lib" - fi - fi - AC_MSG_RESULT($PYINCLUDE) - - # Set the library directory blindly. This probably won't work with older versions - AC_MSG_CHECKING(for Python 2.x library directory) - dirs="$PYVERSION/config $PYVERSION/$PYLIBDIR python/$PYLIBDIR" - for i in $dirs; do - if test -d $PYEPREFIX/$PYLIBDIR/$i; then - PYLIB="$PYEPREFIX/$PYLIBDIR/$i" - break - fi - done - - PYLINK="-l$PYVERSION" - fi - - if test -z "$PYLIB"; then - AC_MSG_RESULT(Not found) - else - AC_MSG_RESULT($PYLIB) - fi - AC_MSG_CHECKING(for Python 2.x library) - if test -z "$PYLINK"; then - AC_MSG_RESULT(Not found) - else - AC_MSG_RESULT($PYLINK) - fi + if test -z "$ANTBIN"; then + AC_CHECK_PROGS(ANT, ant) + else + ANT="$ANTBIN" fi - # Cygwin (Windows) needs the library for dynamic linking + if test -z "$NDKBUILDBIN"; then + AC_CHECK_PROGS(NDKBUILD, ndk-build) + else + NDKBUILD="$NDKBUILDBIN" + fi +fi + +AC_SUBST(ANDROID) +AC_SUBST(ADB) +AC_SUBST(ANT) +AC_SUBST(NDKBUILD) + +#---------------------------------------------------------------- +# Look for C# +#---------------------------------------------------------------- + +AC_ARG_WITH(csharp, AS_HELP_STRING([--without-csharp], [Disable CSharp]), [with_csharp="$withval"], [with_csharp="$alllang_default"]) +AC_ARG_WITH(cil-interpreter, [ --with-cil-interpreter=path Set location of CIL interpreter for CSharp],[CSHARPBIN="$withval"], [CSHARPBIN=]) +AC_ARG_WITH(csharp-compiler, [ --with-csharp-compiler=path Set location of CSharp compiler],[CSHARPCOMPILERBIN="$withval"], [CSHARPCOMPILERBIN=]) + +# First, check for "--without-csharp" or "--with-csharp=no". +if test x"${with_csharp}" = xno; then +AC_MSG_NOTICE([Disabling CSharp]) +CSHARPCOMPILER= +else + +if test -z "$CSHARPCOMPILERBIN" ; then case $host in *-*-cygwin* | *-*-mingw*) - PYTHONDYNAMICLINKING="-L$PYLIB $PYLINK" - DEFS="-DUSE_DL_IMPORT $DEFS" + # prefer unified Mono mcs compiler (not to be confused with the ancient .NET 1 mcs) over older/alternative names. + AC_CHECK_PROGS(CSHARPCOMPILER, csc mcs mono-csc gmcs cscc) + if test -n "$CSHARPCOMPILER" && test "$CSHARPCOMPILER" = "csc" ; then + AC_MSG_CHECKING(whether csc is the Microsoft CSharp compiler) + csc 2>/dev/null | grep "C#" > /dev/null || CSHARPCOMPILER="" + if test -z "$CSHARPCOMPILER" ; then + AC_MSG_RESULT(no) + AC_CHECK_PROGS(CSHARPCOMPILER, mcs mono-csc gmcs cscc) + else + AC_MSG_RESULT(yes) + fi + fi ;; - *-*-aix*) - PYTHONDYNAMICLINKING="-L$PYLIB $PYLINK" - ;; - *)PYTHONDYNAMICLINKING="";; + *)AC_CHECK_PROGS(CSHARPCOMPILER, mono-csc gmcs mcs cscc);; esac +else + CSHARPCOMPILER="$CSHARPCOMPILERBIN" fi -AC_SUBST(PYINCLUDE) -AC_SUBST(PYLIB) -AC_SUBST(PYLINK) -AC_SUBST(PYTHONDYNAMICLINKING) - - -#---------------------------------------------------------------- -# Look for Python 3.x -#---------------------------------------------------------------- - -PY3INCLUDE= -PY3LIB= -PY3LINK= -PY3PACKAGE= - -AC_ARG_WITH(python3, AS_HELP_STRING([--without-python3], [Don't probe for Python 3.x]) -AS_HELP_STRING([--with-python3=path], [Set location of Python 3.x executable]), [PY3BIN="$withval"], [PY3BIN="$alllang_default"]) - -# First, check for "--without-python3" or "--with-python3=no". -if test x"${PY3BIN}" = xno; then - AC_MSG_NOTICE([Disabling Python 3.x probe]) -else - if test -z "$PYVER"; then - PYVER=0 - fi - if test "x$PY3BIN" = xyes; then - if test x"$PYOSNAME" = x"nt" -a x"$PYSEPARATOR" = x"\\" -a $PYVER -ge 3; then - PYTHON3="$PYTHON" - else - for py_ver in 3 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 ""; do - AC_CHECK_PROGS(PYTHON3, [python$py_ver]) - if test -n "$PYTHON3"; then - AC_CHECK_PROGS(PY3CONFIG, [$PYTHON3-config]) - if test -n "$PY3CONFIG"; then - break - fi - fi - done - fi +CSHARPCONVERTPATH="Tools/convertpath -u" +if test -z "$CSHARPBIN" ; then + CSHARPCILINTERPRETER="" + CSHARPCILINTERPRETER_FLAGS="" + if test "cscc" = "$CSHARPCOMPILER" ; then + AC_CHECK_PROGS(CSHARPCILINTERPRETER, ilrun) else - PYTHON3="$PY3BIN" - AC_CHECK_PROGS(PY3CONFIG, [$PYTHON3-config]) - fi - - if test -n "$PYTHON3"; then - AC_MSG_CHECKING([for $PYTHON3 major version number]) - PYVER=`($PYTHON3 -c "import sys; sys.stdout.write(sys.version[[0]])") 2>/dev/null` - AC_MSG_RESULT($PYVER) - if test -z "$PYVER"; then - PYVER=0 - fi - fi - - if test $PYVER -ge 3; then - AC_MSG_CHECKING(for Python 3.x os.name) - PY3OSNAME=`($PYTHON3 -c "import sys, os; sys.stdout.write(os.name)") 2>/dev/null` - AC_MSG_RESULT($PY3OSNAME) - AC_MSG_CHECKING(for Python 3.x path separator) - PYSEPARATOR=`($PYTHON3 -c "import sys, os; sys.stdout.write(os.sep)") 2>/dev/null` - AC_MSG_RESULT($PYSEPARATOR) - - if test x"$PY3OSNAME" = x"nt" -a x"$PYSEPARATOR" = x"\\"; then - # Windows installations are quite different to posix installations - # There is no python-config to use - AC_MSG_CHECKING(for Python 3.x prefix) - PY3PREFIX=`($PYTHON3 -c "import sys; sys.stdout.write(sys.prefix)") 2>/dev/null` - AC_MSG_RESULT($PY3PREFIX) - PY3PREFIX=`echo "$PY3PREFIX" | sed -e 's,\\\\,/,g'` # Forward slashes are easier to use and even work on Windows most of the time - PYTHON_SO=.pyd - - AC_MSG_CHECKING(for Python 3.x header files) - if test -r $PY3PREFIX/include/Python.h; then - PY3INCLUDE="-I$PY3PREFIX/include" - fi - AC_MSG_RESULT($PY3INCLUDE) - - AC_MSG_CHECKING(for Python 3.x library directory) - if test -d $PY3PREFIX/libs; then - PY3LIB=$PY3PREFIX/libs - PY3LINKFILE=`ls $PY3LIB/python*.lib | grep "python[[0-9]][[0-9]]\+\.lib"` - if test -r "$PY3LINKFILE"; then - PY3LINK=-l`basename $PY3LINKFILE | sed -e 's/\.lib$//'` - else - PY3LIB= + if test "mcs" = "$CSHARPCOMPILER"; then + # Check that mcs is the C# compiler and not the Unix mcs utility by examining the output of 'mcs --version' + # The Mono compiler should emit: Mono C# compiler version a.b.c.d + csharp_version_raw=`(mcs --version) 2>/dev/null` + csharp_version_searched=`(mcs --version | sed -e "/C#/b" -e "/Mono/b" -e d) 2>/dev/null` # return string if contains 'Mono' or 'C#' + CSHARPCOMPILER="" + if test -n "$csharp_version_raw" ; then + if test "$csharp_version_raw" = "$csharp_version_searched" ; then + CSHARPCOMPILER="mcs" fi fi - if test -z "$PY3LIB"; then - AC_MSG_RESULT([Not found]) - else - AC_MSG_RESULT($PY3LIB) + if test "mcs" != "$CSHARPCOMPILER" ; then + echo "mcs is not a working Mono C# compiler" fi - AC_MSG_CHECKING([for Python 3.x library]) - if test -z "$PY3LINK"; then - AC_MSG_RESULT(Not found) - else - AC_MSG_RESULT($PY3LINK) - fi - elif test -n "$PY3CONFIG"; then - AC_MSG_CHECKING([for Python 3.x prefix]) - PY3PREFIX=`($PY3CONFIG --prefix) 2>/dev/null` - AC_MSG_RESULT($PY3PREFIX) - AC_MSG_CHECKING(for Python 3.x exec-prefix) - # Piped through xargs to strip trailing whitespace (bug in msys2 + mingw Python) - PY3EPREFIX=`($PY3CONFIG --exec-prefix | xargs) 2>/dev/null` - AC_MSG_RESULT($PY3EPREFIX) - - # Note: I could not think of a standard way to get the version string from different versions. - # This trick pulls it out of the file location for a standard library file. - - AC_MSG_CHECKING([for Python 3.x version]) - - # Need to do this hack since autoconf replaces __file__ with the name of the configure file - filehack="file__" - PY3VERSION=`($PYTHON3 -c "import string,operator,os.path; print(operator.getitem(os.path.split(operator.getitem(os.path.split(string.__$filehack),0)),1))") 2>/dev/null` - AC_MSG_RESULT($PY3VERSION) - - # Find the directory for libraries this is necessary to deal with - # platforms that can have apps built for multiple archs: e.g. x86_64 - AC_MSG_CHECKING([for Python 3.x lib dir]) - PY3LIBDIR=`($PYTHON3 -c "import sys; print(sys.lib)") 2>/dev/null` - if test -z "$PY3LIBDIR"; then - # some dists don't have sys.lib so the best we can do is assume lib - PY3LIBDIR="lib" - fi - AC_MSG_RESULT($PY3LIBDIR) - - # Set the include directory - - AC_MSG_CHECKING([for Python 3.x header files]) - PY3INCLUDE=`($PY3CONFIG --includes) 2>/dev/null` - AC_MSG_RESULT($PY3INCLUDE) - - # Set the library directory blindly. This probably won't work with older versions - AC_MSG_CHECKING([for Python 3.x library directory]) - dirs="$PY3VERSION/config $PY3VERSION/$PY3LIBDIR python/$PY3LIBDIR" - for i in $dirs; do - if test -d $PY3EPREFIX/$PY3LIBDIR/$i; then - PY3LIB="$PY3EPREFIX/$PY3LIBDIR/$i" - break - fi - done - if test -z "$PY3LIB"; then - # Last resort - if test -d $PY3EPREFIX/$PY3LIBDIR; then - PY3LIB="$PY3EPREFIX/$PY3LIBDIR" - fi - fi - if test -z "$PY3LIB"; then - AC_MSG_RESULT([Not found]) - else - AC_MSG_RESULT($PY3LIB) - fi - - PY3LINK="-l$PY3VERSION" - - AC_MSG_CHECKING([for Python 3.x library]) - if test -z "$PY3LINK"; then - AC_MSG_RESULT(Not found) - else - AC_MSG_RESULT($PY3LINK) + fi + if test "mcs" = "$CSHARPCOMPILER" || test "gmcs" = "$CSHARPCOMPILER" || test "mono-csc" = "$CSHARPCOMPILER"; then + AC_CHECK_PROGS(CSHARPCILINTERPRETER, mono) # Mono JIT + CSHARPCILINTERPRETER_FLAGS="--debug" + else + if test "csc" = "$CSHARPCOMPILER"; then + CSHARPCONVERTPATH="Tools/convertpath -w" fi fi fi - - # Cygwin (Windows) needs the library for dynamic linking - case $host in - *-*-cygwin* | *-*-mingw*) - # PYTHON3DYNAMICLINKING ought to be replaced by $PY3CONFIG --ldflags - PYTHON3DYNAMICLINKING="-L$PY3LIB $PY3LINK" - DEFS="-DUSE_DL_IMPORT $DEFS" - ;; - *-*-aix*) - PYTHON3DYNAMICLINKING="-L$PY3LIB $PY3LINK" - ;; - *)PYTHON3DYNAMICLINKING="";; - esac - - AC_SUBST(PY3INCLUDE) - AC_SUBST(PY3LIB) - AC_SUBST(PY3LINK) - AC_SUBST(PYTHON3DYNAMICLINKING) -fi - -if test -n "$PYINCLUDE" || test -n "$PY3INCLUDE" ; then - AC_CHECK_PROGS(PYCODESTYLE, pycodestyle) - if test -n "$PYCODESTYLE"; then - AC_MSG_CHECKING(pycodestyle version) - pycodestyle_version=`$PYCODESTYLE --version 2>/dev/null` - AC_MSG_RESULT($pycodestyle_version) - fi -fi - -#---------------------------------------------------------------- -# Look for Perl5 -#---------------------------------------------------------------- - -PERLBIN= - -AC_ARG_WITH(perl5, AS_HELP_STRING([--without-perl5], [Disable Perl5]) -AS_HELP_STRING([--with-perl5=path], [Set location of Perl5 executable]),[ PERLBIN="$withval"], [PERLBIN="$alllang_default"]) - -# First, check for "--without-perl5" or "--with-perl5=no". -if test x"${PERLBIN}" = xno; then -AC_MSG_NOTICE([Disabling Perl5]) -PERL= else - -# First figure out what the name of Perl5 is - -if test "x$PERLBIN" = xyes; then -AC_CHECK_PROGS(PERL, perl perl5) -else -PERL="$PERLBIN" + CSHARPCILINTERPRETER="$CSHARPBIN" fi - -# This could probably be simplified as for all platforms and all versions of Perl the following apparently should be run to get the compilation options: -# perl -MExtUtils::Embed -e ccopts -AC_MSG_CHECKING(for Perl5 header files) -if test -n "$PERL"; then - PERL5DIR=`($PERL -MConfig -le 'print $Config{archlibexp}') 2>/dev/null` - if test -n "$PERL5DIR" ; then - dirs="$PERL5DIR $PERL5DIR/CORE" - PERL5EXT=none - for i in $dirs; do - if test -r $i/perl.h; then - AC_MSG_RESULT($i) - PERL5EXT="$i" - break - fi - done - if test "$PERL5EXT" = none; then - PERL5EXT="$PERL5DIR/CORE" - AC_MSG_RESULT(could not locate perl.h...using $PERL5EXT) - fi - - AC_MSG_CHECKING(for Perl5 library) - PERL5LIB=`($PERL -e 'use Config; $_=$Config{libperl}; s/^lib//; s/$Config{_a}$//; s/\.$Config{so}.*//; print $_, "\n"') 2>/dev/null` - if test -z "$PERL5LIB" ; then - AC_MSG_RESULT(not found) - else - AC_MSG_RESULT($PERL5LIB) - fi - AC_MSG_CHECKING(for Perl5 ccflags) - PERL5CCFLAGS=`($PERL -e 'use Config; print $Config{ccflags}, "\n"' | sed "s/-Wdeclaration-after-statement//") 2>/dev/null` - if test -z "$PERL5CCFLAGS" ; then - AC_MSG_RESULT(not found) - else - AC_MSG_RESULT($PERL5CCFLAGS) - fi - AC_MSG_CHECKING(for Perl5 ccdlflags) - PERL5CCDLFLAGS=`($PERL -e 'use Config; print $Config{ccdlflags}, "\n"') 2>/dev/null` - if test -z "$PERL5CCDLFLAGS" ; then - AC_MSG_RESULT(not found) - else - AC_MSG_RESULT($PERL5CCDLFLAGS) - fi - AC_MSG_CHECKING(for Perl5 cccdlflags) - PERL5CCCDLFLAGS=`($PERL -e 'use Config; print $Config{cccdlflags}, "\n"') 2>/dev/null` - if test -z "$PERL5CCCDLFLAGS" ; then - AC_MSG_RESULT(not found) - else - AC_MSG_RESULT($PERL5CCCDLFLAGS) - fi - AC_MSG_CHECKING(for Perl5 ldflags) - PERL5LDFLAGS=`($PERL -e 'use Config; print $Config{ldflags}, "\n"') 2>/dev/null` - if test -z "$PERL5LDFLAGS" ; then - AC_MSG_RESULT(not found) - else - AC_MSG_RESULT($PERL5LDFLAGS) - fi - AC_MSG_CHECKING(for Perl5 Test::More module) # For test-suite - PERL5TESTMORE=`($PERL -e 'use Test::More; print "good";') 2>/dev/null` - if test -z "$PERL5TESTMORE" ; then - AC_MSG_RESULT(not found) - else - AC_MSG_RESULT(found) - fi - else - AC_MSG_RESULT(unable to determine perl5 configuration) - PERL5EXT=$PERL5DIR - fi -else - AC_MSG_RESULT(could not figure out how to run perl5) -fi - -# Cygwin (Windows) needs the library for dynamic linking +# Cygwin requires the Windows standard (Pascal) calling convention as it is a Windows executable and not a Cygwin built executable case $host in -*-*-cygwin* | *-*-mingw*) PERL5DYNAMICLINKING="-L$PERL5EXT -l$PERL5LIB";; -*)PERL5DYNAMICLINKING="";; +*-*-cygwin* | *-*-mingw*) + if test "$GCC" = yes; then + CSHARPDYNAMICLINKING="$GCC_MNO_CYGWIN -mthreads -Wl,--add-stdcall-alias" + CSHARPCFLAGS="$GCC_MNO_CYGWIN -mthreads" + else + CSHARPDYNAMICLINKING="" + CSHARPCFLAGS="" + fi ;; +*) + CSHARPDYNAMICLINKING="" + CSHARPCFLAGS="" + ;; +esac + +# CSharp on Windows platforms including Cygwin doesn't use libname.dll, rather name.dll when loading dlls +case $host in +*-*-cygwin* | *-*-mingw*) CSHARPLIBRARYPREFIX="";; +*)CSHARPLIBRARYPREFIX="lib";; +esac + +# C#/Mono on Mac OS X tweaks +case $host in +*-*-darwin*) + CSHARPSO=".so" + ;; +*) + CSHARPSO=$SO + ;; esac fi -AC_SUBST(PERL) -AC_SUBST(PERL5EXT) -AC_SUBST(PERL5DYNAMICLINKING) -AC_SUBST(PERL5LIB) -AC_SUBST(PERL5CCFLAGS) -AC_SUBST(PERL5CCDLFLAGS) -AC_SUBST(PERL5CCCDLFLAGS) -AC_SUBST(PERL5LDFLAGS) +AC_SUBST(CSHARPCILINTERPRETER_FLAGS) +AC_SUBST(CSHARPCILINTERPRETER) +AC_SUBST(CSHARPCONVERTPATH) +AC_SUBST(CSHARPCOMPILER) +AC_SUBST(CSHARPDYNAMICLINKING) +AC_SUBST(CSHARPLIBRARYPREFIX) +AC_SUBST(CSHARPCFLAGS) +AC_SUBST(CSHARPSO) #---------------------------------------------------------------- -# Look for Octave +# Look for D #---------------------------------------------------------------- -OCTAVEBIN= -OCTAVE_SO=.oct +AC_ARG_WITH(d, AS_HELP_STRING([--without-d], [Disable D]), [with_d="$withval"], [with_d="$alllang_default"]) +AC_ARG_WITH(d1-compiler, [ --with-d1-compiler=path Set location of D1/Tango compiler (DMD compatible)],[D1COMPILERBIN="$withval"], [D1COMPILERBIN=]) +AC_ARG_WITH(d2-compiler, [ --with-d2-compiler=path Set location of D2 compiler (DMD compatible)],[D2COMPILERBIN="$withval"], [D2COMPILERBIN=]) -AC_ARG_WITH(octave, AS_HELP_STRING([--without-octave], [Disable Octave]) -AS_HELP_STRING([--with-octave=path], [Set location of Octave executable]),[OCTAVEBIN="$withval"], [OCTAVEBIN="$alllang_default"]) - -# Check for "--without-octave" or "--with-octave=no". -if test x"${OCTAVEBIN}" = xno; then - AC_MSG_NOTICE([Disabling Octave]) - OCTAVE= - -# Check for Octave; prefer command-line program "octave-cli" to (in newer versions) GUI program "octave" -elif test "x$OCTAVEBIN" = xyes; then - AC_PATH_PROG(OCTAVE, [octave-cli octave]) +# First, check for "--without-d" or "--with-d=no". +if test x"${with_d}" = xno; then + AC_MSG_NOTICE([Disabling D]) + D1COMPILER= + D2COMPILER= else - OCTAVE="$OCTAVEBIN" -fi + old_ac_ext=$ac_ext + ac_ext=d -# Check if Octave works -if test -n "$OCTAVE"; then - AC_MSG_CHECKING([if ${OCTAVE} works]) - AS_IF([test "x`${OCTAVE} --version 2>/dev/null | sed -n -e '1p' | sed -n -e '/Octave, version/p'`" != x],[ - AC_MSG_RESULT([yes]) - ],[ - AC_MSG_RESULT([no]) - OCTAVE= - ]) -fi + if test -z "$D1COMPILERBIN" ; then + AC_CHECK_PROGS(D1COMPILER, dmd ldmd gdmd) -# Check for required Octave helper program "mkoctfile" -if test -n "$OCTAVE"; then - AC_MSG_CHECKING([for mkoctfile]) - version_suffix=["`echo $OCTAVE | sed -e 's|.*\(-[0-9][0-9.]*\)$|\1|'`"] - case $version_suffix in - -*) ;; - *) version_suffix="" ;; - esac - octave_directory=`dirname $OCTAVE` - if test "$octave_directory" = "." ; then - mkoctfile="mkoctfile${version_suffix}" - else - mkoctfile="${octave_directory}/mkoctfile${version_suffix}" - fi - AC_MSG_RESULT([${mkoctfile}]) - AC_MSG_CHECKING([if ${mkoctfile} works]) - mkoctfile="env - PATH=$PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH ${mkoctfile}" - AS_IF([test "x`${mkoctfile} --version 2>/dev/null | sed -n -e '1p' | sed -n -e '/mkoctfile, version/p'`" != x],[ - AC_MSG_RESULT([yes]) - ],[ - AC_MSG_RESULT([no]) - OCTAVE= - ]) -fi - -# Check for Octave preprocessor/compiler/linker flags -if test -n "$OCTAVE"; then - - AC_MSG_CHECKING([for Octave preprocessor flags]) - OCTAVE_CPPFLAGS= - for var in CPPFLAGS INCFLAGS ALL_CXXFLAGS; do - for flag in `${mkoctfile} -p ${var}`; do - case ${flag} in - -D*|-I*) OCTAVE_CPPFLAGS="${OCTAVE_CPPFLAGS} ${flag}";; - *) ;; - esac - done - done - AC_MSG_RESULT([$OCTAVE_CPPFLAGS]) - - AC_MSG_CHECKING([for Octave compiler flags]) - OCTAVE_CXXFLAGS= - for var in CXX ALL_CXXFLAGS; do - for flag in `${mkoctfile} -p ${var}`; do - case ${flag} in - -std=*|-g*|-W*) OCTAVE_CXXFLAGS="${OCTAVE_CXXFLAGS} ${flag}";; - *) ;; - esac - done - done - save_CXXFLAGS="${CXXFLAGS}" - CXXFLAGS="-Werror -O0" - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([],[]) - ],[ - OCTAVE_CXXFLAGS="${OCTAVE_CXXFLAGS} -O0" - ]) - CXXFLAGS="${save_CXXFLAGS}" - AC_MSG_RESULT([$OCTAVE_CXXFLAGS]) - - AC_MSG_CHECKING([for Octave linker flags]) - OCTAVE_LDFLAGS= - for var in OCTLIBDIR; do - OCTAVE_LDFLAGS="${OCTAVE_LDFLAGS} "-L`${mkoctfile} -p ${var}` - done - for var in RDYNAMIC_FLAG RLD_FLAG OCTAVE_LIBS LIBS; do - OCTAVE_LDFLAGS="${OCTAVE_LDFLAGS} "`${mkoctfile} -p ${var}` - done - AC_MSG_RESULT([$OCTAVE_LDFLAGS]) - -fi - -# Check for Octave options -if test -n "$OCTAVE"; then - for octave_opt in --no-window-system --silent --norc --no-history; do - AC_MSG_CHECKING([if Octave option '${octave_opt}' is supported]) - octave_out=`${OCTAVE} ${octave_opt} /dev/null 2>&1 | sed -n '1p' | sed -n '/unrecognized/p'` - AS_IF([test "x${octave_out}" = x],[ - AC_MSG_RESULT([yes]) - OCTAVE="${OCTAVE} ${octave_opt}" - ],[ - AC_MSG_RESULT([no]) - ]) - done -fi - -AC_SUBST(OCTAVE) -AC_SUBST(OCTAVE_SO) -AC_SUBST(OCTAVE_CPPFLAGS) -AC_SUBST(OCTAVE_CXXFLAGS) -AC_SUBST(OCTAVE_LDFLAGS) - -#---------------------------------------------------------------- -# Look for Scilab -#---------------------------------------------------------------- - -AC_ARG_WITH(scilab, AS_HELP_STRING([--without-scilab], [Disable Scilab]) -AS_HELP_STRING([--with-scilab=path], [Set location of Scilab executable]),[SCILABBIN="$withval"], [SCILABBIN="$alllang_default"]) -AC_ARG_WITH(scilab-inc, [ --with-scilab-inc=path Set location of Scilab include directory], [SCILABINCDIR="$withval"], [SCILABINCDIR=""]) - -# First, check for "--without-scilab" or "--with-scilab=no". -if test x"${SCILABBIN}" = xno; then - AC_MSG_NOTICE([Disabling Scilab]) - SCILAB= -else - # Check for Scilab executable - if test "x$SCILABBIN" = xyes; then - AC_PATH_PROG(SCILAB, scilab) - else - AC_MSG_CHECKING(for scilab) - if test -f "$SCILABBIN"; then - AC_MSG_RESULT($SCILABBIN) - SCILAB="$SCILABBIN" - else - AC_MSG_RESULT(not found) + if test -n "$D1COMPILER" ; then + AC_MSG_CHECKING(whether the D1/Tango compiler works) + cat > conftest.$ac_ext <<_ACEOF +import tango.io.Stdout; +void main() { +} +_ACEOF + rm -f conftest.$ac_objext + AS_IF( + [$D1COMPILER conftest.$ac_ext 2>&AS_MESSAGE_LOG_FD && test ! -s conftest.err && test -s conftest.$ac_objext], + [AC_MSG_RESULT([yes])], + [_AC_MSG_LOG_CONFTEST AC_MSG_RESULT([no]) + D1COMPILER=] + ) + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi + else + D1COMPILER="$D1COMPILERBIN" fi - if test -n "$SCILAB"; then - # Check for Scilab version (needs api_scilab so needs version 5.3.3 or higher) - SCILAB_VERSION=`$SCILAB -nwni -version | head -1 | sed -e 's|Scilab version \"\(.*\)\"|\1|g'` + if test -z "$D2COMPILERBIN" ; then + AC_CHECK_PROGS(D2COMPILER, dmd gdmd ldmd2 ldc2) - AC_MSG_CHECKING(Scilab version is 5.3.3 or higher) - SCILAB_MAJOR_VERSION=`echo $SCILAB_VERSION | cut -d. -f1` - SCILAB_MINOR_VERSION=`echo $SCILAB_VERSION | cut -d. -f2` - SCILAB_MAINTENANCE_VERSION=`echo $SCILAB_VERSION | cut -d. -f3` - SCILAB_VERSION_NO_DOTS="$SCILAB_MAJOR_VERSION$SCILAB_MINOR_VERSION$SCILAB_MAINTENANCE_VERSION" - - if test -n "$SCILAB_VERSION_NO_DOTS" && test "$SCILAB_VERSION_NO_DOTS" -ge 533; then - AC_MSG_RESULT(yes - $SCILAB_VERSION) - else - AC_MSG_RESULT(no - $SCILAB_VERSION) - SCILAB= + if test -n "$D2COMPILER" ; then + AC_MSG_CHECKING(whether the D2 compiler works) + cat > conftest.$ac_ext <<_ACEOF +import std.algorithm; +void main() { +} +_ACEOF + rm -f conftest.$ac_objext + AS_IF( + [$D2COMPILER conftest.$ac_ext 2>&AS_MESSAGE_LOG_FD && test ! -s conftest.err && test -s conftest.$ac_objext], + [AC_MSG_RESULT([yes])], + [_AC_MSG_LOG_CONFTEST AC_MSG_RESULT([no]) + D2COMPILER=] + ) + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi + else + D2COMPILER="$D2COMPILERBIN" + fi - if test -n "$SCILAB"; then - # Set Scilab startup options depending on version - AC_MSG_CHECKING(for Scilab startup options) - SCILABOPT="-nwni -nb" - if test $SCILAB_VERSION_NO_DOTS -ge 540; then - SCILABOPT+=" -noatomsautoload" - fi - if test $SCILAB_VERSION_NO_DOTS -ge 600; then - SCILABOPT+=" -quit" - fi - AC_MSG_RESULT($SCILABOPT) + ac_ext=$old_ac_ext +fi - # Check for Scilab header files - AC_MSG_CHECKING(for Scilab header files) - headers="`AS_DIRNAME(["$SCILAB"])`/../include" - if test "$SCILABINCDIR" != ""; then - dirs="$SCILABINCDIR" - elif test -d "$SCI"; then - dirs="$SCI/include $SCI/../../include" - elif test -d "$headers"; then - dirs="$headers" - elif test -n "$PKG_CONFIG "; then - dirs=`$PKG_CONFIG scilab --cflags-only-I | sed -e 's/-I//g'` +if test -n "$D1COMPILER"; then + DDEFAULTVERSION=1 +elif test -n "$D2COMPILER"; then + DDEFAULTVERSION=2 +fi + +# Do not prefix library file names with "lib" on Windows. +case $host in +*-*-cygwin* | *-*-mingw*) DLIBPREFIX="";; +*)DLIBPREFIX="lib";; +esac + +AC_SUBST(D1COMPILER) +AC_SUBST(D2COMPILER) +AC_SUBST(DDEFAULTVERSION) +AC_SUBST(DLIBPREFIX) + +#---------------------------------------------------------------- +# Look for Go compilers +#---------------------------------------------------------------- + +AC_ARG_WITH(go, AS_HELP_STRING([--without-go], [Disable Go]) +AS_HELP_STRING([--with-go=path], [Set location of Go compiler]),[GOBIN="$withval"], [GOBIN="$alllang_default"]) + +if test x"${GOBIN}" = xno; then + AC_MSG_NOTICE([Disabling Go]) + GO= + GOGCC=false + GCCGO= + GOOPT= + GCCGOOPT= + GOVERSIONOPTION= +else + + if test "x$GOBIN" = xyes; then + AC_CHECK_PROGS(GO, go) + else + GO="$GOBIN" + fi + + GOGCC=false + GCCGO= + GOOPT= + GCCGOOPT= + GOVERSIONOPTION= + + if test -n "$GO" ; then + GOVERSIONOPTION=version + go_version=$($GO $GOVERSIONOPTION | sed -e 's/go version //') + AC_MSG_CHECKING([whether go version is too old]) + case $go_version in + go1.[012]*) + AC_MSG_RESULT([yes - minimum version is 1.3]) + GO= + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac + fi + + AC_CHECK_PROGS(GCCGO, gccgo) + + if test -n "$GCCGO" ; then + if $GCCGO --help 2>/dev/null | grep gccgo >/dev/null 2>&1 ; then + AC_MSG_CHECKING([whether gccgo version is too old]) + go_version=[`$GO $GOVERSIONOPTION | sed -n '1p' | sed -e 's/^.* \([0-9.]*\) *$/\1/' -e 's/[.]//g'`] + if test "x$go_version" = x; then + AC_MSG_RESULT([could not determine gccgo version]) + GCCGO= + elif test "$go_version" -lt 470; then + AC_MSG_RESULT([yes - minimum version is 4.7.0]) + GCCGO= else - dirs="/usr/include" - fi - for i in $dirs; do - if test -r $i/api_scilab.h; then - AC_MSG_RESULT($i) - SCILABINCLUDE="-I$i" - break + AC_MSG_RESULT([no]) + if test "$go_version" -lt 480; then + GCCGOOPT="-intgosize 32" fi - if test -r $i/scilab/api_scilab.h; then - AC_MSG_RESULT($i/scilab) - SCILABINCLUDE="-I$i/scilab" - break - fi - done - if test "$SCILABINCLUDE" = "" ; then - AC_MSG_RESULT(not found) - SCILAB= fi fi fi fi -AC_SUBST(SCILAB) -AC_SUBST(SCILABINCLUDE) -AC_SUBST(SCILABOPT) -AC_SUBST(SCILAB_VERSION) +AC_SUBST(GOGCC) +AC_SUBST(GCCGO) +AC_SUBST(GO) +AC_SUBST(GOC) +AC_SUBST(GO1) +AC_SUBST(GO12) +AC_SUBST(GO13) +AC_SUBST(GO15) +AC_SUBST(GOOPT) +AC_SUBST(GCCGOOPT) +AC_SUBST(GOVERSIONOPTION) +#---------------------------------------------------------------- +# Look for Guile +#---------------------------------------------------------------- + +GUILE= +GUILE_CFLAGS= +GUILE_LIBS= + +AC_ARG_WITH(guile-config, AS_HELP_STRING([--without-guile], [Disable Guile]) +AS_HELP_STRING([--with-guile-config=path], [Set location of guile-config]),[ GUILE_CONFIG="$withval"], [GUILE_CONFIG=]) +AC_ARG_WITH(guile,[ --with-guile=path Set location of Guile executable],[ + GUILE="$withval"], [GUILE="$alllang_default"]) +AC_ARG_WITH(guile-cflags,[ --with-guile-cflags=cflags Set cflags required to compile against Guile],[ + GUILE_CFLAGS="$withval"]) +AC_ARG_WITH(guile-libs,[ --with-guile-libs=ldflags Set ldflags needed to link with Guile],[ + GUILE_LIBS="$withval"]) + +# First, check for "--without-guile" or "--with-guile=no". +if test x"${GUILE}" = xno; then + AC_MSG_NOTICE([Disabling Guile]) +else + if test -z "$GUILE_CONFIG" ; then + AC_PATH_PROG(GUILE_CONFIG, guile-config) + fi + if test -n "$GUILE_CONFIG" ; then + if test x"$GUILE" = xyes; then + AC_MSG_CHECKING([for guile executable]) + # Try extracting it via guile-config first. If it's defined there it's the most reliable result + GUILE="`$GUILE_CONFIG info guile 2>/dev/null`" + if test -n "$GUILE"; then + AC_MSG_RESULT([$GUILE]) + else + AC_MSG_RESULT([not found via guile-config - constructing path]) + AC_MSG_CHECKING([for guile bindir]) + guile_bindir="`$GUILE_CONFIG info bindir`" + AC_MSG_RESULT([$guile_bindir]) + GUILE="$guile_bindir/guile" + fi + if ! test -f "$GUILE" ; then + GUILE= + AC_PATH_PROG(GUILE, guile) + fi + if test -z "$GUILE" ; then + AC_MSG_WARN([no suitable guile executable found. Disabling Guile]) + fi + fi + + if test -n "$GUILE" ; then + AC_MSG_CHECKING([for guile version]) + guile_version=`$GUILE -c '(display (effective-version))'` + AC_MSG_RESULT([$guile_version]) + AC_MSG_CHECKING([for guile version >= 1.8]) + guile_good_version=`$GUILE -c '(if (>= (string->number (effective-version)) 1.8) (display "yes") (display "no"))'` + AC_MSG_RESULT([$guile_good_version]) + if test x"$guile_good_version" != xyes ; then + AC_MSG_WARN([at least guile version 1.8 is required. Disabling Guile]) + GUILE= + fi + fi + + if test -n "$GUILE" ; then + # Test if guile-config and guile versions match. They should. + gc_version="`$GUILE_CONFIG --version 2>&1 | sed '1 s/.* //;q'`" + g_version="`$GUILE --version | sed '1 s/.* //;q'`" + if test "$gc_version" != "$g_version"; then + AC_MSG_WARN([different versions reported by $GUILE_CONFIG ($gc_version) and $GUILE ($g_version). Disabling Guile]) + GUILE= + fi + fi + + if test -n "$GUILE" ; then + if test -z "$GUILE_CFLAGS" ; then + AC_MSG_CHECKING([for guile compile flags]) + GUILE_CFLAGS="`$GUILE_CONFIG compile`" # Note that this can sometimes be empty + AC_MSG_RESULT([$GUILE_CFLAGS]) + fi + + if test -z "$GUILE_LIBS" ; then + AC_MSG_CHECKING([for guile link flags]) + GUILE_LIBS="`$GUILE_CONFIG link`" + AC_MSG_RESULT([$GUILE_LIBS]) + fi + fi + fi +fi + +AC_SUBST(GUILE) +AC_SUBST(GUILE_CFLAGS) +AC_SUBST(GUILE_LIBS) #---------------------------------------------------------------- # Look for java @@ -1785,527 +1382,6 @@ AC_SUBST(JSV8ENABLED) AC_SUBST(NODEJS) AC_SUBST(NODEGYP) -#---------------------------------------------------------------- -# Look for Android -#---------------------------------------------------------------- - -AC_ARG_WITH(android, AS_HELP_STRING([--without-android], [Disable Android]) -AS_HELP_STRING([--with-android=path], [Set location of android executable]),[ANDROIDBIN="$withval"], [ANDROIDBIN="$alllang_default"]) -AC_ARG_WITH(adb, [ --with-adb=path Set location of adb executable - Android Debug Bridge],[ADBBIN="$withval"], [ADBBIN=]) -AC_ARG_WITH(ant, [ --with-ant=path Set location of ant executable for Android],[ANTBIN="$withval"], [ANTBIN=]) -AC_ARG_WITH(ndk-build, [ --with-ndk-build=path Set location of Android ndk-build executable],[NDKBUILDBIN="$withval"], [NDKBUILDBIN=]) - -# First, check for "--without-android" or "--with-android=no". -if test x"${ANDROIDBIN}" = xno; then - AC_MSG_NOTICE([Disabling Android]) - ANDROID= -else - if test "x$ANDROIDBIN" = xyes; then - AC_CHECK_PROGS(ANDROID, android) - else - ANDROID="$ANDROIDBIN" - fi - - if test -z "$ADBBIN"; then - AC_CHECK_PROGS(ADB, adb) - else - ADB="$ADBBIN" - fi - - if test -z "$ANTBIN"; then - AC_CHECK_PROGS(ANT, ant) - else - ANT="$ANTBIN" - fi - - if test -z "$NDKBUILDBIN"; then - AC_CHECK_PROGS(NDKBUILD, ndk-build) - else - NDKBUILD="$NDKBUILDBIN" - fi -fi - -AC_SUBST(ANDROID) -AC_SUBST(ADB) -AC_SUBST(ANT) -AC_SUBST(NDKBUILD) - -#---------------------------------------------------------------- -# Look for Guile -#---------------------------------------------------------------- - -GUILE= -GUILE_CFLAGS= -GUILE_LIBS= - -AC_ARG_WITH(guile-config, AS_HELP_STRING([--without-guile], [Disable Guile]) -AS_HELP_STRING([--with-guile-config=path], [Set location of guile-config]),[ GUILE_CONFIG="$withval"], [GUILE_CONFIG=]) -AC_ARG_WITH(guile,[ --with-guile=path Set location of Guile executable],[ - GUILE="$withval"], [GUILE="$alllang_default"]) -AC_ARG_WITH(guile-cflags,[ --with-guile-cflags=cflags Set cflags required to compile against Guile],[ - GUILE_CFLAGS="$withval"]) -AC_ARG_WITH(guile-libs,[ --with-guile-libs=ldflags Set ldflags needed to link with Guile],[ - GUILE_LIBS="$withval"]) - -# First, check for "--without-guile" or "--with-guile=no". -if test x"${GUILE}" = xno; then - AC_MSG_NOTICE([Disabling Guile]) -else - if test -z "$GUILE_CONFIG" ; then - AC_PATH_PROG(GUILE_CONFIG, guile-config) - fi - if test -n "$GUILE_CONFIG" ; then - if test x"$GUILE" = xyes; then - AC_MSG_CHECKING([for guile executable]) - # Try extracting it via guile-config first. If it's defined there it's the most reliable result - GUILE="`$GUILE_CONFIG info guile 2>/dev/null`" - if test -n "$GUILE"; then - AC_MSG_RESULT([$GUILE]) - else - AC_MSG_RESULT([not found via guile-config - constructing path]) - AC_MSG_CHECKING([for guile bindir]) - guile_bindir="`$GUILE_CONFIG info bindir`" - AC_MSG_RESULT([$guile_bindir]) - GUILE="$guile_bindir/guile" - fi - if ! test -f "$GUILE" ; then - GUILE= - AC_PATH_PROG(GUILE, guile) - fi - if test -z "$GUILE" ; then - AC_MSG_WARN([no suitable guile executable found. Disabling Guile]) - fi - fi - - if test -n "$GUILE" ; then - AC_MSG_CHECKING([for guile version]) - guile_version=`$GUILE -c '(display (effective-version))'` - AC_MSG_RESULT([$guile_version]) - AC_MSG_CHECKING([for guile version >= 1.8]) - guile_good_version=`$GUILE -c '(if (>= (string->number (effective-version)) 1.8) (display "yes") (display "no"))'` - AC_MSG_RESULT([$guile_good_version]) - if test x"$guile_good_version" != xyes ; then - AC_MSG_WARN([at least guile version 1.8 is required. Disabling Guile]) - GUILE= - fi - fi - - if test -n "$GUILE" ; then - # Test if guile-config and guile versions match. They should. - gc_version="`$GUILE_CONFIG --version 2>&1 | sed '1 s/.* //;q'`" - g_version="`$GUILE --version | sed '1 s/.* //;q'`" - if test "$gc_version" != "$g_version"; then - AC_MSG_WARN([different versions reported by $GUILE_CONFIG ($gc_version) and $GUILE ($g_version). Disabling Guile]) - GUILE= - fi - fi - - if test -n "$GUILE" ; then - if test -z "$GUILE_CFLAGS" ; then - AC_MSG_CHECKING([for guile compile flags]) - GUILE_CFLAGS="`$GUILE_CONFIG compile`" # Note that this can sometimes be empty - AC_MSG_RESULT([$GUILE_CFLAGS]) - fi - - if test -z "$GUILE_LIBS" ; then - AC_MSG_CHECKING([for guile link flags]) - GUILE_LIBS="`$GUILE_CONFIG link`" - AC_MSG_RESULT([$GUILE_LIBS]) - fi - fi - fi -fi - -AC_SUBST(GUILE) -AC_SUBST(GUILE_CFLAGS) -AC_SUBST(GUILE_LIBS) - -#---------------------------------------------------------------- -# Look for MzScheme -#---------------------------------------------------------------- - -AC_ARG_WITH(mzscheme, AS_HELP_STRING([--without-mzscheme], [Disable MzScheme]) -AS_HELP_STRING([--with-mzscheme=path], [Set location of MzScheme executable]),[ MZSCHEMEBIN="$withval"], [MZSCHEMEBIN="$alllang_default"]) -AC_ARG_WITH(mzc, AS_HELP_STRING([--with-mzc=path], [Set location of MzScheme's mzc]), [ MZCBIN="$withval"], [MZCBIN=]) - -# First, check for "--without-mzscheme" or "--with-mzscheme=no". -if test x"${MZSCHEMEBIN}" = xno; then - AC_MSG_NOTICE([Disabling MzScheme]) - MZC= -else - if test "x$MZSCHEMEBIN" = xyes; then - AC_PATH_PROG(MZSCHEME, mzscheme) - else - MZSCHEME="$MZSCHEMEBIN" - fi - - if test -z "$MZCBIN"; then - AC_PATH_PROG(MZC, mzc) - fi - - if test -n "$MZSCHEME"; then - AC_MSG_CHECKING(for MzScheme dynext object) - MZDYNOBJ=`$MZSCHEME --eval '(begin (require dynext/link) (with-handlers (((lambda args #t) (lambda args #f))) (for-each (lambda (x) (printf "~a" x)) (expand-for-link-variant (current-standard-link-libraries)))))' 2>/dev/null` - if test -f "$MZDYNOBJ"; then - : - else - # older versions (3.72 approx and earlier) - MZDYNOBJ=`$MZSCHEME --mute-banner --version --eval '(begin (require (lib "link.ss" "dynext")) (with-handlers (((lambda args #t) (lambda args #f))) (for-each (lambda (x) (display x) (display " ")) ((current-make-standard-link-libraries)))) (with-handlers (((lambda args #t) (lambda args #f))) (for-each (lambda (x) (display x)) (expand-for-link-variant (current-standard-link-libraries)))))' 2>/dev/null` - fi - if test -f "$MZDYNOBJ"; then - AC_MSG_RESULT($MZDYNOBJ) - else - AC_MSG_RESULT(not found) - MZDYNOBJ="" - fi - fi -fi -AC_SUBST(MZDYNOBJ) - -#---------------------------------------------------------------- -# Look for Ruby -#---------------------------------------------------------------- - -RUBYBIN= - -AC_ARG_WITH(ruby, AS_HELP_STRING([--without-ruby], [Disable Ruby]) -AS_HELP_STRING([--with-ruby=path], [Set location of Ruby executable]),[ RUBYBIN="$withval"], [RUBYBIN="$alllang_default"]) - -# First, check for "--without-ruby" or "--with-ruby=no". -RUBYSO=$SO -if test x"${RUBYBIN}" = xno; then -AC_MSG_NOTICE([Disabling Ruby]) -RUBY= -else - -# First figure out what the name of Ruby is - -if test "x$RUBYBIN" = xyes; then - AC_CHECK_PROGS(RUBY, ruby) -else - RUBY="$RUBYBIN" -fi - -AC_MSG_CHECKING(for Ruby header files) -if test -n "$RUBY"; then - # Try Ruby1.9+ first - RUBYDIR=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["rubyhdrdir"]] || $rubyhdrdir') 2>/dev/null` - RUBYARCHHDRDIR=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["rubyarchhdrdir"]] || $rubyarchhdrdir') 2>/dev/null` - if test x"$RUBYDIR" = x"" || test x"$RUBYDIR" = x"nil"; then - RUBYDIR=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["archdir"]] || $archdir') 2>/dev/null` - else - RUBYARCH=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["arch"]] || $arch') 2>/dev/null` - fi - if test x"$RUBYDIR" != x""; then - dirs="$RUBYDIR" - RUBYINCLUDE= - for i in $dirs; do - if test -r $i/ruby.h; then - if test x"$RUBYARCH" = x""; then - RUBYINCLUDE="-I$i" - elif test -n "$RUBYARCHHDRDIR"; then - RUBYINCLUDE="-I$i -I$RUBYARCHHDRDIR" - else - RUBYINCLUDE="-I$i -I$i/$RUBYARCH" - fi - AC_MSG_RESULT($RUBYINCLUDE) - break - fi - done - if test x"$RUBYINCLUDE" = x""; then - AC_MSG_RESULT(could not locate ruby.h) - fi - - # Find library and path for linking. - AC_MSG_CHECKING(for Ruby library) - RUBYLIB="" - rb_archlibdir=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["archlibdir"]]') 2>/dev/null` - rb_libdir=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["libdir"]]') 2>/dev/null` - rb_bindir=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["bindir"]]') 2>/dev/null` - dirs="$dirs $rb_archlibdir $rb_libdir $rb_bindir" - - rb_libruby=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["LIBRUBY_A"]]') 2>/dev/null` - RUBYLINK=`($RUBY -rrbconfig -e ' - c = RbConfig::CONFIG - if c.has_key? "LIBRUBYARG_STATIC" # 1.8.x - if c[["LIBRUBY"]] == c[["LIBRUBY_A"]] - link = c[["LIBRUBYARG_STATIC"]] - else - link = c[["LIBRUBYARG_SHARED"]] - end - else # 1.6.x - link = "-l" + c[["RUBY_INSTALL_NAME"]] - end - - # Get the target Ruby was built for - target = c[["target"]] - - if target == "i386-pc-mswin32" - # Need to change msvcrt-ruby*.lib to -lmsvcrt-ruby* - ext = File.extname(link) - # Get index that counts backwards from end of string - index = -1 - ext.size - # Strip off the extension - link = link.slice(0..index) - puts "-l#{link}" - else - puts link - end') 2>/dev/null` - - if test "$rb_libruby" != ""; then - for i in $dirs; do - if (test -r $i/$rb_libruby;) then - RUBYLIB="$i" - break - fi - done - fi - if test "$RUBYLIB" = ""; then - RUBYLIB="$RUBYDIR" - AC_MSG_RESULT(not found... using $RUBYDIR) - else - AC_MSG_RESULT($RUBYLINK in $RUBYLIB) - fi - else - AC_MSG_RESULT(unable to determine ruby configuration) - fi - - case $host in - *-*-mingw*) ;; # do nothing, the default windows libraries are already included - *) RUBYLINK="$RUBYLINK `($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["LIBS"]]') 2>/dev/null`";; - esac - - RUBYCCDLFLAGS=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["CCDLFLAGS"]]') 2>/dev/null` - RUBYSO=.`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["DLEXT"]]') 2>/dev/null` -else - AC_MSG_RESULT(could not figure out how to run ruby) -fi - -case $host in -*-*-cygwin* | *-*-mingw*) RUBYDYNAMICLINKING="-L$RUBYLIB $RUBYLINK";; -*) RUBYDYNAMICLINKING="";; -esac -fi - -AC_SUBST(RUBYINCLUDE) -AC_SUBST(RUBYLIB) -AC_SUBST(RUBYLINK) -AC_SUBST(RUBYCCDLFLAGS) -AC_SUBST(RUBYSO) -AC_SUBST(RUBYDYNAMICLINKING) - -#------------------------------------------------------------------------- -# Look for PHP -#------------------------------------------------------------------------- - -PHPBIN= - -AC_ARG_WITH(php, AS_HELP_STRING([--without-php], [Disable PHP]) -AS_HELP_STRING([--with-php=path], [Set location of PHP executable]),[ PHPBIN="$withval"], [PHPBIN="$alllang_default"]) - -# First, check for "--without-php" or "--with-php=no". -if test x"${PHPBIN}" = xno; then - AC_MSG_NOTICE([Disabling PHP]) - PHP= -else - if test "x$PHPBIN" = xyes; then - AC_CHECK_PROGS(PHP, [php8.1 php8.0 php7.4 php7.3 php7.2 php7.1 php7.0 php]) - else - PHP=$PHPBIN - fi - - if test -n "$PHP"; then - AC_MSG_CHECKING(for PHP header files) - dnl /usr/bin/php7.0 -> /usr/bin/php-config7.0 - case $PHP in - *7.*) - PHPCONFIG=`echo "$PHP"|sed 's/7\...*$/-config&/'` ;; - *8.*) - PHPCONFIG=`echo "$PHP"|sed 's/8\...*$/-config&/'` ;; - *) - PHPCONFIG=$PHP-config ;; - esac - php_version=`$PHPCONFIG --version 2>/dev/null` - case $php_version in - 7.*|8.*) - PHPINC=`$PHPCONFIG --includes 2>/dev/null` - if test -n "$PHPINC"; then - AC_MSG_RESULT($PHPINC) - else - AC_MSG_RESULT(not found) - fi - ;; - "") - AC_MSG_RESULT([could not find $PHPCONFIG or obtain PHP version from it]) ;; - *) - AC_MSG_RESULT([found PHP $php_version - not PHP 7 or 8]) ;; - esac - fi -fi -AC_SUBST(PHP) -AC_SUBST(PHPINC) - -#---------------------------------------------------------------- -# Look for OCaml -#---------------------------------------------------------------- - -AC_ARG_WITH(ocaml, AS_HELP_STRING([--without-ocaml], [Disable OCaml]), [with_ocaml="$withval"], [with_ocaml="$alllang_default"]) -AC_ARG_WITH(ocamlc,[ --with-ocamlc=path Set location of ocamlc executable],[ OCAMLC="$withval"], [OCAMLC=]) -AC_ARG_WITH(ocamldlgen,[ --with-ocamldlgen=path Set location of ocamldlgen],[ OCAMLDLGEN="$withval" ], [OCAMLDLGEN=]) -AC_ARG_WITH(ocamlfind,[ --with-ocamlfind=path Set location of ocamlfind],[OCAMLFIND="$withval"],[OCAMLFIND=]) -AC_ARG_WITH(ocamlmktop,[ --with-ocamlmktop=path Set location of ocamlmktop executable],[ OCAMLMKTOP="$withval"], [OCAMLMKTOP=]) -AC_ARG_WITH(camlp4,[ --with-camlp4=path Set location of camlp4 executable],[ CAMLP4="$withval"], [CAMLP4=]) - -# First, check for "--without-ocaml" or "--with-ocaml=no". -if test x"${with_ocaml}" = xno; then - AC_MSG_NOTICE([Disabling OCaml]) - OCAMLC= -else - # OCaml compiler - if test -z "$OCAMLC"; then - AC_CHECK_PROGS(OCAMLC, ocamlc) - fi - - # OCaml Pre-Processor-Pretty-Printer - if test -z "$CAMLP4"; then - AC_CHECK_PROGS(CAMLP4, camlp4) - fi - - # OCaml DL load generator - if test -z "$OCAMLDLGEN"; then - AC_CHECK_PROGS(OCAMLDLGEN, ocamldlgen) - fi - - # OCaml package tool - if test -z "$OCAMLFIND"; then - AC_CHECK_PROGS(OCAMLFIND, ocamlfind) - fi - - # OCaml toplevel creator - if test -z "$OCAMLMKTOP"; then - AC_CHECK_PROGS(OCAMLMKTOP, ocamlmktop) - fi -fi - -AC_SUBST(OCAMLC) -AC_SUBST(CAMLP4) -AC_SUBST(OCAMLDLGEN) -AC_SUBST(OCAMLFIND) -AC_SUBST(OCAMLMKTOP) - -#---------------------------------------------------------------- -# Look for C# -#---------------------------------------------------------------- - -AC_ARG_WITH(csharp, AS_HELP_STRING([--without-csharp], [Disable CSharp]), [with_csharp="$withval"], [with_csharp="$alllang_default"]) -AC_ARG_WITH(cil-interpreter, [ --with-cil-interpreter=path Set location of CIL interpreter for CSharp],[CSHARPBIN="$withval"], [CSHARPBIN=]) -AC_ARG_WITH(csharp-compiler, [ --with-csharp-compiler=path Set location of CSharp compiler],[CSHARPCOMPILERBIN="$withval"], [CSHARPCOMPILERBIN=]) - -# First, check for "--without-csharp" or "--with-csharp=no". -if test x"${with_csharp}" = xno; then -AC_MSG_NOTICE([Disabling CSharp]) -CSHARPCOMPILER= -else - -if test -z "$CSHARPCOMPILERBIN" ; then - case $host in - *-*-cygwin* | *-*-mingw*) - # prefer unified Mono mcs compiler (not to be confused with the ancient .NET 1 mcs) over older/alternative names. - AC_CHECK_PROGS(CSHARPCOMPILER, csc mcs mono-csc gmcs cscc) - if test -n "$CSHARPCOMPILER" && test "$CSHARPCOMPILER" = "csc" ; then - AC_MSG_CHECKING(whether csc is the Microsoft CSharp compiler) - csc 2>/dev/null | grep "C#" > /dev/null || CSHARPCOMPILER="" - if test -z "$CSHARPCOMPILER" ; then - AC_MSG_RESULT(no) - AC_CHECK_PROGS(CSHARPCOMPILER, mcs mono-csc gmcs cscc) - else - AC_MSG_RESULT(yes) - fi - fi - ;; - *)AC_CHECK_PROGS(CSHARPCOMPILER, mono-csc gmcs mcs cscc);; - esac -else - CSHARPCOMPILER="$CSHARPCOMPILERBIN" -fi - -CSHARPCONVERTPATH="Tools/convertpath -u" -if test -z "$CSHARPBIN" ; then - CSHARPCILINTERPRETER="" - CSHARPCILINTERPRETER_FLAGS="" - if test "cscc" = "$CSHARPCOMPILER" ; then - AC_CHECK_PROGS(CSHARPCILINTERPRETER, ilrun) - else - if test "mcs" = "$CSHARPCOMPILER"; then - # Check that mcs is the C# compiler and not the Unix mcs utility by examining the output of 'mcs --version' - # The Mono compiler should emit: Mono C# compiler version a.b.c.d - csharp_version_raw=`(mcs --version) 2>/dev/null` - csharp_version_searched=`(mcs --version | sed -e "/C#/b" -e "/Mono/b" -e d) 2>/dev/null` # return string if contains 'Mono' or 'C#' - CSHARPCOMPILER="" - if test -n "$csharp_version_raw" ; then - if test "$csharp_version_raw" = "$csharp_version_searched" ; then - CSHARPCOMPILER="mcs" - fi - fi - if test "mcs" != "$CSHARPCOMPILER" ; then - echo "mcs is not a working Mono C# compiler" - fi - fi - if test "mcs" = "$CSHARPCOMPILER" || test "gmcs" = "$CSHARPCOMPILER" || test "mono-csc" = "$CSHARPCOMPILER"; then - AC_CHECK_PROGS(CSHARPCILINTERPRETER, mono) # Mono JIT - CSHARPCILINTERPRETER_FLAGS="--debug" - else - if test "csc" = "$CSHARPCOMPILER"; then - CSHARPCONVERTPATH="Tools/convertpath -w" - fi - fi - fi -else - CSHARPCILINTERPRETER="$CSHARPBIN" -fi - -# Cygwin requires the Windows standard (Pascal) calling convention as it is a Windows executable and not a Cygwin built executable -case $host in -*-*-cygwin* | *-*-mingw*) - if test "$GCC" = yes; then - CSHARPDYNAMICLINKING="$GCC_MNO_CYGWIN -mthreads -Wl,--add-stdcall-alias" - CSHARPCFLAGS="$GCC_MNO_CYGWIN -mthreads" - else - CSHARPDYNAMICLINKING="" - CSHARPCFLAGS="" - fi ;; -*) - CSHARPDYNAMICLINKING="" - CSHARPCFLAGS="" - ;; -esac - -# CSharp on Windows platforms including Cygwin doesn't use libname.dll, rather name.dll when loading dlls -case $host in -*-*-cygwin* | *-*-mingw*) CSHARPLIBRARYPREFIX="";; -*)CSHARPLIBRARYPREFIX="lib";; -esac - -# C#/Mono on Mac OS X tweaks -case $host in -*-*-darwin*) - CSHARPSO=".so" - ;; -*) - CSHARPSO=$SO - ;; -esac -fi - -AC_SUBST(CSHARPCILINTERPRETER_FLAGS) -AC_SUBST(CSHARPCILINTERPRETER) -AC_SUBST(CSHARPCONVERTPATH) -AC_SUBST(CSHARPCOMPILER) -AC_SUBST(CSHARPDYNAMICLINKING) -AC_SUBST(CSHARPLIBRARYPREFIX) -AC_SUBST(CSHARPCFLAGS) -AC_SUBST(CSHARPSO) - #---------------------------------------------------------------- # Look for Lua #---------------------------------------------------------------- @@ -2443,7 +1519,718 @@ AC_SUBST(LUALINK) AC_SUBST(LUABIN) #---------------------------------------------------------------- -# Look for GNU R +# Look for MzScheme +#---------------------------------------------------------------- + +AC_ARG_WITH(mzscheme, AS_HELP_STRING([--without-mzscheme], [Disable MzScheme]) +AS_HELP_STRING([--with-mzscheme=path], [Set location of MzScheme executable]),[ MZSCHEMEBIN="$withval"], [MZSCHEMEBIN="$alllang_default"]) +AC_ARG_WITH(mzc, AS_HELP_STRING([--with-mzc=path], [Set location of MzScheme's mzc]), [ MZCBIN="$withval"], [MZCBIN=]) + +# First, check for "--without-mzscheme" or "--with-mzscheme=no". +if test x"${MZSCHEMEBIN}" = xno; then + AC_MSG_NOTICE([Disabling MzScheme]) + MZC= +else + if test "x$MZSCHEMEBIN" = xyes; then + AC_PATH_PROG(MZSCHEME, mzscheme) + else + MZSCHEME="$MZSCHEMEBIN" + fi + + if test -z "$MZCBIN"; then + AC_PATH_PROG(MZC, mzc) + fi + + if test -n "$MZSCHEME"; then + AC_MSG_CHECKING(for MzScheme dynext object) + MZDYNOBJ=`$MZSCHEME --eval '(begin (require dynext/link) (with-handlers (((lambda args #t) (lambda args #f))) (for-each (lambda (x) (printf "~a" x)) (expand-for-link-variant (current-standard-link-libraries)))))' 2>/dev/null` + if test -f "$MZDYNOBJ"; then + : + else + # older versions (3.72 approx and earlier) + MZDYNOBJ=`$MZSCHEME --mute-banner --version --eval '(begin (require (lib "link.ss" "dynext")) (with-handlers (((lambda args #t) (lambda args #f))) (for-each (lambda (x) (display x) (display " ")) ((current-make-standard-link-libraries)))) (with-handlers (((lambda args #t) (lambda args #f))) (for-each (lambda (x) (display x)) (expand-for-link-variant (current-standard-link-libraries)))))' 2>/dev/null` + fi + if test -f "$MZDYNOBJ"; then + AC_MSG_RESULT($MZDYNOBJ) + else + AC_MSG_RESULT(not found) + MZDYNOBJ="" + fi + fi +fi +AC_SUBST(MZDYNOBJ) + +#---------------------------------------------------------------- +# Look for OCaml +#---------------------------------------------------------------- + +AC_ARG_WITH(ocaml, AS_HELP_STRING([--without-ocaml], [Disable OCaml]), [with_ocaml="$withval"], [with_ocaml="$alllang_default"]) +AC_ARG_WITH(ocamlc,[ --with-ocamlc=path Set location of ocamlc executable],[ OCAMLC="$withval"], [OCAMLC=]) +AC_ARG_WITH(ocamldlgen,[ --with-ocamldlgen=path Set location of ocamldlgen],[ OCAMLDLGEN="$withval" ], [OCAMLDLGEN=]) +AC_ARG_WITH(ocamlfind,[ --with-ocamlfind=path Set location of ocamlfind],[OCAMLFIND="$withval"],[OCAMLFIND=]) +AC_ARG_WITH(ocamlmktop,[ --with-ocamlmktop=path Set location of ocamlmktop executable],[ OCAMLMKTOP="$withval"], [OCAMLMKTOP=]) +AC_ARG_WITH(camlp4,[ --with-camlp4=path Set location of camlp4 executable],[ CAMLP4="$withval"], [CAMLP4=]) + +# First, check for "--without-ocaml" or "--with-ocaml=no". +if test x"${with_ocaml}" = xno; then + AC_MSG_NOTICE([Disabling OCaml]) + OCAMLC= +else + # OCaml compiler + if test -z "$OCAMLC"; then + AC_CHECK_PROGS(OCAMLC, ocamlc) + fi + + # OCaml Pre-Processor-Pretty-Printer + if test -z "$CAMLP4"; then + AC_CHECK_PROGS(CAMLP4, camlp4) + fi + + # OCaml DL load generator + if test -z "$OCAMLDLGEN"; then + AC_CHECK_PROGS(OCAMLDLGEN, ocamldlgen) + fi + + # OCaml package tool + if test -z "$OCAMLFIND"; then + AC_CHECK_PROGS(OCAMLFIND, ocamlfind) + fi + + # OCaml toplevel creator + if test -z "$OCAMLMKTOP"; then + AC_CHECK_PROGS(OCAMLMKTOP, ocamlmktop) + fi +fi + +AC_SUBST(OCAMLC) +AC_SUBST(CAMLP4) +AC_SUBST(OCAMLDLGEN) +AC_SUBST(OCAMLFIND) +AC_SUBST(OCAMLMKTOP) + +#---------------------------------------------------------------- +# Look for Octave +#---------------------------------------------------------------- + +OCTAVEBIN= +OCTAVE_SO=.oct + +AC_ARG_WITH(octave, AS_HELP_STRING([--without-octave], [Disable Octave]) +AS_HELP_STRING([--with-octave=path], [Set location of Octave executable]),[OCTAVEBIN="$withval"], [OCTAVEBIN="$alllang_default"]) + +# Check for "--without-octave" or "--with-octave=no". +if test x"${OCTAVEBIN}" = xno; then + AC_MSG_NOTICE([Disabling Octave]) + OCTAVE= + +# Check for Octave; prefer command-line program "octave-cli" to (in newer versions) GUI program "octave" +elif test "x$OCTAVEBIN" = xyes; then + AC_PATH_PROG(OCTAVE, [octave-cli octave]) + +else + OCTAVE="$OCTAVEBIN" +fi + +# Check if Octave works +if test -n "$OCTAVE"; then + AC_MSG_CHECKING([if ${OCTAVE} works]) + AS_IF([test "x`${OCTAVE} --version 2>/dev/null | sed -n -e '1p' | sed -n -e '/Octave, version/p'`" != x],[ + AC_MSG_RESULT([yes]) + ],[ + AC_MSG_RESULT([no]) + OCTAVE= + ]) +fi + +# Check for required Octave helper program "mkoctfile" +if test -n "$OCTAVE"; then + AC_MSG_CHECKING([for mkoctfile]) + version_suffix=["`echo $OCTAVE | sed -e 's|.*\(-[0-9][0-9.]*\)$|\1|'`"] + case $version_suffix in + -*) ;; + *) version_suffix="" ;; + esac + octave_directory=`dirname $OCTAVE` + if test "$octave_directory" = "." ; then + mkoctfile="mkoctfile${version_suffix}" + else + mkoctfile="${octave_directory}/mkoctfile${version_suffix}" + fi + AC_MSG_RESULT([${mkoctfile}]) + AC_MSG_CHECKING([if ${mkoctfile} works]) + mkoctfile="env - PATH=$PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH ${mkoctfile}" + AS_IF([test "x`${mkoctfile} --version 2>/dev/null | sed -n -e '1p' | sed -n -e '/mkoctfile, version/p'`" != x],[ + AC_MSG_RESULT([yes]) + ],[ + AC_MSG_RESULT([no]) + OCTAVE= + ]) +fi + +# Check for Octave preprocessor/compiler/linker flags +if test -n "$OCTAVE"; then + + AC_MSG_CHECKING([for Octave preprocessor flags]) + OCTAVE_CPPFLAGS= + for var in CPPFLAGS INCFLAGS ALL_CXXFLAGS; do + for flag in `${mkoctfile} -p ${var}`; do + case ${flag} in + -D*|-I*) OCTAVE_CPPFLAGS="${OCTAVE_CPPFLAGS} ${flag}";; + *) ;; + esac + done + done + AC_MSG_RESULT([$OCTAVE_CPPFLAGS]) + + AC_MSG_CHECKING([for Octave compiler flags]) + OCTAVE_CXXFLAGS= + for var in CXX ALL_CXXFLAGS; do + for flag in `${mkoctfile} -p ${var}`; do + case ${flag} in + -std=*|-g*|-W*) OCTAVE_CXXFLAGS="${OCTAVE_CXXFLAGS} ${flag}";; + *) ;; + esac + done + done + save_CXXFLAGS="${CXXFLAGS}" + CXXFLAGS="-Werror -O0" + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([],[]) + ],[ + OCTAVE_CXXFLAGS="${OCTAVE_CXXFLAGS} -O0" + ]) + CXXFLAGS="${save_CXXFLAGS}" + AC_MSG_RESULT([$OCTAVE_CXXFLAGS]) + + AC_MSG_CHECKING([for Octave linker flags]) + OCTAVE_LDFLAGS= + for var in OCTLIBDIR; do + OCTAVE_LDFLAGS="${OCTAVE_LDFLAGS} "-L`${mkoctfile} -p ${var}` + done + for var in RDYNAMIC_FLAG RLD_FLAG OCTAVE_LIBS LIBS; do + OCTAVE_LDFLAGS="${OCTAVE_LDFLAGS} "`${mkoctfile} -p ${var}` + done + AC_MSG_RESULT([$OCTAVE_LDFLAGS]) + +fi + +# Check for Octave options +if test -n "$OCTAVE"; then + for octave_opt in --no-window-system --silent --norc --no-history; do + AC_MSG_CHECKING([if Octave option '${octave_opt}' is supported]) + octave_out=`${OCTAVE} ${octave_opt} /dev/null 2>&1 | sed -n '1p' | sed -n '/unrecognized/p'` + AS_IF([test "x${octave_out}" = x],[ + AC_MSG_RESULT([yes]) + OCTAVE="${OCTAVE} ${octave_opt}" + ],[ + AC_MSG_RESULT([no]) + ]) + done +fi + +AC_SUBST(OCTAVE) +AC_SUBST(OCTAVE_SO) +AC_SUBST(OCTAVE_CPPFLAGS) +AC_SUBST(OCTAVE_CXXFLAGS) +AC_SUBST(OCTAVE_LDFLAGS) + +#---------------------------------------------------------------- +# Look for Perl5 +#---------------------------------------------------------------- + +PERLBIN= + +AC_ARG_WITH(perl5, AS_HELP_STRING([--without-perl5], [Disable Perl5]) +AS_HELP_STRING([--with-perl5=path], [Set location of Perl5 executable]),[ PERLBIN="$withval"], [PERLBIN="$alllang_default"]) + +# First, check for "--without-perl5" or "--with-perl5=no". +if test x"${PERLBIN}" = xno; then +AC_MSG_NOTICE([Disabling Perl5]) +PERL= +else + +# First figure out what the name of Perl5 is + +if test "x$PERLBIN" = xyes; then +AC_CHECK_PROGS(PERL, perl perl5) +else +PERL="$PERLBIN" +fi + + +# This could probably be simplified as for all platforms and all versions of Perl the following apparently should be run to get the compilation options: +# perl -MExtUtils::Embed -e ccopts +AC_MSG_CHECKING(for Perl5 header files) +if test -n "$PERL"; then + PERL5DIR=`($PERL -MConfig -le 'print $Config{archlibexp}') 2>/dev/null` + if test -n "$PERL5DIR" ; then + dirs="$PERL5DIR $PERL5DIR/CORE" + PERL5EXT=none + for i in $dirs; do + if test -r $i/perl.h; then + AC_MSG_RESULT($i) + PERL5EXT="$i" + break + fi + done + if test "$PERL5EXT" = none; then + PERL5EXT="$PERL5DIR/CORE" + AC_MSG_RESULT(could not locate perl.h...using $PERL5EXT) + fi + + AC_MSG_CHECKING(for Perl5 library) + PERL5LIB=`($PERL -e 'use Config; $_=$Config{libperl}; s/^lib//; s/$Config{_a}$//; s/\.$Config{so}.*//; print $_, "\n"') 2>/dev/null` + if test -z "$PERL5LIB" ; then + AC_MSG_RESULT(not found) + else + AC_MSG_RESULT($PERL5LIB) + fi + AC_MSG_CHECKING(for Perl5 ccflags) + PERL5CCFLAGS=`($PERL -e 'use Config; print $Config{ccflags}, "\n"' | sed "s/-Wdeclaration-after-statement//") 2>/dev/null` + if test -z "$PERL5CCFLAGS" ; then + AC_MSG_RESULT(not found) + else + AC_MSG_RESULT($PERL5CCFLAGS) + fi + AC_MSG_CHECKING(for Perl5 ccdlflags) + PERL5CCDLFLAGS=`($PERL -e 'use Config; print $Config{ccdlflags}, "\n"') 2>/dev/null` + if test -z "$PERL5CCDLFLAGS" ; then + AC_MSG_RESULT(not found) + else + AC_MSG_RESULT($PERL5CCDLFLAGS) + fi + AC_MSG_CHECKING(for Perl5 cccdlflags) + PERL5CCCDLFLAGS=`($PERL -e 'use Config; print $Config{cccdlflags}, "\n"') 2>/dev/null` + if test -z "$PERL5CCCDLFLAGS" ; then + AC_MSG_RESULT(not found) + else + AC_MSG_RESULT($PERL5CCCDLFLAGS) + fi + AC_MSG_CHECKING(for Perl5 ldflags) + PERL5LDFLAGS=`($PERL -e 'use Config; print $Config{ldflags}, "\n"') 2>/dev/null` + if test -z "$PERL5LDFLAGS" ; then + AC_MSG_RESULT(not found) + else + AC_MSG_RESULT($PERL5LDFLAGS) + fi + AC_MSG_CHECKING(for Perl5 Test::More module) # For test-suite + PERL5TESTMORE=`($PERL -e 'use Test::More; print "good";') 2>/dev/null` + if test -z "$PERL5TESTMORE" ; then + AC_MSG_RESULT(not found) + else + AC_MSG_RESULT(found) + fi + else + AC_MSG_RESULT(unable to determine perl5 configuration) + PERL5EXT=$PERL5DIR + fi +else + AC_MSG_RESULT(could not figure out how to run perl5) +fi + +# Cygwin (Windows) needs the library for dynamic linking +case $host in +*-*-cygwin* | *-*-mingw*) PERL5DYNAMICLINKING="-L$PERL5EXT -l$PERL5LIB";; +*)PERL5DYNAMICLINKING="";; +esac +fi + +AC_SUBST(PERL) +AC_SUBST(PERL5EXT) +AC_SUBST(PERL5DYNAMICLINKING) +AC_SUBST(PERL5LIB) +AC_SUBST(PERL5CCFLAGS) +AC_SUBST(PERL5CCDLFLAGS) +AC_SUBST(PERL5CCCDLFLAGS) +AC_SUBST(PERL5LDFLAGS) + +#------------------------------------------------------------------------- +# Look for PHP +#------------------------------------------------------------------------- + +PHPBIN= + +AC_ARG_WITH(php, AS_HELP_STRING([--without-php], [Disable PHP]) +AS_HELP_STRING([--with-php=path], [Set location of PHP executable]),[ PHPBIN="$withval"], [PHPBIN="$alllang_default"]) + +# First, check for "--without-php" or "--with-php=no". +if test x"${PHPBIN}" = xno; then + AC_MSG_NOTICE([Disabling PHP]) + PHP= +else + if test "x$PHPBIN" = xyes; then + AC_CHECK_PROGS(PHP, [php8.1 php8.0 php7.4 php7.3 php7.2 php7.1 php7.0 php]) + else + PHP=$PHPBIN + fi + + if test -n "$PHP"; then + AC_MSG_CHECKING(for PHP header files) + dnl /usr/bin/php7.0 -> /usr/bin/php-config7.0 + case $PHP in + *7.*) + PHPCONFIG=`echo "$PHP"|sed 's/7\...*$/-config&/'` ;; + *8.*) + PHPCONFIG=`echo "$PHP"|sed 's/8\...*$/-config&/'` ;; + *) + PHPCONFIG=$PHP-config ;; + esac + php_version=`$PHPCONFIG --version 2>/dev/null` + case $php_version in + 7.*|8.*) + PHPINC=`$PHPCONFIG --includes 2>/dev/null` + if test -n "$PHPINC"; then + AC_MSG_RESULT($PHPINC) + else + AC_MSG_RESULT(not found) + fi + ;; + "") + AC_MSG_RESULT([could not find $PHPCONFIG or obtain PHP version from it]) ;; + *) + AC_MSG_RESULT([found PHP $php_version - not PHP 7 or 8]) ;; + esac + fi +fi +AC_SUBST(PHP) +AC_SUBST(PHPINC) + +#---------------------------------------------------------------- +# Look for Python +#---------------------------------------------------------------- + +PYINCLUDE= +PYLIB= +PYLINK= +PYPACKAGE= + +AC_ARG_WITH(python, AS_HELP_STRING([--without-python], [Don't probe for Python 2.x]) +AS_HELP_STRING([--with-python=path], [Set location of Python 2.x executable]), [PYBIN="$withval"], [PYBIN="$alllang_default"]) + +# First, check for "--without-python" or "--with-python=no". +if test x"${PYBIN}" = xno; then + AC_MSG_NOTICE([Disabling Python 2.x probe]) +else + # First figure out the name of the Python 2.x executable + if test "x$PYBIN" = xyes; then + AC_CHECK_PROGS(PYTHON, [python python2.7]) + else + PYTHON="$PYBIN" + fi + + PYVER=0 + if test -n "$PYTHON"; then + AC_MSG_CHECKING([for $PYTHON major version number]) + PYVER=`($PYTHON -c "import sys; sys.stdout.write(sys.version[[0]])") 2>/dev/null` + AC_MSG_RESULT($PYVER) + if test -z "$PYVER"; then + PYVER=0 + else + AC_MSG_CHECKING(for Python 2.x os.name) + PYOSNAME=`($PYTHON -c "import sys, os; sys.stdout.write(os.name)") 2>/dev/null` + AC_MSG_RESULT($PYOSNAME) + AC_MSG_CHECKING(for Python 2.x path separator) + PYSEPARATOR=`($PYTHON -c "import sys, os; sys.stdout.write(os.sep)") 2>/dev/null` + AC_MSG_RESULT($PYSEPARATOR) + fi + fi + + if test $PYVER -eq 1 -o $PYVER -eq 2; then + AC_MSG_CHECKING(for Python 2.x prefix) + PYPREFIX=`($PYTHON -c "import sys; sys.stdout.write(sys.prefix)") 2>/dev/null` + AC_MSG_RESULT($PYPREFIX) + AC_MSG_CHECKING(for Python 2.x exec-prefix) + PYEPREFIX=`($PYTHON -c "import sys; sys.stdout.write(sys.exec_prefix)") 2>/dev/null` + AC_MSG_RESULT($PYEPREFIX) + + if test x"$PYOSNAME" = x"nt" -a x"$PYSEPARATOR" = x"\\"; then + # Windows installations are quite different to posix installations (MinGW path separator is a forward slash) + PYPREFIX=`echo "$PYPREFIX" | sed -e 's,\\\\,/,g'` # Forward slashes are easier to use and even work on Windows most of the time + PYTHON_SO=.pyd + + AC_MSG_CHECKING(for Python 2.x header files) + if test -r $PYPREFIX/include/Python.h; then + PYINCLUDE="-I$PYPREFIX/include" + fi + AC_MSG_RESULT($PYINCLUDE) + + AC_MSG_CHECKING(for Python 2.x library directory) + if test -d $PYPREFIX/libs; then + PYLIB=$PYPREFIX/libs + PYLINKFILE=`ls $PYLIB/python*.lib | grep "python[[0-9]][[0-9]]\+\.lib"` + if test -r "$PYLINKFILE"; then + PYLINK=-l`basename $PYLINKFILE | sed -e 's/\.lib$//'` + else + PYLIB= + fi + fi + else + # Note: I could not think of a standard way to get the version string from different versions. + # This trick pulls it out of the file location for a standard library file. + + AC_MSG_CHECKING(for Python 2.x version) + + # Need to do this hack since autoconf replaces __file__ with the name of the configure file + filehack="file__" + PYVERSION=`($PYTHON -c "import sys,string,operator,os.path; sys.stdout.write(operator.getitem(os.path.split(operator.getitem(os.path.split(string.__$filehack),0)),1))") 2>/dev/null` + AC_MSG_RESULT($PYVERSION) + + # Find the directory for libraries this is necessary to deal with + # platforms that can have apps built for multiple archs: e.g. x86_64 + AC_MSG_CHECKING(for Python 2.x lib dir) + PYLIBDIR=`($PYTHON -c "import sys; sys.stdout.write(sys.lib)") 2>/dev/null` + if test -z "$PYLIBDIR"; then + # Fedora patch Python to add sys.lib, for other distros we assume "lib". + PYLIBDIR="lib" + fi + AC_MSG_RESULT($PYLIBDIR) + + # Set the include directory + + AC_MSG_CHECKING(for Python 2.x header files) + if test -r $PYPREFIX/include/$PYVERSION/Python.h; then + PYINCLUDE="-I$PYPREFIX/include/$PYVERSION -I$PYEPREFIX/$PYLIBDIR/$PYVERSION/config" + fi + if test -z "$PYINCLUDE"; then + if test -r $PYPREFIX/include/Py/Python.h; then + PYINCLUDE="-I$PYPREFIX/include/Py -I$PYEPREFIX/$PYLIBDIR/python/lib" + fi + fi + AC_MSG_RESULT($PYINCLUDE) + + # Set the library directory blindly. This probably won't work with older versions + AC_MSG_CHECKING(for Python 2.x library directory) + dirs="$PYVERSION/config $PYVERSION/$PYLIBDIR python/$PYLIBDIR" + for i in $dirs; do + if test -d $PYEPREFIX/$PYLIBDIR/$i; then + PYLIB="$PYEPREFIX/$PYLIBDIR/$i" + break + fi + done + + PYLINK="-l$PYVERSION" + fi + + if test -z "$PYLIB"; then + AC_MSG_RESULT(Not found) + else + AC_MSG_RESULT($PYLIB) + fi + AC_MSG_CHECKING(for Python 2.x library) + if test -z "$PYLINK"; then + AC_MSG_RESULT(Not found) + else + AC_MSG_RESULT($PYLINK) + fi + fi + + # Cygwin (Windows) needs the library for dynamic linking + case $host in + *-*-cygwin* | *-*-mingw*) + PYTHONDYNAMICLINKING="-L$PYLIB $PYLINK" + DEFS="-DUSE_DL_IMPORT $DEFS" + ;; + *-*-aix*) + PYTHONDYNAMICLINKING="-L$PYLIB $PYLINK" + ;; + *)PYTHONDYNAMICLINKING="";; + esac +fi + +AC_SUBST(PYINCLUDE) +AC_SUBST(PYLIB) +AC_SUBST(PYLINK) +AC_SUBST(PYTHONDYNAMICLINKING) + + +#---------------------------------------------------------------- +# Look for Python 3.x +#---------------------------------------------------------------- + +PY3INCLUDE= +PY3LIB= +PY3LINK= +PY3PACKAGE= + +AC_ARG_WITH(python3, AS_HELP_STRING([--without-python3], [Don't probe for Python 3.x]) +AS_HELP_STRING([--with-python3=path], [Set location of Python 3.x executable]), [PY3BIN="$withval"], [PY3BIN="$alllang_default"]) + +# First, check for "--without-python3" or "--with-python3=no". +if test x"${PY3BIN}" = xno; then + AC_MSG_NOTICE([Disabling Python 3.x probe]) +else + if test -z "$PYVER"; then + PYVER=0 + fi + if test "x$PY3BIN" = xyes; then + if test x"$PYOSNAME" = x"nt" -a x"$PYSEPARATOR" = x"\\" -a $PYVER -ge 3; then + PYTHON3="$PYTHON" + else + for py_ver in 3 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 ""; do + AC_CHECK_PROGS(PYTHON3, [python$py_ver]) + if test -n "$PYTHON3"; then + AC_CHECK_PROGS(PY3CONFIG, [$PYTHON3-config]) + if test -n "$PY3CONFIG"; then + break + fi + fi + done + fi + else + PYTHON3="$PY3BIN" + AC_CHECK_PROGS(PY3CONFIG, [$PYTHON3-config]) + fi + + if test -n "$PYTHON3"; then + AC_MSG_CHECKING([for $PYTHON3 major version number]) + PYVER=`($PYTHON3 -c "import sys; sys.stdout.write(sys.version[[0]])") 2>/dev/null` + AC_MSG_RESULT($PYVER) + if test -z "$PYVER"; then + PYVER=0 + fi + fi + + if test $PYVER -ge 3; then + AC_MSG_CHECKING(for Python 3.x os.name) + PY3OSNAME=`($PYTHON3 -c "import sys, os; sys.stdout.write(os.name)") 2>/dev/null` + AC_MSG_RESULT($PY3OSNAME) + AC_MSG_CHECKING(for Python 3.x path separator) + PYSEPARATOR=`($PYTHON3 -c "import sys, os; sys.stdout.write(os.sep)") 2>/dev/null` + AC_MSG_RESULT($PYSEPARATOR) + + if test x"$PY3OSNAME" = x"nt" -a x"$PYSEPARATOR" = x"\\"; then + # Windows installations are quite different to posix installations + # There is no python-config to use + AC_MSG_CHECKING(for Python 3.x prefix) + PY3PREFIX=`($PYTHON3 -c "import sys; sys.stdout.write(sys.prefix)") 2>/dev/null` + AC_MSG_RESULT($PY3PREFIX) + PY3PREFIX=`echo "$PY3PREFIX" | sed -e 's,\\\\,/,g'` # Forward slashes are easier to use and even work on Windows most of the time + PYTHON_SO=.pyd + + AC_MSG_CHECKING(for Python 3.x header files) + if test -r $PY3PREFIX/include/Python.h; then + PY3INCLUDE="-I$PY3PREFIX/include" + fi + AC_MSG_RESULT($PY3INCLUDE) + + AC_MSG_CHECKING(for Python 3.x library directory) + if test -d $PY3PREFIX/libs; then + PY3LIB=$PY3PREFIX/libs + PY3LINKFILE=`ls $PY3LIB/python*.lib | grep "python[[0-9]][[0-9]]\+\.lib"` + if test -r "$PY3LINKFILE"; then + PY3LINK=-l`basename $PY3LINKFILE | sed -e 's/\.lib$//'` + else + PY3LIB= + fi + fi + if test -z "$PY3LIB"; then + AC_MSG_RESULT([Not found]) + else + AC_MSG_RESULT($PY3LIB) + fi + AC_MSG_CHECKING([for Python 3.x library]) + if test -z "$PY3LINK"; then + AC_MSG_RESULT(Not found) + else + AC_MSG_RESULT($PY3LINK) + fi + elif test -n "$PY3CONFIG"; then + AC_MSG_CHECKING([for Python 3.x prefix]) + PY3PREFIX=`($PY3CONFIG --prefix) 2>/dev/null` + AC_MSG_RESULT($PY3PREFIX) + AC_MSG_CHECKING(for Python 3.x exec-prefix) + # Piped through xargs to strip trailing whitespace (bug in msys2 + mingw Python) + PY3EPREFIX=`($PY3CONFIG --exec-prefix | xargs) 2>/dev/null` + AC_MSG_RESULT($PY3EPREFIX) + + # Note: I could not think of a standard way to get the version string from different versions. + # This trick pulls it out of the file location for a standard library file. + + AC_MSG_CHECKING([for Python 3.x version]) + + # Need to do this hack since autoconf replaces __file__ with the name of the configure file + filehack="file__" + PY3VERSION=`($PYTHON3 -c "import string,operator,os.path; print(operator.getitem(os.path.split(operator.getitem(os.path.split(string.__$filehack),0)),1))") 2>/dev/null` + AC_MSG_RESULT($PY3VERSION) + + # Find the directory for libraries this is necessary to deal with + # platforms that can have apps built for multiple archs: e.g. x86_64 + AC_MSG_CHECKING([for Python 3.x lib dir]) + PY3LIBDIR=`($PYTHON3 -c "import sys; print(sys.lib)") 2>/dev/null` + if test -z "$PY3LIBDIR"; then + # some dists don't have sys.lib so the best we can do is assume lib + PY3LIBDIR="lib" + fi + AC_MSG_RESULT($PY3LIBDIR) + + # Set the include directory + + AC_MSG_CHECKING([for Python 3.x header files]) + PY3INCLUDE=`($PY3CONFIG --includes) 2>/dev/null` + AC_MSG_RESULT($PY3INCLUDE) + + # Set the library directory blindly. This probably won't work with older versions + AC_MSG_CHECKING([for Python 3.x library directory]) + dirs="$PY3VERSION/config $PY3VERSION/$PY3LIBDIR python/$PY3LIBDIR" + for i in $dirs; do + if test -d $PY3EPREFIX/$PY3LIBDIR/$i; then + PY3LIB="$PY3EPREFIX/$PY3LIBDIR/$i" + break + fi + done + if test -z "$PY3LIB"; then + # Last resort + if test -d $PY3EPREFIX/$PY3LIBDIR; then + PY3LIB="$PY3EPREFIX/$PY3LIBDIR" + fi + fi + if test -z "$PY3LIB"; then + AC_MSG_RESULT([Not found]) + else + AC_MSG_RESULT($PY3LIB) + fi + + PY3LINK="-l$PY3VERSION" + + AC_MSG_CHECKING([for Python 3.x library]) + if test -z "$PY3LINK"; then + AC_MSG_RESULT(Not found) + else + AC_MSG_RESULT($PY3LINK) + fi + fi + fi + + # Cygwin (Windows) needs the library for dynamic linking + case $host in + *-*-cygwin* | *-*-mingw*) + # PYTHON3DYNAMICLINKING ought to be replaced by $PY3CONFIG --ldflags + PYTHON3DYNAMICLINKING="-L$PY3LIB $PY3LINK" + DEFS="-DUSE_DL_IMPORT $DEFS" + ;; + *-*-aix*) + PYTHON3DYNAMICLINKING="-L$PY3LIB $PY3LINK" + ;; + *)PYTHON3DYNAMICLINKING="";; + esac + + AC_SUBST(PY3INCLUDE) + AC_SUBST(PY3LIB) + AC_SUBST(PY3LINK) + AC_SUBST(PYTHON3DYNAMICLINKING) +fi + +if test -n "$PYINCLUDE" || test -n "$PY3INCLUDE" ; then + AC_CHECK_PROGS(PYCODESTYLE, pycodestyle) + if test -n "$PYCODESTYLE"; then + AC_MSG_CHECKING(pycodestyle version) + pycodestyle_version=`$PYCODESTYLE --version 2>/dev/null` + AC_MSG_RESULT($pycodestyle_version) + fi +fi + +#---------------------------------------------------------------- +# Look for R #---------------------------------------------------------------- RBIN= @@ -2466,252 +2253,383 @@ fi AC_SUBST(RBIN) #---------------------------------------------------------------- -# Look for Go compilers +# Look for Ruby #---------------------------------------------------------------- -AC_ARG_WITH(go, AS_HELP_STRING([--without-go], [Disable Go]) -AS_HELP_STRING([--with-go=path], [Set location of Go compiler]),[GOBIN="$withval"], [GOBIN="$alllang_default"]) +RUBYBIN= -if test x"${GOBIN}" = xno; then - AC_MSG_NOTICE([Disabling Go]) - GO= - GOGCC=false - GCCGO= - GOOPT= - GCCGOOPT= - GOVERSIONOPTION= +AC_ARG_WITH(ruby, AS_HELP_STRING([--without-ruby], [Disable Ruby]) +AS_HELP_STRING([--with-ruby=path], [Set location of Ruby executable]),[ RUBYBIN="$withval"], [RUBYBIN="$alllang_default"]) + +# First, check for "--without-ruby" or "--with-ruby=no". +RUBYSO=$SO +if test x"${RUBYBIN}" = xno; then +AC_MSG_NOTICE([Disabling Ruby]) +RUBY= else - if test "x$GOBIN" = xyes; then - AC_CHECK_PROGS(GO, go) - else - GO="$GOBIN" - fi +# First figure out what the name of Ruby is - GOGCC=false - GCCGO= - GOOPT= - GCCGOOPT= - GOVERSIONOPTION= +if test "x$RUBYBIN" = xyes; then + AC_CHECK_PROGS(RUBY, ruby) +else + RUBY="$RUBYBIN" +fi - if test -n "$GO" ; then - GOVERSIONOPTION=version - go_version=$($GO $GOVERSIONOPTION | sed -e 's/go version //') - AC_MSG_CHECKING([whether go version is too old]) - case $go_version in - go1.[012]*) - AC_MSG_RESULT([yes - minimum version is 1.3]) - GO= - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac - fi - - AC_CHECK_PROGS(GCCGO, gccgo) - - if test -n "$GCCGO" ; then - if $GCCGO --help 2>/dev/null | grep gccgo >/dev/null 2>&1 ; then - AC_MSG_CHECKING([whether gccgo version is too old]) - go_version=[`$GO $GOVERSIONOPTION | sed -n '1p' | sed -e 's/^.* \([0-9.]*\) *$/\1/' -e 's/[.]//g'`] - if test "x$go_version" = x; then - AC_MSG_RESULT([could not determine gccgo version]) - GCCGO= - elif test "$go_version" -lt 470; then - AC_MSG_RESULT([yes - minimum version is 4.7.0]) - GCCGO= - else - AC_MSG_RESULT([no]) - if test "$go_version" -lt 480; then - GCCGOOPT="-intgosize 32" +AC_MSG_CHECKING(for Ruby header files) +if test -n "$RUBY"; then + # Try Ruby1.9+ first + RUBYDIR=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["rubyhdrdir"]] || $rubyhdrdir') 2>/dev/null` + RUBYARCHHDRDIR=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["rubyarchhdrdir"]] || $rubyarchhdrdir') 2>/dev/null` + if test x"$RUBYDIR" = x"" || test x"$RUBYDIR" = x"nil"; then + RUBYDIR=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["archdir"]] || $archdir') 2>/dev/null` + else + RUBYARCH=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["arch"]] || $arch') 2>/dev/null` fi + if test x"$RUBYDIR" != x""; then + dirs="$RUBYDIR" + RUBYINCLUDE= + for i in $dirs; do + if test -r $i/ruby.h; then + if test x"$RUBYARCH" = x""; then + RUBYINCLUDE="-I$i" + elif test -n "$RUBYARCHHDRDIR"; then + RUBYINCLUDE="-I$i -I$RUBYARCHHDRDIR" + else + RUBYINCLUDE="-I$i -I$i/$RUBYARCH" + fi + AC_MSG_RESULT($RUBYINCLUDE) + break + fi + done + if test x"$RUBYINCLUDE" = x""; then + AC_MSG_RESULT(could not locate ruby.h) + fi + + # Find library and path for linking. + AC_MSG_CHECKING(for Ruby library) + RUBYLIB="" + rb_archlibdir=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["archlibdir"]]') 2>/dev/null` + rb_libdir=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["libdir"]]') 2>/dev/null` + rb_bindir=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["bindir"]]') 2>/dev/null` + dirs="$dirs $rb_archlibdir $rb_libdir $rb_bindir" + + rb_libruby=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["LIBRUBY_A"]]') 2>/dev/null` + RUBYLINK=`($RUBY -rrbconfig -e ' + c = RbConfig::CONFIG + if c.has_key? "LIBRUBYARG_STATIC" # 1.8.x + if c[["LIBRUBY"]] == c[["LIBRUBY_A"]] + link = c[["LIBRUBYARG_STATIC"]] + else + link = c[["LIBRUBYARG_SHARED"]] + end + else # 1.6.x + link = "-l" + c[["RUBY_INSTALL_NAME"]] + end + + # Get the target Ruby was built for + target = c[["target"]] + + if target == "i386-pc-mswin32" + # Need to change msvcrt-ruby*.lib to -lmsvcrt-ruby* + ext = File.extname(link) + # Get index that counts backwards from end of string + index = -1 - ext.size + # Strip off the extension + link = link.slice(0..index) + puts "-l#{link}" + else + puts link + end') 2>/dev/null` + + if test "$rb_libruby" != ""; then + for i in $dirs; do + if (test -r $i/$rb_libruby;) then + RUBYLIB="$i" + break + fi + done + fi + if test "$RUBYLIB" = ""; then + RUBYLIB="$RUBYDIR" + AC_MSG_RESULT(not found... using $RUBYDIR) + else + AC_MSG_RESULT($RUBYLINK in $RUBYLIB) + fi + else + AC_MSG_RESULT(unable to determine ruby configuration) + fi + + case $host in + *-*-mingw*) ;; # do nothing, the default windows libraries are already included + *) RUBYLINK="$RUBYLINK `($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["LIBS"]]') 2>/dev/null`";; + esac + + RUBYCCDLFLAGS=`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["CCDLFLAGS"]]') 2>/dev/null` + RUBYSO=.`($RUBY -rrbconfig -e 'print RbConfig::CONFIG[["DLEXT"]]') 2>/dev/null` +else + AC_MSG_RESULT(could not figure out how to run ruby) +fi + +case $host in +*-*-cygwin* | *-*-mingw*) RUBYDYNAMICLINKING="-L$RUBYLIB $RUBYLINK";; +*) RUBYDYNAMICLINKING="";; +esac +fi + +AC_SUBST(RUBYINCLUDE) +AC_SUBST(RUBYLIB) +AC_SUBST(RUBYLINK) +AC_SUBST(RUBYCCDLFLAGS) +AC_SUBST(RUBYSO) +AC_SUBST(RUBYDYNAMICLINKING) + +#---------------------------------------------------------------- +# Look for Scilab +#---------------------------------------------------------------- + +AC_ARG_WITH(scilab, AS_HELP_STRING([--without-scilab], [Disable Scilab]) +AS_HELP_STRING([--with-scilab=path], [Set location of Scilab executable]),[SCILABBIN="$withval"], [SCILABBIN="$alllang_default"]) +AC_ARG_WITH(scilab-inc, [ --with-scilab-inc=path Set location of Scilab include directory], [SCILABINCDIR="$withval"], [SCILABINCDIR=""]) + +# First, check for "--without-scilab" or "--with-scilab=no". +if test x"${SCILABBIN}" = xno; then + AC_MSG_NOTICE([Disabling Scilab]) + SCILAB= +else + # Check for Scilab executable + if test "x$SCILABBIN" = xyes; then + AC_PATH_PROG(SCILAB, scilab) + else + AC_MSG_CHECKING(for scilab) + if test -f "$SCILABBIN"; then + AC_MSG_RESULT($SCILABBIN) + SCILAB="$SCILABBIN" + else + AC_MSG_RESULT(not found) + fi + fi + + if test -n "$SCILAB"; then + # Check for Scilab version (needs api_scilab so needs version 5.3.3 or higher) + SCILAB_VERSION=`$SCILAB -nwni -version | head -1 | sed -e 's|Scilab version \"\(.*\)\"|\1|g'` + + AC_MSG_CHECKING(Scilab version is 5.3.3 or higher) + SCILAB_MAJOR_VERSION=`echo $SCILAB_VERSION | cut -d. -f1` + SCILAB_MINOR_VERSION=`echo $SCILAB_VERSION | cut -d. -f2` + SCILAB_MAINTENANCE_VERSION=`echo $SCILAB_VERSION | cut -d. -f3` + SCILAB_VERSION_NO_DOTS="$SCILAB_MAJOR_VERSION$SCILAB_MINOR_VERSION$SCILAB_MAINTENANCE_VERSION" + + if test -n "$SCILAB_VERSION_NO_DOTS" && test "$SCILAB_VERSION_NO_DOTS" -ge 533; then + AC_MSG_RESULT(yes - $SCILAB_VERSION) + else + AC_MSG_RESULT(no - $SCILAB_VERSION) + SCILAB= + fi + + if test -n "$SCILAB"; then + # Set Scilab startup options depending on version + AC_MSG_CHECKING(for Scilab startup options) + SCILABOPT="-nwni -nb" + if test $SCILAB_VERSION_NO_DOTS -ge 540; then + SCILABOPT+=" -noatomsautoload" + fi + if test $SCILAB_VERSION_NO_DOTS -ge 600; then + SCILABOPT+=" -quit" + fi + AC_MSG_RESULT($SCILABOPT) + + # Check for Scilab header files + AC_MSG_CHECKING(for Scilab header files) + headers="`AS_DIRNAME(["$SCILAB"])`/../include" + if test "$SCILABINCDIR" != ""; then + dirs="$SCILABINCDIR" + elif test -d "$SCI"; then + dirs="$SCI/include $SCI/../../include" + elif test -d "$headers"; then + dirs="$headers" + elif test -n "$PKG_CONFIG "; then + dirs=`$PKG_CONFIG scilab --cflags-only-I | sed -e 's/-I//g'` + else + dirs="/usr/include" + fi + for i in $dirs; do + if test -r $i/api_scilab.h; then + AC_MSG_RESULT($i) + SCILABINCLUDE="-I$i" + break + fi + if test -r $i/scilab/api_scilab.h; then + AC_MSG_RESULT($i/scilab) + SCILABINCLUDE="-I$i/scilab" + break + fi + done + if test "$SCILABINCLUDE" = "" ; then + AC_MSG_RESULT(not found) + SCILAB= fi fi fi fi -AC_SUBST(GOGCC) -AC_SUBST(GCCGO) -AC_SUBST(GO) -AC_SUBST(GOC) -AC_SUBST(GO1) -AC_SUBST(GO12) -AC_SUBST(GO13) -AC_SUBST(GO15) -AC_SUBST(GOOPT) -AC_SUBST(GCCGOOPT) -AC_SUBST(GOVERSIONOPTION) +AC_SUBST(SCILAB) +AC_SUBST(SCILABINCLUDE) +AC_SUBST(SCILABOPT) +AC_SUBST(SCILAB_VERSION) -#---------------------------------------------------------------- -# Look for D -#---------------------------------------------------------------- +#-------------------------------------------------------------------- +# Look for Tcl +#-------------------------------------------------------------------- -AC_ARG_WITH(d, AS_HELP_STRING([--without-d], [Disable D]), [with_d="$withval"], [with_d="$alllang_default"]) -AC_ARG_WITH(d1-compiler, [ --with-d1-compiler=path Set location of D1/Tango compiler (DMD compatible)],[D1COMPILERBIN="$withval"], [D1COMPILERBIN=]) -AC_ARG_WITH(d2-compiler, [ --with-d2-compiler=path Set location of D2 compiler (DMD compatible)],[D2COMPILERBIN="$withval"], [D2COMPILERBIN=]) +TCLINCLUDE= +TCLLIB= +TCLPACKAGE= +TCLLINK= +AC_ARG_WITH(tclconfig, AS_HELP_STRING([--without-tcl], [Disable Tcl]) +AS_HELP_STRING([--with-tclconfig=path], [Set location of tclConfig.sh]), [with_tclconfig="$withval"], [with_tclconfig=]) +AC_ARG_WITH(tcl, + [ --with-tcl=path Set location of Tcl package],[ + TCLPACKAGE="$withval"], [TCLPACKAGE="$alllang_default"]) +AC_ARG_WITH(tclincl,[ --with-tclincl=path Set location of Tcl include directory],[ + TCLINCLUDE="-I$withval"], [TCLINCLUDE=]) +AC_ARG_WITH(tcllib,[ --with-tcllib=path Set location of Tcl library directory],[ + TCLLIB="-L$withval"], [TCLLIB=]) -# First, check for "--without-d" or "--with-d=no". -if test x"${with_d}" = xno; then - AC_MSG_NOTICE([Disabling D]) - D1COMPILER= - D2COMPILER= +# First, check for "--without-tcl" or "--with-tcl=no". +if test x"${TCLPACKAGE}" = xno; then +AC_MSG_NOTICE([Disabling Tcl]) else - old_ac_ext=$ac_ext - ac_ext=d - - if test -z "$D1COMPILERBIN" ; then - AC_CHECK_PROGS(D1COMPILER, dmd ldmd gdmd) - - if test -n "$D1COMPILER" ; then - AC_MSG_CHECKING(whether the D1/Tango compiler works) - cat > conftest.$ac_ext <<_ACEOF -import tango.io.Stdout; -void main() { -} -_ACEOF - rm -f conftest.$ac_objext - AS_IF( - [$D1COMPILER conftest.$ac_ext 2>&AS_MESSAGE_LOG_FD && test ! -s conftest.err && test -s conftest.$ac_objext], - [AC_MSG_RESULT([yes])], - [_AC_MSG_LOG_CONFTEST AC_MSG_RESULT([no]) - D1COMPILER=] - ) - rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi - else - D1COMPILER="$D1COMPILERBIN" - fi - - if test -z "$D2COMPILERBIN" ; then - AC_CHECK_PROGS(D2COMPILER, dmd gdmd ldmd2 ldc2) - - if test -n "$D2COMPILER" ; then - AC_MSG_CHECKING(whether the D2 compiler works) - cat > conftest.$ac_ext <<_ACEOF -import std.algorithm; -void main() { -} -_ACEOF - rm -f conftest.$ac_objext - AS_IF( - [$D2COMPILER conftest.$ac_ext 2>&AS_MESSAGE_LOG_FD && test ! -s conftest.err && test -s conftest.$ac_objext], - [AC_MSG_RESULT([yes])], - [_AC_MSG_LOG_CONFTEST AC_MSG_RESULT([no]) - D2COMPILER=] - ) - rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi - else - D2COMPILER="$D2COMPILERBIN" - fi - - ac_ext=$old_ac_ext +AC_MSG_CHECKING([for Tcl configuration]) +# First check to see if --with-tclconfig was specified. +if test x"${with_tclconfig}" != x ; then + if test -f "${with_tclconfig}/tclConfig.sh" ; then + TCLCONFIG=`(cd ${with_tclconfig}; pwd)` + else + AC_MSG_ERROR([${with_tcl} directory does not contain tclConfig.sh]) + fi fi - -if test -n "$D1COMPILER"; then - DDEFAULTVERSION=1 -elif test -n "$D2COMPILER"; then - DDEFAULTVERSION=2 -fi - -# Do not prefix library file names with "lib" on Windows. +# check in a few common install locations +dirs="/usr/lib*/ /usr/lib*/tcl*/ /usr/local/lib*/ /usr/local/lib*/tcl*/" case $host in -*-*-cygwin* | *-*-mingw*) DLIBPREFIX="";; -*)DLIBPREFIX="lib";; +*-*-darwin*) + tcl_framework="/System/Library/Frameworks/Tcl.framework/" + macos_sysroot="$(xcodebuild -version -sdk macosx Path 2>/dev/null)" # For MacOSX10.14 and later + dirs="$macos_sysroot$tcl_framework $tcl_framework $dirs" + ;; +*) + ;; +esac +if test x"${TCLCONFIG}" = x ; then + for d in $dirs ; do + for i in `ls -d -r $d 2>/dev/null` ; do + if test -f $i"tclConfig.sh" ; then + TCLCONFIG=`(cd $i; pwd)` + break + fi + done + done +fi +if test x"${TCLCONFIG}" = x ; then + AC_MSG_RESULT(no) +else + AC_MSG_RESULT(found $TCLCONFIG/tclConfig.sh) + . $TCLCONFIG/tclConfig.sh + if test -z "$TCLINCLUDE"; then + TCLINCLUDE=`echo $TCL_INCLUDE_SPEC` + fi + if test -z "$TCLLIB"; then + TCLLIB=$TCL_LIB_SPEC + fi +fi + +if test -z "$TCLINCLUDE"; then + if test "x$TCLPACKAGE" != xyes; then + TCLINCLUDE="-I$TCLPACKAGE/include" + fi +fi + +if test -z "$TCLLIB"; then + if test "x$TCLPACKAGE" != xyes; then + TCLLIB="-L$TCLPACKAGE/lib -ltcl" + fi +fi + +AC_MSG_CHECKING(for Tcl header files) +if test -z "$TCLINCLUDE"; then +AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[],[TCLINCLUDE=""]) +if test -z "$TCLINCLUDE"; then + dirs="/usr/local/include /usr/include /opt/local/include" + for i in $dirs ; do + if test -r $i/tcl.h; then + AC_MSG_RESULT($i) + TCLINCLUDE="-I$i" + break + fi + done +fi +if test -z "$TCLINCLUDE"; then + AC_MSG_RESULT(not found) +fi +else + AC_MSG_RESULT($TCLINCLUDE) +fi + +AC_MSG_CHECKING(for Tcl library) +if test -z "$TCLLIB"; then +dirs="/usr/local/lib /usr/lib /opt/local/lib /opt/freeware/lib" +for i in $dirs ; do + if test -r $i/libtcl.a; then + AC_MSG_RESULT($i) + TCLLIB="-L$i -ltcl" + break + fi +done +if test -z "$TCLLIB"; then + AC_MSG_RESULT(not found) +fi +else +AC_MSG_RESULT($TCLLIB) +fi + +# Cygwin (Windows) needs the library for dynamic linking +case $host in +*-*-cygwin* | *-*-mingw*) TCLDYNAMICLINKING="$TCLLIB";; +*-*-aix*) TCLDYNAMICLINKING="$TCLLIB";; +*)TCLDYNAMICLINKING="";; esac -AC_SUBST(D1COMPILER) -AC_SUBST(D2COMPILER) -AC_SUBST(DDEFAULTVERSION) -AC_SUBST(DLIBPREFIX) +# AIX needs -ltcl for linking at test time +case $host in +*-*-aix*) TCLLINK="-ltcl";; +*)TCLLINK="";; +esac + +case $host in +*-*-darwin*) + TCLLDSHARED='$(CC) -dynamiclib -undefined suppress -flat_namespace' + TCLCXXSHARED='$(CXX) -dynamiclib -undefined suppress -flat_namespace' + ;; +*) + TCLLDSHARED='$(LDSHARED)' + TCLCXXSHARED='$(CXXSHARED)' + ;; +esac + +fi + +AC_SUBST(TCLINCLUDE) +AC_SUBST(TCLLIB) +AC_SUBST(TCLDYNAMICLINKING) +AC_SUBST(TCLLDSHARED) +AC_SUBST(TCLCXXSHARED) +AC_SUBST(TCLLINK) #---------------------------------------------------------------- # Determine which languages to use for examples/test-suite #---------------------------------------------------------------- -SKIP_TCL= -if test -z "$TCLINCLUDE" || test -z "$TCLLIB" ; then - SKIP_TCL="1" -fi -AC_SUBST(SKIP_TCL) - - -SKIP_PERL5= -if test -z "$PERL" || test -z "$PERL5EXT" || test -z "$PERL5TESTMORE"; then - SKIP_PERL5="1" -fi -AC_SUBST(SKIP_PERL5) - - -SKIP_OCTAVE= -if test -z "$OCTAVE" ; then - SKIP_OCTAVE="1" -fi -AC_SUBST(SKIP_OCTAVE) - - -SKIP_PYTHON= -if (test -z "$PYINCLUDE" || test -z "$PYLINK") && - (test -z "$PY3INCLUDE" || test -z "$PY3LINK") ; then - SKIP_PYTHON="1" -fi -AC_SUBST(SKIP_PYTHON) - -SKIP_PYTHON3= -if test -z "$PY3INCLUDE" || test -z "$PY3LINK" ; then - SKIP_PYTHON3="1" -fi -AC_SUBST(SKIP_PYTHON3) - -SKIP_JAVA= -if test -z "$JAVA" || test -z "$JAVAC" || test -z "$JAVAINC" ; then - SKIP_JAVA="1" -fi -AC_SUBST(SKIP_JAVA) - -SKIP_JAVASCRIPT= -if test -z "$JAVASCRIPT" || ( test -z "$NODEJS" && test -z "$JSCENABLED" && test -z "$JSV8ENABLED" ) ; then - SKIP_JAVASCRIPT="1" -fi -AC_SUBST(SKIP_JAVASCRIPT) - -SKIP_GUILE= -if test -z "$GUILE" || test -z "$GUILE_LIBS" ; then - SKIP_GUILE="1" -fi -AC_SUBST(SKIP_GUILE) - - -SKIP_MZSCHEME= -if test -z "$MZC" || test -z "$MZDYNOBJ" ; then - SKIP_MZSCHEME="1" -fi -AC_SUBST(SKIP_MZSCHEME) - - -SKIP_RUBY= -if test -z "$RUBY" || test -z "$RUBYINCLUDE" || test -z "$RUBYLIB" ; then - SKIP_RUBY="1" -fi -AC_SUBST(SKIP_RUBY) - - -SKIP_PHP= -if test -z "$PHP" || test -z "$PHPINC" ; then - SKIP_PHP="1" -fi -AC_SUBST(SKIP_PHP) - - -SKIP_OCAML= -if test -z "$OCAMLC" || test -z "$CAMLP4" ; then - SKIP_OCAML="1" -fi -AC_SUBST(SKIP_OCAML) - - SKIP_CSHARP= if test -z "$CSHARPCOMPILER" ; then SKIP_CSHARP="1" @@ -2722,24 +2640,13 @@ else fi AC_SUBST(SKIP_CSHARP) -SKIP_LUA= -# we need LUABIN & dynamic loading -if test -z "$LUABIN" || test -z "$LUADYNAMICLOADLIB"; then - SKIP_LUA="1" -fi -AC_SUBST(SKIP_LUA) -SKIP_R= -if test -z "$RBIN" ; then - SKIP_R="1" +SKIP_D= +if test -z "$DDEFAULTVERSION" ; then + SKIP_D="1" fi -AC_SUBST(SKIP_R) +AC_SUBST(SKIP_D) -SKIP_SCILAB= -if test -z "$SCILAB"; then - SKIP_SCILAB="1" -fi -AC_SUBST(SKIP_SCILAB) SKIP_GO= if test -z "$GO" ; then @@ -2747,11 +2654,112 @@ if test -z "$GO" ; then fi AC_SUBST(SKIP_GO) -SKIP_D= -if test -z "$DDEFAULTVERSION" ; then - SKIP_D="1" + +SKIP_GUILE= +if test -z "$GUILE" || test -z "$GUILE_LIBS" ; then + SKIP_GUILE="1" fi -AC_SUBST(SKIP_D) +AC_SUBST(SKIP_GUILE) + +SKIP_JAVA= +if test -z "$JAVA" || test -z "$JAVAC" || test -z "$JAVAINC" ; then + SKIP_JAVA="1" +fi +AC_SUBST(SKIP_JAVA) + + +SKIP_JAVASCRIPT= +if test -z "$JAVASCRIPT" || ( test -z "$NODEJS" && test -z "$JSCENABLED" && test -z "$JSV8ENABLED" ) ; then + SKIP_JAVASCRIPT="1" +fi +AC_SUBST(SKIP_JAVASCRIPT) + + +SKIP_LUA= +# we need LUABIN & dynamic loading +if test -z "$LUABIN" || test -z "$LUADYNAMICLOADLIB"; then + SKIP_LUA="1" +fi +AC_SUBST(SKIP_LUA) + + +SKIP_MZSCHEME= +if test -z "$MZC" || test -z "$MZDYNOBJ" ; then + SKIP_MZSCHEME="1" +fi +AC_SUBST(SKIP_MZSCHEME) + + +SKIP_OCAML= +if test -z "$OCAMLC" || test -z "$CAMLP4" ; then + SKIP_OCAML="1" +fi +AC_SUBST(SKIP_OCAML) + + +SKIP_OCTAVE= +if test -z "$OCTAVE" ; then + SKIP_OCTAVE="1" +fi +AC_SUBST(SKIP_OCTAVE) + + +SKIP_PHP= +if test -z "$PHP" || test -z "$PHPINC" ; then + SKIP_PHP="1" +fi +AC_SUBST(SKIP_PHP) + + +SKIP_PERL5= +if test -z "$PERL" || test -z "$PERL5EXT" || test -z "$PERL5TESTMORE"; then + SKIP_PERL5="1" +fi +AC_SUBST(SKIP_PERL5) + + +SKIP_PYTHON= +if (test -z "$PYINCLUDE" || test -z "$PYLINK") && + (test -z "$PY3INCLUDE" || test -z "$PY3LINK") ; then + SKIP_PYTHON="1" +fi +AC_SUBST(SKIP_PYTHON) + + +SKIP_PYTHON3= +if test -z "$PY3INCLUDE" || test -z "$PY3LINK" ; then + SKIP_PYTHON3="1" +fi +AC_SUBST(SKIP_PYTHON3) + + +SKIP_R= +if test -z "$RBIN" ; then + SKIP_R="1" +fi +AC_SUBST(SKIP_R) + + +SKIP_RUBY= +if test -z "$RUBY" || test -z "$RUBYINCLUDE" || test -z "$RUBYLIB" ; then + SKIP_RUBY="1" +fi +AC_SUBST(SKIP_RUBY) + + +SKIP_SCILAB= +if test -z "$SCILAB"; then + SKIP_SCILAB="1" +fi +AC_SUBST(SKIP_SCILAB) + + +SKIP_TCL= +if test -z "$TCLINCLUDE" || test -z "$TCLLIB" ; then + SKIP_TCL="1" +fi +AC_SUBST(SKIP_TCL) + #---------------------------------------------------------------- # Additional language dependencies @@ -2843,21 +2851,21 @@ AC_CONFIG_FILES([ Examples/test-suite/errors/Makefile Examples/test-suite/csharp/Makefile Examples/test-suite/d/Makefile + Examples/test-suite/go/Makefile Examples/test-suite/guile/Makefile Examples/test-suite/java/Makefile Examples/test-suite/javascript/Makefile + Examples/test-suite/lua/Makefile Examples/test-suite/mzscheme/Makefile Examples/test-suite/ocaml/Makefile Examples/test-suite/octave/Makefile Examples/test-suite/perl5/Makefile Examples/test-suite/php/Makefile Examples/test-suite/python/Makefile + Examples/test-suite/r/Makefile Examples/test-suite/ruby/Makefile Examples/test-suite/scilab/Makefile Examples/test-suite/tcl/Makefile - Examples/test-suite/lua/Makefile - Examples/test-suite/r/Makefile - Examples/test-suite/go/Makefile Source/Makefile Tools/javascript/Makefile ]) From 7b0f7caaf2c4d8e863b38a88099ea9dd7e3df0e5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 6 Oct 2022 22:48:35 +0100 Subject: [PATCH 072/217] Makefile re-order All target languages are in now in alphabetical order --- Examples/Makefile.in | 1609 +++++++++++++++++++++--------------------- Makefile.in | 164 ++--- 2 files changed, 886 insertions(+), 887 deletions(-) diff --git a/Examples/Makefile.in b/Examples/Makefile.in index fc33ead8b..28c87862c 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -148,347 +148,413 @@ swiginvoke: $(SWIG) $(SWIGOPT) ################################################################## -##### Tcl/Tk ###### +##### ANDROID ###### ################################################################## -# Set these to your local copy of Tcl/Tk. +ANDROID = @ANDROID@ +ANDROID_NDK_BUILD = @NDKBUILD@ +ANDROID_ADB = @ADB@ +ANT = @ANT@ +TARGETID = 1 -TCLSH = tclsh -TCL_INCLUDE = @TCLINCLUDE@ -TCL_LIB = @TCLLIB@ -TCL_OPTS = @LIBS@ -TK_OPTS = -ltk -ltcl @LIBS@ +# ---------------------------------------------------------------- +# Build an Android dynamically loadable module (C) +# ---------------------------------------------------------------- -# Extra Tcl specific dynamic linking options -TCL_DLNK = @TCLDYNAMICLINKING@ -TCL_SO = @TCL_SO@ -TCLLDSHARED = @TCLLDSHARED@ -TCLCXXSHARED = @TCLCXXSHARED@ -TCL_SCRIPT = $(SRCDIR)$(RUNME).tcl -TCL_LINK = @TCLLINK@ +android: $(SRCDIR_SRCS) + $(ANDROID) $(SILENT_OPTION) update project --target $(TARGETID) --name $(PROJECTNAME) --path . + $(SWIG) -java $(SWIGOPT) -o $(INTERFACEDIR)$(TARGET)_wrap.c $(INTERFACEPATH) + +$(ANDROID_NDK_BUILD) $(SILENT_PIPE) + $(ANT) $(ANT_QUIET) debug -# ----------------------------------------------------------- -# Build a new version of the tclsh shell -# ----------------------------------------------------------- +# ---------------------------------------------------------------- +# Build an Android dynamically loadable module (C++) +# ---------------------------------------------------------------- -tclsh: $(SRCDIR_SRCS) - $(SWIG) -tcl8 $(SWIGOPT) $(TCL_SWIGOPTS) -ltclsh.i -o $(ISRCS) $(INTERFACEPATH) - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(TCL_INCLUDE) \ - $(TCL_LIB) $(TCL_OPTS) $(LIBS) $(SYSLIBS) -o $(TARGET) +android_cpp: $(SRCDIR_SRCS) + $(ANDROID) $(SILENT_OPTION) update project --target $(TARGETID) --name $(PROJECTNAME) --path . + $(SWIG) -java -c++ $(SWIGOPT) -o $(INTERFACEDIR)$(TARGET)_wrap.cpp $(INTERFACEPATH) + +$(ANDROID_NDK_BUILD) $(SILENT_PIPE) + $(ANT) $(ANT_QUIET) debug -tclsh_cpp: $(SRCDIR_SRCS) - $(SWIG) -tcl8 -c++ $(SWIGOPT) $(TCL_SWIGOPTS) -ltclsh.i -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(TCL_INCLUDE) \ - $(TCL_LIB) $(TCL_OPTS) $(LIBS) $(SYSLIBS) -o $(TARGET) +# ---------------------------------------------------------------- +# Android install +# ---------------------------------------------------------------- -# ----------------------------------------------------------- -# Build a Tcl dynamic loadable module (you might need to tweak this) -# ----------------------------------------------------------- - -tcl: $(SRCDIR_SRCS) - $(SWIG) -tcl8 $(SWIGOPT) $(TCL_SWIGOPTS) -o $(ISRCS) $(INTERFACEPATH) - $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(TCL_INCLUDE) - $(TCLLDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(TCL_DLNK) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(TCL_SO) $(TCL_LINK) - -# ----------------------------------------------------------- -# Build a Tcl dynamic loadable module for C++ -# ----------------------------------------------------------- - -tcl_cpp: $(SRCDIR_SRCS) - $(SWIG) -tcl8 -c++ $(SWIGOPT) $(TCL_SWIGOPTS) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(TCL_INCLUDE) - $(TCLCXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(TCL_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(TCL_SO) $(TCL_LINK) - -# ----------------------------------------------------------------- -# Run Tcl example -# ----------------------------------------------------------------- - -tcl_run: - $(RUNTOOL) $(TCLSH) $(TCL_SCRIPT) $(RUNPIPE) +android_install: + -$(ANDROID_ADB) uninstall $(PACKAGENAME) + $(ANDROID_ADB) install $(INSTALLOPTIONS) bin/$(PROJECTNAME)-debug.apk # ----------------------------------------------------------------- # Version display # ----------------------------------------------------------------- -tcl_version: - echo 'puts $$tcl_version;exit 0' | $(TCLSH) +android_version: + $(ANDROID_ADB) version # ----------------------------------------------------------------- -# Cleaning the Tcl examples +# Cleaning the Android examples # ----------------------------------------------------------------- -tcl_clean: - rm -f *_wrap* *~ .~* mytclsh@EXEEXT@ - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *$(TCL_SO) +android_clean: + test -n "$(SRCDIR)" && cd $(SRCDIR) ; $(ANT) -q -logfile /dev/null clean + rm -f $(INTERFACEDIR)$(TARGET)_wrap.* + rm -f `find $(PACKAGEDIR) -name \*.java | grep -v $(PROJECTNAME).java` + rm -rf obj ################################################################## -##### PERL 5 ###### +##### CFFI ###### ################################################################## -# You need to set this variable to the Perl5 directory containing the -# files "perl.h", "EXTERN.h" and "XSUB.h". With Perl5.003, it's -# usually something like /usr/local/lib/perl5/arch-osname/5.003/CORE. +CFFI = @CFFIBIN@ +CFFI_SCRIPT=$(RUNME).lisp -PERL5_INCLUDE= @PERL5EXT@ +cffi: $(SRCDIR_SRCS) + $(SWIG) -cffi $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) +# $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCDIR_SRCS) +# $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) -# Extra Perl specific dynamic linking options -PERL5_DLNK = @PERL5DYNAMICLINKING@ -PERL5_CCFLAGS = @PERL5CCFLAGS@ -PERL5_CCDLFLAGS = @PERL5CCDLFLAGS@ -PERL5_CCCDLFLAGS = @PERL5CCCDLFLAGS@ -PERL5_LDFLAGS = @PERL5LDFLAGS@ -PERL = @PERL@ -PERL5_LIB = -L$(PERL5_INCLUDE) -l@PERL5LIB@ @LIBS@ $(SYSLIBS) -PERL5_SCRIPT = $(SRCDIR)$(RUNME).pl - -# ---------------------------------------------------------------- -# Build a Perl5 dynamically loadable module (C) -# ---------------------------------------------------------------- - -perl5: $(SRCDIR_SRCS) - $(SWIG) -perl5 $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(CC) -c -Dbool=char $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(PERL5_CCFLAGS) $(PERL5_CCCDLFLAGS) -I$(PERL5_INCLUDE) - $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(PERL5_CCDLFLAGS) $(OBJS) $(IOBJS) $(PERL5_LDFLAGS) $(PERL5_DLNK) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) - -# ---------------------------------------------------------------- -# Build a Perl5 dynamically loadable module (C++) -# ---------------------------------------------------------------- - -perl5_cpp: $(SRCDIR_SRCS) - $(SWIG) -perl5 -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(PERL5_CCFLAGS) $(PERL5_CCCDLFLAGS) -I$(PERL5_INCLUDE) - $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(PERL5_CCDLFLAGS) $(OBJS) $(IOBJS) $(PERL5_LDFLAGS) $(PERL5_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) - -# ---------------------------------------------------------------- -# Build a module from existing XS C source code. (ie. from xsubpp). -# ---------------------------------------------------------------- -perl5_xs: $(SRCDIR_SRCS) - $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(INCLUDES) -I$(PERL5_INCLUDE) - $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $(TARGET)$(SO) - -# ---------------------------------------------------------------- -# Build a statically linked Perl5 executable -# ---------------------------------------------------------------- - -perl5_static: $(SRCDIR_SRCS) - $(SWIG) -perl5 -static -lperlmain.i $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Dbool=char $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) -I$(PERL5_INCLUDE) $(PERL5_LIB) $(LIBS) -o $(TARGET) - -perl5_static_cpp: $(SRCDIR_SRCS) - $(SWIG) -perl5 -c++ -static -lperlmain.i $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) -I$(PERL5_INCLUDE) $(PERL5_LIB) $(LIBS) -o $(TARGET) +cffi_cpp: $(SRCDIR_SRCS) + $(SWIG) -c++ -cffi $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) + $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) # ----------------------------------------------------------------- -# Running a Perl5 example +# Run CFFI example # ----------------------------------------------------------------- -perl5_run: - $(RUNTOOL) $(PERL) -I. $(PERL5_SCRIPT) $(RUNPIPE) +cffi_run: + $(RUNTOOL) $(CFFI) -batch -s $(CFFI_SCRIPT) $(RUNPIPE) # ----------------------------------------------------------------- # Version display # ----------------------------------------------------------------- -perl5_version: - $(PERL) -v | grep "This is" +cffi_version: + $(CFFI) --version # ----------------------------------------------------------------- -# Cleaning the Perl5 examples +# Cleaning the CFFI examples # ----------------------------------------------------------------- -perl5_clean: - rm -f *_wrap* *~ .~* myperl@EXEEXT@ *.pm +cffi_clean: + rm -f *_wrap* *~ .~* rm -f core @EXTRA_CLEAN@ rm -f *.@OBJEXT@ *@SO@ ################################################################## -##### PYTHON ###### +##### CSHARP ###### ################################################################## -PYTHON_FLAGS = - -# Make sure these locate your Python installation -ifneq (,$(PY2)) - PYTHON_INCLUDE= $(DEFS) @PYINCLUDE@ - PYTHON_LIB = @PYLIB@ - PYTHON = @PYTHON@ $(PYTHON_FLAGS) -else - PYTHON_INCLUDE= $(DEFS) @PY3INCLUDE@ - PYTHON_LIB = @PY3LIB@ - PYTHON = @PYTHON3@ $(PYTHON_FLAGS) -endif - -# Extra Python specific linking options -ifneq (,$(PY2)) - PYTHON_DLNK = @PYTHONDYNAMICLINKING@ - PYTHON_LINK = @PYLINK@ -else - PYTHON_DLNK = @PYTHON3DYNAMICLINKING@ - PYTHON_LINK = @PY3LINK@ -endif -PYTHON_SO = @PYTHON_SO@ - -PYCODESTYLE = @PYCODESTYLE@ -PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,W291,W391 +# Extra CSharp specific dynamic linking options +CSHARP_DLNK = @CSHARPDYNAMICLINKING@ +CSHARP_LIBPREFIX = @CSHARPLIBRARYPREFIX@ +CSHARPCOMPILER = @CSHARPCOMPILER@ +CSHARPCILINTERPRETER = @CSHARPCILINTERPRETER@ +CSHARPCILINTERPRETER_FLAGS = @CSHARPCILINTERPRETER_FLAGS@ +CSHARPCFLAGS = @CSHARPCFLAGS@ +CSHARPFLAGS = +CSHARPOPTIONS = +CSHARPSO = @CSHARPSO@ +CSHARP_RUNME = ./$(RUNME).exe # ---------------------------------------------------------------- -# Build a C dynamically loadable module +# Build a CSharp dynamically loadable module (C) # ---------------------------------------------------------------- -python: $(SRCDIR_SRCS) - $(SWIG) -python $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) $(PYTHON_INCLUDE) - $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(PYTHON_DLNK) $(LIBS) -o $(LIBPREFIX)_$(TARGET)$(PYTHON_SO) +csharp: $(SRCDIR_SRCS) + $(SWIG) -csharp $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(CSHARPCFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) + $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(CSHARP_DLNK) $(LIBS) -o $(CSHARP_LIBPREFIX)$(TARGET)$(CSHARPSO) -# ----------------------------------------------------------------- -# Build a C++ dynamically loadable module -# ----------------------------------------------------------------- +# ---------------------------------------------------------------- +# Build a CSharp dynamically loadable module (C++) +# ---------------------------------------------------------------- -python_cpp: $(SRCDIR_SRCS) - $(SWIG) -python -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) $(PYTHON_INCLUDE) - $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(PYTHON_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)_$(TARGET)$(PYTHON_SO) +csharp_cpp: $(SRCDIR_SRCS) + $(SWIG) -csharp -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(CSHARPCFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) + $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(CSHARP_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(CSHARP_LIBPREFIX)$(TARGET)$(CSHARPSO) -# ----------------------------------------------------------------- -# Build statically linked Python interpreter -# -# These should only be used in conjunction with the %include embed.i -# library file -# ----------------------------------------------------------------- - -#TKINTER = -L/usr/X11R6.3/lib -L/usr/local/compat/lib -ltk4.0 -ltcl7.4 -lX11 -TKINTER = -PYTHON_LIBOPTS = $(PYTHON_LINK) @LIBS@ $(TKINTER) $(SYSLIBS) - -python_static: $(SRCDIR_SRCS) - $(SWIG) -python -lembed.i $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) @LINKFORSHARED@ $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) \ - $(PYTHON_INCLUDE) $(LIBS) -L$(PYTHON_LIB) $(PYTHON_LIBOPTS) -o $(TARGET) - -python_static_cpp: $(SRCDIR_SRCS) - $(SWIG) -python -c++ -lembed.i $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) \ - $(PYTHON_INCLUDE) $(LIBS) -L$(PYTHON_LIB) $(PYTHON_LIBOPTS) -o $(TARGET) - -# ----------------------------------------------------------------- -# Running a Python example -# ----------------------------------------------------------------- - -PYSCRIPT = $(RUNME).py - -python_run: $(PYSCRIPT) -ifneq (,$(PYCODESTYLE)) - $(COMPILETOOL) $(PYCODESTYLE) $(PYCODESTYLE_FLAGS) $(PYSCRIPT) -endif - env PYTHONPATH=$$PWD $(RUNTOOL) $(PYTHON) $(PYSCRIPT) $(RUNPIPE) +# ---------------------------------------------------------------- +# Compile CSharp files +# ---------------------------------------------------------------- ifneq (,$(SRCDIR)) -$(RUNME).py: $(SRCDIR)$(RUNME).py - cp $< $@ +SRCDIR_CSHARPSRCS = $(addprefix $(SRCDIR),$(CSHARPSRCS)) +else +SRCDIR_CSHARPSRCS = endif +csharp_compile: $(SRCDIR_SRCS) + $(COMPILETOOL) $(CSHARPCOMPILER) $(CSHARPFLAGS) $(CSHARPOPTIONS) $(CSHARPSRCS) $(SRCDIR_CSHARPSRCS) + +# ----------------------------------------------------------------- +# Run CSharp example +# ----------------------------------------------------------------- + +csharp_run: + env LD_LIBRARY_PATH=$$PWD $(RUNTOOL) $(CSHARPCILINTERPRETER) $(CSHARPCILINTERPRETER_FLAGS) $(CSHARP_RUNME) $(RUNPIPE) + # ----------------------------------------------------------------- # Version display # ----------------------------------------------------------------- -python_version: - $(PYTHON) -V +# Version check below also works with MS csc.exe which does not understand --version +csharp_version: + $(CSHARPCOMPILER) --version | head -n 1 + if test -n "$(CSHARPCILINTERPRETER)" ; then "$(CSHARPCILINTERPRETER)" --version ; fi # ----------------------------------------------------------------- -# Cleaning the python examples +# Cleaning the CSharp examples # ----------------------------------------------------------------- -python_clean: - rm -rf __pycache__ - rm -f *_wrap* *~ .~* mypython@EXEEXT@ *.pyc +csharp_clean: + rm -f *_wrap* *~ .~* $(RUNME) $(RUNME).exe *.exe.mdb gc.log `find . -name \*.cs | grep -v $(RUNME).cs` rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@SO@ *$(PYTHON_SO) - rm -f $(TARGET).py - case "x$(SRCDIR)" in x|x./);; *) rm -f $(RUNME).py;; esac - + rm -f *.@OBJEXT@ *@CSHARPSO@ ################################################################## -##### OCTAVE ###### +##### D ###### ################################################################## -# Make sure these locate your Octave installation -OCTAVE = @OCTAVE@ -OCTAVE_CXX = $(DEFS) @OCTAVE_CPPFLAGS@ @OCTAVE_CXXFLAGS@ +DLIBPREFIX = @DLIBPREFIX@ -# Extra Octave specific dynamic linking options -OCTAVE_DLNK = @OCTAVE_LDFLAGS@ -OCTAVE_SO = @OCTAVE_SO@ +ifeq (,$(D_VERSION)) + D_VERSION = @DDEFAULTVERSION@ +endif -OCTAVE_SCRIPT = $(SRCDIR)$(RUNME).m +ifeq (2,$(D_VERSION)) + SWIGD = $(SWIG) -d -d2 + DCOMPILER = @D2COMPILER@ +else + SWIGD = $(SWIG) -d + DCOMPILER = @D1COMPILER@ +endif + +D_RUNME = ./$(RUNME) # ---------------------------------------------------------------- -# Pre-compile Octave headers, if supported +# Build a dynamically loadable D wrapper for a C module # ---------------------------------------------------------------- -ifeq (yes,$(PCHSUPPORT)) +d: $(SRCDIR_SRCS) + $(SWIGD) $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(DCFLAGS) $(EXTRA_CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) + $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(DCFLAGS) $(EXTRA_LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(DLIBPREFIX)$(TARGET)$(SO) -octave_precompile_headers: - echo "precompiling $(OCTHEADERS)" - cp -f $(OCTHEADERSSRC) $(OCTHEADERS) - if $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) $(OCTAVE_CXX) $(OCTHEADERS); then \ - : ; \ - else \ - rm -f $(OCTHEADERSGCH); \ - exit 1; \ +# ---------------------------------------------------------------- +# Build a dynamically loadable D wrapper for a C++ module +# ---------------------------------------------------------------- + +d_cpp: $(SRCDIR_SRCS) + $(SWIGD) -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(DCFLAGS) $(EXTRA_CFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) + $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(DCFLAGS) $(EXTRA_LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(DLIBPREFIX)$(TARGET)$(SO) + +# ---------------------------------------------------------------- +# Compile D files +# ---------------------------------------------------------------- + +# Clear the DFLAGS environment variable for the compiler call itself +# to work around a discrepancy in argument handling between DMD and LDC. +d_compile: $(SRCDIR_SRCS) + DFLAGS="" $(COMPILETOOL) $(DCOMPILER) $(DFLAGS) $(DSRCS) + +# ----------------------------------------------------------------- +# Run D example +# ----------------------------------------------------------------- + +d_run: + env LD_LIBRARY_PATH=$$PWD $(RUNTOOL) $(D_RUNME) $(RUNPIPE) + +# ----------------------------------------------------------------- +# Version display +# ----------------------------------------------------------------- + +d_version: + ($(DCOMPILER) --version 2> /dev/null || $(DCOMPILER)) | head -n 3 + +# ----------------------------------------------------------------- +# Clean the D examples +# ----------------------------------------------------------------- + +d_clean: + rm -f *_wrap* *~ .~* $(RUNME) $(RUNME).exe `find . -name \*.d | grep -v $(RUNME).d` + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *@SO@ + +################################################################## +##### Go ###### +################################################################## + +# TODO: The Go make targets need simplifying to use configure time +# configuration or to use Make's ifeq rather than using lots of +# runtime shell code. The output will then be a lot less verbose. + +GO = @GO@ +GOGCC = @GOGCC@ +GCCGO = @GCCGO@ +GOOPT = @GOOPT@ +GCCGOOPT = @GCCGOOPT@ +GOVERSIONOPTION = @GOVERSIONOPTION@ + +GOSWIGARG = `if $(GOGCC) ; then echo -gccgo; fi` + +GOSRCS = $(INTERFACE:.i=.go) +GOCSRCS = $(INTERFACE:.i=_gc.c) + +GOPACKAGE = $(notdir $(INTERFACE:.i=.a)) + +GOPATHPARENTDIR = gopath/$(GOMOD)/src +GOPATHDIR = $(GOPATHPARENTDIR)/$(INTERFACE:.i=) + +# ---------------------------------------------------------------- +# Build a Go module (C) +# ---------------------------------------------------------------- + +$(GOPATHPARENTDIR)/go.mod: + @mkdir gopath 2>/dev/null || true + @mkdir gopath/$(GOMOD) 2>/dev/null || true + @mkdir gopath/$(GOMOD)/src 2>/dev/null || true + @mkdir $(GOPATHDIR) 2>/dev/null || true + echo "module swigtests" > $(GOPATHDIR)/go.mod + echo "" >> $(GOPATHDIR)/go.mod + echo "go 1.12" >> $(GOPATHDIR)/go.mod + mv -f $(GOPATHDIR)/go.mod $(GOPATHPARENTDIR)/go.mod + +go: $(SRCDIR_SRCS) $(GOPATHPARENTDIR)/go.mod + $(SWIG) -go -import-prefix swigtests $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + @mkdir gopath 2>/dev/null || true + @mkdir gopath/$(GOMOD) 2>/dev/null || true + @mkdir gopath/$(GOMOD)/src 2>/dev/null || true + @mkdir $(GOPATHDIR) 2>/dev/null || true + rm -rf $(GOPATHDIR)/* + cp $(ISRCS) $(GOPATHDIR)/ + if test -f $(IWRAP:.i=.h); then \ + cp $(IWRAP:.i=.h) $(GOPATHDIR)/; \ + fi + if test -n "$(SRCDIR_SRCS)"; then \ + cp $(SRCDIR_SRCS) $(GOPATHDIR)/; \ + fi + cp $(GOSRCS) $(GOPATHDIR)/ + @if test -f $(SRCDIR)$(RUNME).go; then \ + mkdir gopath/$(GOMOD)/src/runme 2>/dev/null || true; \ + rm -f gopath/$(GOMOD)/src/runme/*; \ + fi + if test -f $(SRCDIR)$(RUNME).go; then \ + cp $(SRCDIR)$(RUNME).go gopath/$(GOMOD)/src/runme/; \ + fi + GOPATH=`pwd`/gopath/$(GOMOD); \ + export GOPATH; \ + CGO_CPPFLAGS="$(CPPFLAGS) $(INCLUDES) -I `cd $(SRCDIR) && pwd` -I `pwd`"; \ + export CGO_CPPFLAGS; \ + CGO_CFLAGS="$(CFLAGS)"; \ + export CGO_CFLAGS; \ + CGO_LDFLAGS="$(LDFLAGS) -lm"; \ + export CGO_LDFLAGS; \ + (cd $(GOPATHDIR)/ && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o $(GOPACKAGE)); \ + stat=$$?; \ + if test $$stat != 0; then \ + exit $$stat; \ + fi; \ + if $(GOGCC); then \ + cp $(GOPATHDIR)/$(GOPACKAGE) $(GOPATHDIR)/$(GOPACKAGE:.a=.gox); \ + fi; \ + if test -f $(SRCDIR)$(RUNME).go; then \ + mkdir gopath/$(GOMOD)/src/swigtests 2>/dev/null || true; \ + mkdir gopath/$(GOMOD)/src/swigtests/$(INTERFACE:.i=) 2>/dev/null || true; \ + cp $(GOPATHDIR)/* gopath/$(GOMOD)/src/swigtests/$(INTERFACE:.i=)/; \ + (cd gopath/$(GOMOD)/src/runme && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o runme $(RUNME).go); \ + stat=$$?; \ + if test $$stat != 0; then \ + exit $$stat; \ + fi; \ + cp gopath/$(GOMOD)/src/runme/runme $(RUNME); \ fi -else - -octave_precompile_headers: - echo "precompiling Octave headers not supported"; exit 1 - -endif - # ---------------------------------------------------------------- -# Build a C dynamically loadable module -# Note: Octave requires C++ compiler when compiling C wrappers +# Build a Go module (C++) # ---------------------------------------------------------------- -octave: $(SRCDIR_SRCS) - $(SWIG) -octave $(SWIGOCTHDROPT) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -g -c $(IOCTHEADERS) $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(INCLUDES) $(OCTAVE_CXX) - $(CC) -g -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CSRCS) $(INCLUDES) - $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(OCTAVE_DLNK) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(OCTAVE_SO) +go_cpp: $(SRCDIR_SRCS) $(GOPATHPARENTDIR)/go.mod + $(SWIG) -go -c++ -import-prefix swigtests $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + @mkdir gopath 2>/dev/null || true + @mkdir gopath/$(GOMOD) 2>/dev/null || true + @mkdir gopath/$(GOMOD)/src 2>/dev/null || true + @mkdir $(GOPATHDIR) 2>/dev/null || true + rm -rf $(GOPATHDIR)/* + cp $(ICXXSRCS) $(GOPATHDIR)/ + if test -f $(IWRAP:.i=.h); then \ + cp $(IWRAP:.i=.h) $(GOPATHDIR)/; \ + fi + if test -n "$(SRCDIR_CXXSRCS)"; then \ + cp $(SRCDIR_CXXSRCS) $(GOPATHDIR)/; \ + fi + if test -n "$(SRCDIR_SRCS)"; then \ + cp $(SRCDIR_SRCS) $(GOPATHDIR)/; \ + fi + cp $(GOSRCS) $(GOPATHDIR)/ + @if test -f $(SRCDIR)$(RUNME).go; then \ + mkdir gopath/$(GOMOD)/src/runme 2>/dev/null || true; \ + rm -f gopath/$(GOMOD)/src/runme/*; \ + fi + if test -f $(SRCDIR)$(RUNME).go; then \ + cp $(SRCDIR)$(RUNME).go gopath/$(GOMOD)/src/runme/; \ + fi + GOPATH=`pwd`/gopath/$(GOMOD); \ + export GOPATH; \ + CGO_CPPFLAGS="$(CPPFLAGS) $(INCLUDES) -I `cd $(SRCDIR) && pwd` -I `pwd`"; \ + export CGO_CPPFLAGS; \ + CGO_CFLAGS="$(CFLAGS)"; \ + export CGO_CFLAGS; \ + CGO_CXXFLAGS="$(CXXFLAGS)"; \ + export CGO_CXXFLAGS; \ + CGO_LDFLAGS="$(LDFLAGS) -lm"; \ + export CGO_LDFLAGS; \ + (cd $(GOPATHDIR) && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o $(GOPACKAGE)); \ + stat=$$?; \ + if test $$stat != 0; then \ + exit $$stat; \ + fi; \ + if $(GOGCC); then \ + cp $(GOPATHDIR)/$(GOPACKAGE) $(GOPATHDIR)/$(GOPACKAGE:.a=.gox); \ + fi; \ + if test -f $(SRCDIR)$(RUNME).go; then \ + mkdir gopath/$(GOMOD)/src/swigtests 2>/dev/null || true; \ + mkdir gopath/$(GOMOD)/src/swigtests/$(INTERFACE:.i=) 2>/dev/null || true; \ + cp $(GOPATHDIR)/* gopath/$(GOMOD)/src/swigtests/$(INTERFACE:.i=)/; \ + (cd gopath/$(GOMOD)/src/runme && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o runme $(RUNME).go); \ + stat=$$?; \ + if test $$stat != 0; then \ + exit $$stat; \ + fi; \ + cp gopath/$(GOMOD)/src/runme/runme $(RUNME); \ + fi # ----------------------------------------------------------------- -# Build a C++ dynamically loadable module +# Running Go example # ----------------------------------------------------------------- -octave_cpp: $(SRCDIR_SRCS) - $(SWIG) -c++ -octave $(SWIGOCTHDROPT) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -g -c $(IOCTHEADERS) $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) $(OCTAVE_CXX) - $(CXXSHARED) -g $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(OCTAVE_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(OCTAVE_SO) - -# ----------------------------------------------------------------- -# Running an Octave example -# ----------------------------------------------------------------- - -octave_run: - env OCTAVE_PATH= OCTAVE_HISTFILE=/dev/null $(RUNTOOL) $(OCTAVE) $(OCTAVE_SCRIPT) $(RUNPIPE) +go_run: + env $(RUNTOOL) ./$(RUNME) $(RUNPIPE) # ----------------------------------------------------------------- # Version display # ----------------------------------------------------------------- -octave_version: - $(OCTAVE) --version | head -n 1 +go_version: + $(GO) $(GOVERSIONOPTION) # ----------------------------------------------------------------- -# Cleaning the Octave examples +# Cleaning the Go examples # ----------------------------------------------------------------- -octave_clean: - rm -rf __pycache__ - rm -f *_wrap* *~ .~* myoctave@EXEEXT@ *.pyc +go_clean: + rm -f *_wrap* *_gc* *.gox .~* $(RUNME) $(GOSRCS) + rm -rf gopath rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@SO@ *$(OCTAVE_SO) - rm -f $(OCTHEADERS) $(OCTHEADERSGCH) + rm -f *.@OBJEXT@ *.[568] *.a *@SO@ ################################################################## ##### GUILE ###### @@ -759,59 +825,86 @@ javascript_clean: cd $(ROOT_DIR)/Tools/javascript && $(MAKE) -s clean ################################################################## -##### ANDROID ###### +##### LUA ###### ################################################################## -ANDROID = @ANDROID@ -ANDROID_NDK_BUILD = @NDKBUILD@ -ANDROID_ADB = @ADB@ -ANT = @ANT@ -TARGETID = 1 +# lua flags +LUA_INCLUDE= @LUAFLAGS@ +LUA_LIB = @LUALINK@ + +# Extra specific dynamic linking options +LUA_DLNK = @LUADYNAMICLINKING@ +LUA_SO = @LUA_SO@ + +LUA = @LUABIN@ +LUA_SCRIPT = $(SRCDIR)$(RUNME).lua + +# Extra code for lua static link +LUA_INTERP = ../lua.c # ---------------------------------------------------------------- -# Build an Android dynamically loadable module (C) +# Build a C dynamically loadable module # ---------------------------------------------------------------- -android: $(SRCDIR_SRCS) - $(ANDROID) $(SILENT_OPTION) update project --target $(TARGETID) --name $(PROJECTNAME) --path . - $(SWIG) -java $(SWIGOPT) -o $(INTERFACEDIR)$(TARGET)_wrap.c $(INTERFACEPATH) - +$(ANDROID_NDK_BUILD) $(SILENT_PIPE) - $(ANT) $(ANT_QUIET) debug +lua: $(SRCDIR_SRCS) + $(SWIG) -lua $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) $(LUA_INCLUDE) + $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(LUA_LIB) -o $(LIBPREFIX)$(TARGET)$(LUA_SO) -# ---------------------------------------------------------------- -# Build an Android dynamically loadable module (C++) -# ---------------------------------------------------------------- +# ----------------------------------------------------------------- +# Build a C++ dynamically loadable module +# ----------------------------------------------------------------- -android_cpp: $(SRCDIR_SRCS) - $(ANDROID) $(SILENT_OPTION) update project --target $(TARGETID) --name $(PROJECTNAME) --path . - $(SWIG) -java -c++ $(SWIGOPT) -o $(INTERFACEDIR)$(TARGET)_wrap.cpp $(INTERFACEPATH) - +$(ANDROID_NDK_BUILD) $(SILENT_PIPE) - $(ANT) $(ANT_QUIET) debug +lua_cpp: $(SRCDIR_SRCS) $(GENCXXSRCS) + $(SWIG) -c++ -lua $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(GENCXXSRCS) $(INCLUDES) $(LUA_INCLUDE) + $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(LUA_LIB) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(LUA_SO) -# ---------------------------------------------------------------- -# Android install -# ---------------------------------------------------------------- +lua_externalhdr: + $(SWIG) -lua -external-runtime $(TARGET) -android_install: - -$(ANDROID_ADB) uninstall $(PACKAGENAME) - $(ANDROID_ADB) install $(INSTALLOPTIONS) bin/$(PROJECTNAME)-debug.apk +lua_swig_cpp: + $(SWIG) -c++ -lua $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + +# ----------------------------------------------------------------- +# Build statically linked Lua interpreter +# ----------------------------------------------------------------- + +lua_static: $(SRCDIR_SRCS) + $(SWIG) -lua -module example $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(SRCDIR)$(LUA_INTERP) $(INCLUDES) \ + $(LUA_INCLUDE) $(LIBS) $(LUA_LIB) -o $(TARGET) + +lua_static_cpp: $(SRCDIR_SRCS) $(GENCXXSRCS) + $(SWIG) -c++ -lua -module example $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(GENCXXSRCS) $(SRCDIR)$(LUA_INTERP) $(INCLUDES) \ + $(LUA_INCLUDE) $(LIBS) $(LUA_LIB) -o $(TARGET) + +# ----------------------------------------------------------------- +# Run Lua example +# ----------------------------------------------------------------- + +lua_run: + $(RUNTOOL) $(LUA) $(LUA_SCRIPT) $(RUNPIPE) + +lua_embed_run: + $(RUNTOOL) ./$(TARGET) $(LUA_SCRIPT) $(RUNPIPE) # ----------------------------------------------------------------- # Version display # ----------------------------------------------------------------- -android_version: - $(ANDROID_ADB) version +lua_version: + $(LUA) -v | head -n 1 # ----------------------------------------------------------------- -# Cleaning the Android examples +# Cleaning the lua examples # ----------------------------------------------------------------- -android_clean: - test -n "$(SRCDIR)" && cd $(SRCDIR) ; $(ANT) -q -logfile /dev/null clean - rm -f $(INTERFACEDIR)$(TARGET)_wrap.* - rm -f `find $(PACKAGEDIR) -name \*.java | grep -v $(PROJECTNAME).java` - rm -rf obj +lua_clean: + rm -f *_wrap* *~ .~* mylua@EXEEXT@ + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *$(LUA_SO) ################################################################## ##### MZSCHEME ###### @@ -862,7 +955,7 @@ mzscheme_clean: rm -f *.@OBJEXT@ *$(MZSCHEME_SO) ################################################################## -##### Ocaml ##### +##### OCAML ###### ################################################################## OCC=$(COMPILETOOL) @OCAMLC@ @@ -965,6 +1058,384 @@ ocaml_clean: rm -f *.@OBJEXT@ *@SO@ rm -rf ./localtmp +################################################################## +##### OCTAVE ###### +################################################################## + +# Make sure these locate your Octave installation +OCTAVE = @OCTAVE@ +OCTAVE_CXX = $(DEFS) @OCTAVE_CPPFLAGS@ @OCTAVE_CXXFLAGS@ + +# Extra Octave specific dynamic linking options +OCTAVE_DLNK = @OCTAVE_LDFLAGS@ +OCTAVE_SO = @OCTAVE_SO@ + +OCTAVE_SCRIPT = $(SRCDIR)$(RUNME).m + +# ---------------------------------------------------------------- +# Pre-compile Octave headers, if supported +# ---------------------------------------------------------------- + +ifeq (yes,$(PCHSUPPORT)) + +octave_precompile_headers: + echo "precompiling $(OCTHEADERS)" + cp -f $(OCTHEADERSSRC) $(OCTHEADERS) + if $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) $(OCTAVE_CXX) $(OCTHEADERS); then \ + : ; \ + else \ + rm -f $(OCTHEADERSGCH); \ + exit 1; \ + fi + +else + +octave_precompile_headers: + echo "precompiling Octave headers not supported"; exit 1 + +endif + +# ---------------------------------------------------------------- +# Build a C dynamically loadable module +# Note: Octave requires C++ compiler when compiling C wrappers +# ---------------------------------------------------------------- + +octave: $(SRCDIR_SRCS) + $(SWIG) -octave $(SWIGOCTHDROPT) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) -g -c $(IOCTHEADERS) $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(INCLUDES) $(OCTAVE_CXX) + $(CC) -g -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CSRCS) $(INCLUDES) + $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(OCTAVE_DLNK) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(OCTAVE_SO) + +# ----------------------------------------------------------------- +# Build a C++ dynamically loadable module +# ----------------------------------------------------------------- + +octave_cpp: $(SRCDIR_SRCS) + $(SWIG) -c++ -octave $(SWIGOCTHDROPT) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) -g -c $(IOCTHEADERS) $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) $(OCTAVE_CXX) + $(CXXSHARED) -g $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(OCTAVE_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(OCTAVE_SO) + +# ----------------------------------------------------------------- +# Running an Octave example +# ----------------------------------------------------------------- + +octave_run: + env OCTAVE_PATH= OCTAVE_HISTFILE=/dev/null $(RUNTOOL) $(OCTAVE) $(OCTAVE_SCRIPT) $(RUNPIPE) + +# ----------------------------------------------------------------- +# Version display +# ----------------------------------------------------------------- + +octave_version: + $(OCTAVE) --version | head -n 1 + +# ----------------------------------------------------------------- +# Cleaning the Octave examples +# ----------------------------------------------------------------- + +octave_clean: + rm -rf __pycache__ + rm -f *_wrap* *~ .~* myoctave@EXEEXT@ *.pyc + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *@SO@ *$(OCTAVE_SO) + rm -f $(OCTHEADERS) $(OCTHEADERSGCH) + +################################################################## +##### PERL 5 ###### +################################################################## + +# You need to set this variable to the Perl5 directory containing the +# files "perl.h", "EXTERN.h" and "XSUB.h". With Perl5.003, it's +# usually something like /usr/local/lib/perl5/arch-osname/5.003/CORE. + +PERL5_INCLUDE= @PERL5EXT@ + +# Extra Perl specific dynamic linking options +PERL5_DLNK = @PERL5DYNAMICLINKING@ +PERL5_CCFLAGS = @PERL5CCFLAGS@ +PERL5_CCDLFLAGS = @PERL5CCDLFLAGS@ +PERL5_CCCDLFLAGS = @PERL5CCCDLFLAGS@ +PERL5_LDFLAGS = @PERL5LDFLAGS@ +PERL = @PERL@ +PERL5_LIB = -L$(PERL5_INCLUDE) -l@PERL5LIB@ @LIBS@ $(SYSLIBS) +PERL5_SCRIPT = $(SRCDIR)$(RUNME).pl + +# ---------------------------------------------------------------- +# Build a Perl5 dynamically loadable module (C) +# ---------------------------------------------------------------- + +perl5: $(SRCDIR_SRCS) + $(SWIG) -perl5 $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(CC) -c -Dbool=char $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(PERL5_CCFLAGS) $(PERL5_CCCDLFLAGS) -I$(PERL5_INCLUDE) + $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(PERL5_CCDLFLAGS) $(OBJS) $(IOBJS) $(PERL5_LDFLAGS) $(PERL5_DLNK) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + +# ---------------------------------------------------------------- +# Build a Perl5 dynamically loadable module (C++) +# ---------------------------------------------------------------- + +perl5_cpp: $(SRCDIR_SRCS) + $(SWIG) -perl5 -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(PERL5_CCFLAGS) $(PERL5_CCCDLFLAGS) -I$(PERL5_INCLUDE) + $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(PERL5_CCDLFLAGS) $(OBJS) $(IOBJS) $(PERL5_LDFLAGS) $(PERL5_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + +# ---------------------------------------------------------------- +# Build a module from existing XS C source code. (ie. from xsubpp). +# ---------------------------------------------------------------- +perl5_xs: $(SRCDIR_SRCS) + $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(INCLUDES) -I$(PERL5_INCLUDE) + $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $(TARGET)$(SO) + +# ---------------------------------------------------------------- +# Build a statically linked Perl5 executable +# ---------------------------------------------------------------- + +perl5_static: $(SRCDIR_SRCS) + $(SWIG) -perl5 -static -lperlmain.i $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Dbool=char $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) -I$(PERL5_INCLUDE) $(PERL5_LIB) $(LIBS) -o $(TARGET) + +perl5_static_cpp: $(SRCDIR_SRCS) + $(SWIG) -perl5 -c++ -static -lperlmain.i $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) -I$(PERL5_INCLUDE) $(PERL5_LIB) $(LIBS) -o $(TARGET) + +# ----------------------------------------------------------------- +# Running a Perl5 example +# ----------------------------------------------------------------- + +perl5_run: + $(RUNTOOL) $(PERL) -I. $(PERL5_SCRIPT) $(RUNPIPE) + +# ----------------------------------------------------------------- +# Version display +# ----------------------------------------------------------------- + +perl5_version: + $(PERL) -v | grep "This is" + +# ----------------------------------------------------------------- +# Cleaning the Perl5 examples +# ----------------------------------------------------------------- + +perl5_clean: + rm -f *_wrap* *~ .~* myperl@EXEEXT@ *.pm + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *@SO@ + +################################################################## +##### PHP ###### +################################################################## + +PHP = @PHP@ +PHP_INCLUDE = @PHPINC@ +PHP_SO = @PHP_SO@ +PHP_SCRIPT = $(SRCDIR)$(RUNME).php +PHP_EXTENSION = example$(PHP_SO) + +# ------------------------------------------------------------------- +# Build a PHP dynamically loadable module (C) +# ------------------------------------------------------------------- + +php: $(SRCDIR_SRCS) + $(SWIG) -php $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(PHP_INCLUDE) + $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(PHP_SO) + +# -------------------------------------------------------------------- +# Build a PHP dynamically loadable module (C++) +# -------------------------------------------------------------------- + +php_cpp: $(SRCDIR_SRCS) + $(SWIG) -php -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(PHP_INCLUDE) + $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(PHP_SO) + +# ----------------------------------------------------------------- +# Running a PHP example +# ----------------------------------------------------------------- + +php_run: + $(RUNTOOL) $(PHP) -n -d extension_dir=. -d extension=$(PHP_EXTENSION) -d display_errors=stderr -r 'set_error_handler(function($$n,$$s,$$f,$$l){if($$f!==Null){print$$f;if($$l!==Null)print":$$l";print": ";}print"$$s\n";exit(1);});if(strlen($$argv[1]))include($$argv[1]);' '$(PHP_SCRIPT)' $(RUNPIPE) + +# ----------------------------------------------------------------- +# Version display +# ----------------------------------------------------------------- + +php_version: + $(PHP) -v | head -n 1 + +# ----------------------------------------------------------------- +# Cleaning the PHP examples +# ----------------------------------------------------------------- + +php_clean: + rm -f *_wrap* *~ .~* example.php php_example.h + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *$(PHP_SO) + +################################################################## +##### PYTHON ###### +################################################################## + +PYTHON_FLAGS = + +# Make sure these locate your Python installation +ifneq (,$(PY2)) + PYTHON_INCLUDE= $(DEFS) @PYINCLUDE@ + PYTHON_LIB = @PYLIB@ + PYTHON = @PYTHON@ $(PYTHON_FLAGS) +else + PYTHON_INCLUDE= $(DEFS) @PY3INCLUDE@ + PYTHON_LIB = @PY3LIB@ + PYTHON = @PYTHON3@ $(PYTHON_FLAGS) +endif + +# Extra Python specific linking options +ifneq (,$(PY2)) + PYTHON_DLNK = @PYTHONDYNAMICLINKING@ + PYTHON_LINK = @PYLINK@ +else + PYTHON_DLNK = @PYTHON3DYNAMICLINKING@ + PYTHON_LINK = @PY3LINK@ +endif +PYTHON_SO = @PYTHON_SO@ + +PYCODESTYLE = @PYCODESTYLE@ +PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,W291,W391 + +# ---------------------------------------------------------------- +# Build a C dynamically loadable module +# ---------------------------------------------------------------- + +python: $(SRCDIR_SRCS) + $(SWIG) -python $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) $(PYTHON_INCLUDE) + $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(PYTHON_DLNK) $(LIBS) -o $(LIBPREFIX)_$(TARGET)$(PYTHON_SO) + +# ----------------------------------------------------------------- +# Build a C++ dynamically loadable module +# ----------------------------------------------------------------- + +python_cpp: $(SRCDIR_SRCS) + $(SWIG) -python -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) $(PYTHON_INCLUDE) + $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(PYTHON_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)_$(TARGET)$(PYTHON_SO) + +# ----------------------------------------------------------------- +# Build statically linked Python interpreter +# +# These should only be used in conjunction with the %include embed.i +# library file +# ----------------------------------------------------------------- + +#TKINTER = -L/usr/X11R6.3/lib -L/usr/local/compat/lib -ltk4.0 -ltcl7.4 -lX11 +TKINTER = +PYTHON_LIBOPTS = $(PYTHON_LINK) @LIBS@ $(TKINTER) $(SYSLIBS) + +python_static: $(SRCDIR_SRCS) + $(SWIG) -python -lembed.i $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) @LINKFORSHARED@ $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) \ + $(PYTHON_INCLUDE) $(LIBS) -L$(PYTHON_LIB) $(PYTHON_LIBOPTS) -o $(TARGET) + +python_static_cpp: $(SRCDIR_SRCS) + $(SWIG) -python -c++ -lembed.i $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) \ + $(PYTHON_INCLUDE) $(LIBS) -L$(PYTHON_LIB) $(PYTHON_LIBOPTS) -o $(TARGET) + +# ----------------------------------------------------------------- +# Running a Python example +# ----------------------------------------------------------------- + +PYSCRIPT = $(RUNME).py + +python_run: $(PYSCRIPT) +ifneq (,$(PYCODESTYLE)) + $(COMPILETOOL) $(PYCODESTYLE) $(PYCODESTYLE_FLAGS) $(PYSCRIPT) +endif + env PYTHONPATH=$$PWD $(RUNTOOL) $(PYTHON) $(PYSCRIPT) $(RUNPIPE) + +ifneq (,$(SRCDIR)) +$(RUNME).py: $(SRCDIR)$(RUNME).py + cp $< $@ +endif + +# ----------------------------------------------------------------- +# Version display +# ----------------------------------------------------------------- + +python_version: + $(PYTHON) -V + +# ----------------------------------------------------------------- +# Cleaning the python examples +# ----------------------------------------------------------------- + +python_clean: + rm -rf __pycache__ + rm -f *_wrap* *~ .~* mypython@EXEEXT@ *.pyc + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *@SO@ *$(PYTHON_SO) + rm -f $(TARGET).py + case "x$(SRCDIR)" in x|x./);; *) rm -f $(RUNME).py;; esac + +################################################################## +##### R ###### +################################################################## + +R = R +RCXXSRCS = $(INTERFACE:.i=_wrap.cpp) #Need to use _wrap.cpp for R build system as it does not understand _wrap.cxx +RRSRC = $(INTERFACE:.i=.R) +R_CFLAGS=-fPIC +R_OPT = --slave --quiet --no-save --no-restore +R_SCRIPT=$(SRCDIR)$(RUNME).R + +# need to compile .cxx files outside of R build system to make sure that +# we get -fPIC +# CMD SHLIB stdout is piped to /dev/null to prevent echo of compiler command + +# ---------------------------------------------------------------- +# Build a R dynamically loadable module (C) +# ---------------------------------------------------------------- + +r: $(SRCDIR_SRCS) + $(SWIG) -r $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) +ifneq ($(SRCDIR_SRCS),) + $(CC) -g -c $(CPPFLAGS) $(CFLAGS) $(R_CFLAGS) $(SRCDIR_SRCS) $(INCLUDES) +endif + +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" PKG_CFLAGS="$(CFLAGS)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(ISRCS) $(OBJS) > /dev/null ) + +# ---------------------------------------------------------------- +# Build a R dynamically loadable module (C++) +# ---------------------------------------------------------------- +r_cpp: $(SRCDIR_CXXSRCS) + $(SWIG) -c++ -r $(SWIGOPT) -o $(RCXXSRCS) $(INTERFACEPATH) +ifneq ($(SRCDIR_CXXSRCS),) + $(CXX) -g -c $(CPPFLAGS) $(CXXFLAGS) $(R_CFLAGS) $(SRCDIR_CXXSRCS) $(INCLUDES) +endif + +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" PKG_CXXFLAGS="$(CXXFLAGS)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(RCXXSRCS) $(OBJS) > /dev/null ) + +# ----------------------------------------------------------------- +# Run R example +# ----------------------------------------------------------------- + +r_run: + $(RUNTOOL) $(R) $(R_OPT) -f $(R_SCRIPT) $(RUNPIPE) + +# ----------------------------------------------------------------- +# Version display +# ----------------------------------------------------------------- + +r_version: + $(R) --version | head -n 1 + +# ----------------------------------------------------------------- +# Cleaning the R examples +# ----------------------------------------------------------------- + +r_clean: + rm -f *_wrap* *~ .~* + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *@SO@ NAMESPACE + rm -f $(RRSRC) $(RUNME).Rout .RData + ################################################################## ##### RUBY ###### ################################################################## @@ -1039,312 +1510,7 @@ ruby_clean: rm -f *.@OBJEXT@ *$(RUBY_SO) ################################################################## -##### PHP ###### -################################################################## - -PHP = @PHP@ -PHP_INCLUDE = @PHPINC@ -PHP_SO = @PHP_SO@ -PHP_SCRIPT = $(SRCDIR)$(RUNME).php -PHP_EXTENSION = example$(PHP_SO) - -# ------------------------------------------------------------------- -# Build a PHP dynamically loadable module (C) -# ------------------------------------------------------------------- - -php: $(SRCDIR_SRCS) - $(SWIG) -php $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(PHP_INCLUDE) - $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(PHP_SO) - -# -------------------------------------------------------------------- -# Build a PHP dynamically loadable module (C++) -# -------------------------------------------------------------------- - -php_cpp: $(SRCDIR_SRCS) - $(SWIG) -php -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(PHP_INCLUDE) - $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(PHP_SO) - -# ----------------------------------------------------------------- -# Running a PHP example -# ----------------------------------------------------------------- - -php_run: - $(RUNTOOL) $(PHP) -n -d extension_dir=. -d extension=$(PHP_EXTENSION) -d display_errors=stderr -r 'set_error_handler(function($$n,$$s,$$f,$$l){if($$f!==Null){print$$f;if($$l!==Null)print":$$l";print": ";}print"$$s\n";exit(1);});if(strlen($$argv[1]))include($$argv[1]);' '$(PHP_SCRIPT)' $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -php_version: - $(PHP) -v | head -n 1 - -# ----------------------------------------------------------------- -# Cleaning the PHP examples -# ----------------------------------------------------------------- - -php_clean: - rm -f *_wrap* *~ .~* example.php php_example.h - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *$(PHP_SO) - -################################################################## -##### CSHARP ###### -################################################################## - -# Extra CSharp specific dynamic linking options -CSHARP_DLNK = @CSHARPDYNAMICLINKING@ -CSHARP_LIBPREFIX = @CSHARPLIBRARYPREFIX@ -CSHARPCOMPILER = @CSHARPCOMPILER@ -CSHARPCILINTERPRETER = @CSHARPCILINTERPRETER@ -CSHARPCILINTERPRETER_FLAGS = @CSHARPCILINTERPRETER_FLAGS@ -CSHARPCFLAGS = @CSHARPCFLAGS@ -CSHARPFLAGS = -CSHARPOPTIONS = -CSHARPSO = @CSHARPSO@ -CSHARP_RUNME = ./$(RUNME).exe - -# ---------------------------------------------------------------- -# Build a CSharp dynamically loadable module (C) -# ---------------------------------------------------------------- - -csharp: $(SRCDIR_SRCS) - $(SWIG) -csharp $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(CSHARPCFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) - $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(CSHARP_DLNK) $(LIBS) -o $(CSHARP_LIBPREFIX)$(TARGET)$(CSHARPSO) - -# ---------------------------------------------------------------- -# Build a CSharp dynamically loadable module (C++) -# ---------------------------------------------------------------- - -csharp_cpp: $(SRCDIR_SRCS) - $(SWIG) -csharp -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(CSHARPCFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) - $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(CSHARP_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(CSHARP_LIBPREFIX)$(TARGET)$(CSHARPSO) - -# ---------------------------------------------------------------- -# Compile CSharp files -# ---------------------------------------------------------------- - -ifneq (,$(SRCDIR)) -SRCDIR_CSHARPSRCS = $(addprefix $(SRCDIR),$(CSHARPSRCS)) -else -SRCDIR_CSHARPSRCS = -endif - -csharp_compile: $(SRCDIR_SRCS) - $(COMPILETOOL) $(CSHARPCOMPILER) $(CSHARPFLAGS) $(CSHARPOPTIONS) $(CSHARPSRCS) $(SRCDIR_CSHARPSRCS) - -# ----------------------------------------------------------------- -# Run CSharp example -# ----------------------------------------------------------------- - -csharp_run: - env LD_LIBRARY_PATH=$$PWD $(RUNTOOL) $(CSHARPCILINTERPRETER) $(CSHARPCILINTERPRETER_FLAGS) $(CSHARP_RUNME) $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -# Version check below also works with MS csc.exe which does not understand --version -csharp_version: - $(CSHARPCOMPILER) --version | head -n 1 - if test -n "$(CSHARPCILINTERPRETER)" ; then "$(CSHARPCILINTERPRETER)" --version ; fi - -# ----------------------------------------------------------------- -# Cleaning the CSharp examples -# ----------------------------------------------------------------- - -csharp_clean: - rm -f *_wrap* *~ .~* $(RUNME) $(RUNME).exe *.exe.mdb gc.log `find . -name \*.cs | grep -v $(RUNME).cs` - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@CSHARPSO@ - -################################################################## -##### LUA ###### -################################################################## - -# lua flags -LUA_INCLUDE= @LUAFLAGS@ -LUA_LIB = @LUALINK@ - -# Extra specific dynamic linking options -LUA_DLNK = @LUADYNAMICLINKING@ -LUA_SO = @LUA_SO@ - -LUA = @LUABIN@ -LUA_SCRIPT = $(SRCDIR)$(RUNME).lua - -# Extra code for lua static link -LUA_INTERP = ../lua.c - -# ---------------------------------------------------------------- -# Build a C dynamically loadable module -# ---------------------------------------------------------------- - -lua: $(SRCDIR_SRCS) - $(SWIG) -lua $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) $(LUA_INCLUDE) - $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(LUA_LIB) -o $(LIBPREFIX)$(TARGET)$(LUA_SO) - -# ----------------------------------------------------------------- -# Build a C++ dynamically loadable module -# ----------------------------------------------------------------- - -lua_cpp: $(SRCDIR_SRCS) $(GENCXXSRCS) - $(SWIG) -c++ -lua $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(GENCXXSRCS) $(INCLUDES) $(LUA_INCLUDE) - $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(LUA_LIB) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(LUA_SO) - -lua_externalhdr: - $(SWIG) -lua -external-runtime $(TARGET) - -lua_swig_cpp: - $(SWIG) -c++ -lua $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - -# ----------------------------------------------------------------- -# Build statically linked Lua interpreter -# ----------------------------------------------------------------- - -lua_static: $(SRCDIR_SRCS) - $(SWIG) -lua -module example $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(SRCDIR)$(LUA_INTERP) $(INCLUDES) \ - $(LUA_INCLUDE) $(LIBS) $(LUA_LIB) -o $(TARGET) - -lua_static_cpp: $(SRCDIR_SRCS) $(GENCXXSRCS) - $(SWIG) -c++ -lua -module example $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(GENCXXSRCS) $(SRCDIR)$(LUA_INTERP) $(INCLUDES) \ - $(LUA_INCLUDE) $(LIBS) $(LUA_LIB) -o $(TARGET) - -# ----------------------------------------------------------------- -# Run Lua example -# ----------------------------------------------------------------- - -lua_run: - $(RUNTOOL) $(LUA) $(LUA_SCRIPT) $(RUNPIPE) - -lua_embed_run: - $(RUNTOOL) ./$(TARGET) $(LUA_SCRIPT) $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -lua_version: - $(LUA) -v | head -n 1 - -# ----------------------------------------------------------------- -# Cleaning the lua examples -# ----------------------------------------------------------------- - -lua_clean: - rm -f *_wrap* *~ .~* mylua@EXEEXT@ - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *$(LUA_SO) - -################################################################## -##### CFFI ###### -################################################################## - -CFFI = @CFFIBIN@ -CFFI_SCRIPT=$(RUNME).lisp - -cffi: $(SRCDIR_SRCS) - $(SWIG) -cffi $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) -# $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCDIR_SRCS) -# $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) - -cffi_cpp: $(SRCDIR_SRCS) - $(SWIG) -c++ -cffi $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) - $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) - -# ----------------------------------------------------------------- -# Run CFFI example -# ----------------------------------------------------------------- - -cffi_run: - $(RUNTOOL) $(CFFI) -batch -s $(CFFI_SCRIPT) $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -cffi_version: - $(CFFI) --version - -# ----------------------------------------------------------------- -# Cleaning the CFFI examples -# ----------------------------------------------------------------- - -cffi_clean: - rm -f *_wrap* *~ .~* - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@SO@ - -################################################################## -##### R ###### -################################################################## - -R = R -RCXXSRCS = $(INTERFACE:.i=_wrap.cpp) #Need to use _wrap.cpp for R build system as it does not understand _wrap.cxx -RRSRC = $(INTERFACE:.i=.R) -R_CFLAGS=-fPIC -R_OPT = --slave --quiet --no-save --no-restore -R_SCRIPT=$(SRCDIR)$(RUNME).R - -# need to compile .cxx files outside of R build system to make sure that -# we get -fPIC -# CMD SHLIB stdout is piped to /dev/null to prevent echo of compiler command - -# ---------------------------------------------------------------- -# Build a R dynamically loadable module (C) -# ---------------------------------------------------------------- - -r: $(SRCDIR_SRCS) - $(SWIG) -r $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) -ifneq ($(SRCDIR_SRCS),) - $(CC) -g -c $(CPPFLAGS) $(CFLAGS) $(R_CFLAGS) $(SRCDIR_SRCS) $(INCLUDES) -endif - +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" PKG_CFLAGS="$(CFLAGS)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(ISRCS) $(OBJS) > /dev/null ) - -# ---------------------------------------------------------------- -# Build a R dynamically loadable module (C++) -# ---------------------------------------------------------------- -r_cpp: $(SRCDIR_CXXSRCS) - $(SWIG) -c++ -r $(SWIGOPT) -o $(RCXXSRCS) $(INTERFACEPATH) -ifneq ($(SRCDIR_CXXSRCS),) - $(CXX) -g -c $(CPPFLAGS) $(CXXFLAGS) $(R_CFLAGS) $(SRCDIR_CXXSRCS) $(INCLUDES) -endif - +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" PKG_CXXFLAGS="$(CXXFLAGS)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(RCXXSRCS) $(OBJS) > /dev/null ) - -# ----------------------------------------------------------------- -# Run R example -# ----------------------------------------------------------------- - -r_run: - $(RUNTOOL) $(R) $(R_OPT) -f $(R_SCRIPT) $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -r_version: - $(R) --version | head -n 1 - -# ----------------------------------------------------------------- -# Cleaning the R examples -# ----------------------------------------------------------------- - -r_clean: - rm -f *_wrap* *~ .~* - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@SO@ NAMESPACE - rm -f $(RRSRC) $(RUNME).Rout .RData - -################################################################## -##### SCILAB ###### +##### SCILAB ###### ################################################################## SCILAB = @SCILAB@ @@ -1396,243 +1562,76 @@ scilab_clean: rm -f *.sce ################################################################## -##### Go ###### +##### TCL ###### ################################################################## -# TODO: The Go make targets need simplifying to use configure time -# configuration or to use Make's ifeq rather than using lots of -# runtime shell code. The output will then be a lot less verbose. +# Set these to your local copy of Tcl -GO = @GO@ -GOGCC = @GOGCC@ -GCCGO = @GCCGO@ -GOOPT = @GOOPT@ -GCCGOOPT = @GCCGOOPT@ -GOVERSIONOPTION = @GOVERSIONOPTION@ +TCLSH = tclsh +TCL_INCLUDE = @TCLINCLUDE@ +TCL_LIB = @TCLLIB@ +TCL_OPTS = @LIBS@ +TK_OPTS = -ltk -ltcl @LIBS@ -GOSWIGARG = `if $(GOGCC) ; then echo -gccgo; fi` +# Extra Tcl specific dynamic linking options +TCL_DLNK = @TCLDYNAMICLINKING@ +TCL_SO = @TCL_SO@ +TCLLDSHARED = @TCLLDSHARED@ +TCLCXXSHARED = @TCLCXXSHARED@ +TCL_SCRIPT = $(SRCDIR)$(RUNME).tcl +TCL_LINK = @TCLLINK@ -GOSRCS = $(INTERFACE:.i=.go) -GOCSRCS = $(INTERFACE:.i=_gc.c) +# ----------------------------------------------------------- +# Build a new version of the tclsh shell +# ----------------------------------------------------------- -GOPACKAGE = $(notdir $(INTERFACE:.i=.a)) +tclsh: $(SRCDIR_SRCS) + $(SWIG) -tcl8 $(SWIGOPT) $(TCL_SWIGOPTS) -ltclsh.i -o $(ISRCS) $(INTERFACEPATH) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(TCL_INCLUDE) \ + $(TCL_LIB) $(TCL_OPTS) $(LIBS) $(SYSLIBS) -o $(TARGET) -GOPATHPARENTDIR = gopath/$(GOMOD)/src -GOPATHDIR = $(GOPATHPARENTDIR)/$(INTERFACE:.i=) +tclsh_cpp: $(SRCDIR_SRCS) + $(SWIG) -tcl8 -c++ $(SWIGOPT) $(TCL_SWIGOPTS) -ltclsh.i -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(TCL_INCLUDE) \ + $(TCL_LIB) $(TCL_OPTS) $(LIBS) $(SYSLIBS) -o $(TARGET) -# ---------------------------------------------------------------- -# Build a Go module (C) -# ---------------------------------------------------------------- +# ----------------------------------------------------------- +# Build a Tcl dynamic loadable module (you might need to tweak this) +# ----------------------------------------------------------- -$(GOPATHPARENTDIR)/go.mod: - @mkdir gopath 2>/dev/null || true - @mkdir gopath/$(GOMOD) 2>/dev/null || true - @mkdir gopath/$(GOMOD)/src 2>/dev/null || true - @mkdir $(GOPATHDIR) 2>/dev/null || true - echo "module swigtests" > $(GOPATHDIR)/go.mod - echo "" >> $(GOPATHDIR)/go.mod - echo "go 1.12" >> $(GOPATHDIR)/go.mod - mv -f $(GOPATHDIR)/go.mod $(GOPATHPARENTDIR)/go.mod +tcl: $(SRCDIR_SRCS) + $(SWIG) -tcl8 $(SWIGOPT) $(TCL_SWIGOPTS) -o $(ISRCS) $(INTERFACEPATH) + $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(TCL_INCLUDE) + $(TCLLDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(TCL_DLNK) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(TCL_SO) $(TCL_LINK) -go: $(SRCDIR_SRCS) $(GOPATHPARENTDIR)/go.mod - $(SWIG) -go -import-prefix swigtests $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - @mkdir gopath 2>/dev/null || true - @mkdir gopath/$(GOMOD) 2>/dev/null || true - @mkdir gopath/$(GOMOD)/src 2>/dev/null || true - @mkdir $(GOPATHDIR) 2>/dev/null || true - rm -rf $(GOPATHDIR)/* - cp $(ISRCS) $(GOPATHDIR)/ - if test -f $(IWRAP:.i=.h); then \ - cp $(IWRAP:.i=.h) $(GOPATHDIR)/; \ - fi - if test -n "$(SRCDIR_SRCS)"; then \ - cp $(SRCDIR_SRCS) $(GOPATHDIR)/; \ - fi - cp $(GOSRCS) $(GOPATHDIR)/ - @if test -f $(SRCDIR)$(RUNME).go; then \ - mkdir gopath/$(GOMOD)/src/runme 2>/dev/null || true; \ - rm -f gopath/$(GOMOD)/src/runme/*; \ - fi - if test -f $(SRCDIR)$(RUNME).go; then \ - cp $(SRCDIR)$(RUNME).go gopath/$(GOMOD)/src/runme/; \ - fi - GOPATH=`pwd`/gopath/$(GOMOD); \ - export GOPATH; \ - CGO_CPPFLAGS="$(CPPFLAGS) $(INCLUDES) -I `cd $(SRCDIR) && pwd` -I `pwd`"; \ - export CGO_CPPFLAGS; \ - CGO_CFLAGS="$(CFLAGS)"; \ - export CGO_CFLAGS; \ - CGO_LDFLAGS="$(LDFLAGS) -lm"; \ - export CGO_LDFLAGS; \ - (cd $(GOPATHDIR)/ && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o $(GOPACKAGE)); \ - stat=$$?; \ - if test $$stat != 0; then \ - exit $$stat; \ - fi; \ - if $(GOGCC); then \ - cp $(GOPATHDIR)/$(GOPACKAGE) $(GOPATHDIR)/$(GOPACKAGE:.a=.gox); \ - fi; \ - if test -f $(SRCDIR)$(RUNME).go; then \ - mkdir gopath/$(GOMOD)/src/swigtests 2>/dev/null || true; \ - mkdir gopath/$(GOMOD)/src/swigtests/$(INTERFACE:.i=) 2>/dev/null || true; \ - cp $(GOPATHDIR)/* gopath/$(GOMOD)/src/swigtests/$(INTERFACE:.i=)/; \ - (cd gopath/$(GOMOD)/src/runme && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o runme $(RUNME).go); \ - stat=$$?; \ - if test $$stat != 0; then \ - exit $$stat; \ - fi; \ - cp gopath/$(GOMOD)/src/runme/runme $(RUNME); \ - fi +# ----------------------------------------------------------- +# Build a Tcl dynamic loadable module for C++ +# ----------------------------------------------------------- -# ---------------------------------------------------------------- -# Build a Go module (C++) -# ---------------------------------------------------------------- - -go_cpp: $(SRCDIR_SRCS) $(GOPATHPARENTDIR)/go.mod - $(SWIG) -go -c++ -import-prefix swigtests $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - @mkdir gopath 2>/dev/null || true - @mkdir gopath/$(GOMOD) 2>/dev/null || true - @mkdir gopath/$(GOMOD)/src 2>/dev/null || true - @mkdir $(GOPATHDIR) 2>/dev/null || true - rm -rf $(GOPATHDIR)/* - cp $(ICXXSRCS) $(GOPATHDIR)/ - if test -f $(IWRAP:.i=.h); then \ - cp $(IWRAP:.i=.h) $(GOPATHDIR)/; \ - fi - if test -n "$(SRCDIR_CXXSRCS)"; then \ - cp $(SRCDIR_CXXSRCS) $(GOPATHDIR)/; \ - fi - if test -n "$(SRCDIR_SRCS)"; then \ - cp $(SRCDIR_SRCS) $(GOPATHDIR)/; \ - fi - cp $(GOSRCS) $(GOPATHDIR)/ - @if test -f $(SRCDIR)$(RUNME).go; then \ - mkdir gopath/$(GOMOD)/src/runme 2>/dev/null || true; \ - rm -f gopath/$(GOMOD)/src/runme/*; \ - fi - if test -f $(SRCDIR)$(RUNME).go; then \ - cp $(SRCDIR)$(RUNME).go gopath/$(GOMOD)/src/runme/; \ - fi - GOPATH=`pwd`/gopath/$(GOMOD); \ - export GOPATH; \ - CGO_CPPFLAGS="$(CPPFLAGS) $(INCLUDES) -I `cd $(SRCDIR) && pwd` -I `pwd`"; \ - export CGO_CPPFLAGS; \ - CGO_CFLAGS="$(CFLAGS)"; \ - export CGO_CFLAGS; \ - CGO_CXXFLAGS="$(CXXFLAGS)"; \ - export CGO_CXXFLAGS; \ - CGO_LDFLAGS="$(LDFLAGS) -lm"; \ - export CGO_LDFLAGS; \ - (cd $(GOPATHDIR) && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o $(GOPACKAGE)); \ - stat=$$?; \ - if test $$stat != 0; then \ - exit $$stat; \ - fi; \ - if $(GOGCC); then \ - cp $(GOPATHDIR)/$(GOPACKAGE) $(GOPATHDIR)/$(GOPACKAGE:.a=.gox); \ - fi; \ - if test -f $(SRCDIR)$(RUNME).go; then \ - mkdir gopath/$(GOMOD)/src/swigtests 2>/dev/null || true; \ - mkdir gopath/$(GOMOD)/src/swigtests/$(INTERFACE:.i=) 2>/dev/null || true; \ - cp $(GOPATHDIR)/* gopath/$(GOMOD)/src/swigtests/$(INTERFACE:.i=)/; \ - (cd gopath/$(GOMOD)/src/runme && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o runme $(RUNME).go); \ - stat=$$?; \ - if test $$stat != 0; then \ - exit $$stat; \ - fi; \ - cp gopath/$(GOMOD)/src/runme/runme $(RUNME); \ - fi +tcl_cpp: $(SRCDIR_SRCS) + $(SWIG) -tcl8 -c++ $(SWIGOPT) $(TCL_SWIGOPTS) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(TCL_INCLUDE) + $(TCLCXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(TCL_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(TCL_SO) $(TCL_LINK) # ----------------------------------------------------------------- -# Running Go example +# Run Tcl example # ----------------------------------------------------------------- -go_run: - env $(RUNTOOL) ./$(RUNME) $(RUNPIPE) +tcl_run: + $(RUNTOOL) $(TCLSH) $(TCL_SCRIPT) $(RUNPIPE) # ----------------------------------------------------------------- # Version display # ----------------------------------------------------------------- -go_version: - $(GO) $(GOVERSIONOPTION) +tcl_version: + echo 'puts $$tcl_version;exit 0' | $(TCLSH) # ----------------------------------------------------------------- -# Cleaning the Go examples +# Cleaning the Tcl examples # ----------------------------------------------------------------- -go_clean: - rm -f *_wrap* *_gc* *.gox .~* $(RUNME) $(GOSRCS) - rm -rf gopath +tcl_clean: + rm -f *_wrap* *~ .~* mytclsh@EXEEXT@ rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *.[568] *.a *@SO@ - -################################################################## -##### D ###### -################################################################## - -DLIBPREFIX = @DLIBPREFIX@ - -ifeq (,$(D_VERSION)) - D_VERSION = @DDEFAULTVERSION@ -endif - -ifeq (2,$(D_VERSION)) - SWIGD = $(SWIG) -d -d2 - DCOMPILER = @D2COMPILER@ -else - SWIGD = $(SWIG) -d - DCOMPILER = @D1COMPILER@ -endif - -D_RUNME = ./$(RUNME) - -# ---------------------------------------------------------------- -# Build a dynamically loadable D wrapper for a C module -# ---------------------------------------------------------------- - -d: $(SRCDIR_SRCS) - $(SWIGD) $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(DCFLAGS) $(EXTRA_CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) - $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(DCFLAGS) $(EXTRA_LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(DLIBPREFIX)$(TARGET)$(SO) - -# ---------------------------------------------------------------- -# Build a dynamically loadable D wrapper for a C++ module -# ---------------------------------------------------------------- - -d_cpp: $(SRCDIR_SRCS) - $(SWIGD) -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(DCFLAGS) $(EXTRA_CFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) - $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(DCFLAGS) $(EXTRA_LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(DLIBPREFIX)$(TARGET)$(SO) - -# ---------------------------------------------------------------- -# Compile D files -# ---------------------------------------------------------------- - -# Clear the DFLAGS environment variable for the compiler call itself -# to work around a discrepancy in argument handling between DMD and LDC. -d_compile: $(SRCDIR_SRCS) - DFLAGS="" $(COMPILETOOL) $(DCOMPILER) $(DFLAGS) $(DSRCS) - -# ----------------------------------------------------------------- -# Run D example -# ----------------------------------------------------------------- - -d_run: - env LD_LIBRARY_PATH=$$PWD $(RUNTOOL) $(D_RUNME) $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -d_version: - ($(DCOMPILER) --version 2> /dev/null || $(DCOMPILER)) | head -n 3 - -# ----------------------------------------------------------------- -# Clean the D examples -# ----------------------------------------------------------------- - -d_clean: - rm -f *_wrap* *~ .~* $(RUNME) $(RUNME).exe `find . -name \*.d | grep -v $(RUNME).d` - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@SO@ + rm -f *.@OBJEXT@ *$(TCL_SO) diff --git a/Makefile.in b/Makefile.in index a1cb423e4..a20245b5a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -58,23 +58,23 @@ docs-main: # All the languages SWIG speaks (when it wants to) ##################################################################### -skip-tcl = test -n "@SKIP_TCL@" -skip-perl5 = test -n "@SKIP_PERL5@" -skip-python = test -n "@SKIP_PYTHON@" -skip-java = test -n "@SKIP_JAVA@" +skip-csharp = test -n "@SKIP_CSHARP@" +skip-d = test -n "@SKIP_D@" +skip-go = test -n "@SKIP_GO@" skip-guile = test -n "@SKIP_GUILE@" +skip-java = test -n "@SKIP_JAVA@" +skip-javascript = test -n "@SKIP_JAVASCRIPT@" +skip-lua = test -n "@SKIP_LUA@" skip-mzscheme = test -n "@SKIP_MZSCHEME@" -skip-ruby = test -n "@SKIP_RUBY@" -skip-php = test -n "@SKIP_PHP@" skip-ocaml = test -n "@SKIP_OCAML@" skip-octave = test -n "@SKIP_OCTAVE@" -skip-csharp = test -n "@SKIP_CSHARP@" -skip-lua = test -n "@SKIP_LUA@" +skip-perl5 = test -n "@SKIP_PERL5@" +skip-php = test -n "@SKIP_PHP@" +skip-python = test -n "@SKIP_PYTHON@" skip-r = test -n "@SKIP_R@" +skip-ruby = test -n "@SKIP_RUBY@" skip-scilab = test -n "@SKIP_SCILAB@" -skip-go = test -n "@SKIP_GO@" -skip-d = test -n "@SKIP_D@" -skip-javascript = test -n "@SKIP_JAVASCRIPT@" +skip-tcl = test -n "@SKIP_TCL@" # Additional dependencies for some tests skip-android = test -n "@SKIP_ANDROID@" @@ -99,47 +99,47 @@ check-aliveness: test -x ./$(TARGET) ./$(TARGET) -version ./$(TARGET) -help - @$(skip-tcl) || ./$(TARGET) -tcl -help - @$(skip-perl5) || ./$(TARGET) -perl -help - @$(skip-python) || ./$(TARGET) -python -help - @$(skip-java) || ./$(TARGET) -java -help + @$(skip-csharp) || ./$(TARGET) -csharp -help + @$(skip-d) || ./$(TARGET) -d -help + @$(skip-go) || ./$(TARGET) -go -help @$(skip-guile) || ./$(TARGET) -guile -help + @$(skip-java) || ./$(TARGET) -java -help + @$(skip-javascript) || ./$(TARGET) -javascript -help + @$(skip-lua) || ./$(TARGET) -lua -help @$(skip-mzscheme) || ./$(TARGET) -mzscheme -help - @$(skip-ruby) || ./$(TARGET) -ruby -help @$(skip-ocaml) || ./$(TARGET) -ocaml -help @$(skip-octave) || ./$(TARGET) -octave -help + @$(skip-perl5) || ./$(TARGET) -perl -help @$(skip-php) || ./$(TARGET) -php7 -help - @$(skip-csharp) || ./$(TARGET) -csharp -help - @$(skip-lua) || ./$(TARGET) -lua -help + @$(skip-python) || ./$(TARGET) -python -help @$(skip-r) || ./$(TARGET) -r -help + @$(skip-ruby) || ./$(TARGET) -ruby -help @$(skip-scilab) || ./$(TARGET) -scilab -help - @$(skip-go) || ./$(TARGET) -go -help - @$(skip-d) || ./$(TARGET) -d -help - @$(skip-javascript) || ./$(TARGET) -javascript -help + @$(skip-tcl) || ./$(TARGET) -tcl -help check-ccache: test -z "$(ENABLE_CCACHE)" || (cd $(CCACHE) && $(MAKE) check) # Checks / displays versions of each target language check-versions: \ - check-tcl-version \ - check-perl5-version \ - check-python-version \ - check-java-version \ - check-javascript-version \ check-android-version \ + check-csharp-version \ + check-d-version \ + check-go-version \ check-guile-version \ + check-java-version \ + check-javascript-version \ + check-lua-version \ check-mzscheme-version \ - check-ruby-version \ check-ocaml-version \ check-octave-version \ + check-perl5-version \ check-php-version \ - check-csharp-version \ - check-lua-version \ + check-python-version \ check-r-version \ + check-ruby-version \ check-scilab-version \ - check-go-version \ - check-d-version + check-tcl-version \ # all examples check-%-version : @@ -156,43 +156,43 @@ check-%-version : # Checks examples for compilation (does not run them) check-examples: \ - check-tcl-examples \ - check-perl5-examples \ - check-python-examples \ - check-java-examples \ check-android-examples \ + check-csharp-examples \ + check-d-examples \ + check-go-examples \ check-guile-examples \ + check-java-examples \ + check-javascript-examples \ + check-lua-examples \ check-mzscheme-examples \ - check-ruby-examples \ check-ocaml-examples \ check-octave-examples \ + check-perl5-examples \ check-php-examples \ - check-csharp-examples \ - check-lua-examples \ + check-python-examples \ check-r-examples \ + check-ruby-examples \ check-scilab-examples \ - check-go-examples \ - check-d-examples \ - check-javascript-examples + check-tcl-examples \ -tcl_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/tcl/check.list) -perl5_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/perl5/check.list) -python_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/python/check.list) -java_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/java/check.list) android_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/android/check.list) +csharp_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/csharp/check.list) +d_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/d/check.list) +go_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/go/check.list) guile_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/guile/check.list) +java_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/java/check.list) +javascript_examples:=$(shell sed '/^\#/d' $(srcdir)/Examples/javascript/check.list) +lua_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/lua/check.list) mzscheme_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/mzscheme/check.list) -ruby_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/ruby/check.list) ocaml_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/ocaml/check.list) octave_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/octave/check.list) +perl5_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/perl5/check.list) php_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/php/check.list) -csharp_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/csharp/check.list) -lua_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/lua/check.list) +python_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/python/check.list) r_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/r/check.list) +ruby_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/ruby/check.list) scilab_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/scilab/check.list) -go_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/go/check.list) -d_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/d/check.list) -javascript_examples:=$(shell sed '/^\#/d' $(srcdir)/Examples/javascript/check.list) +tcl_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/tcl/check.list) # all examples check-%-examples : @@ -217,23 +217,23 @@ check-%-examples : # Checks testcases in the test-suite excluding those which are known to be broken check-test-suite: \ check-errors-test-suite \ - check-tcl-test-suite \ - check-perl5-test-suite \ - check-python-test-suite \ - check-java-test-suite \ + check-csharp-test-suite \ + check-d-test-suite \ + check-go-test-suite \ check-guile-test-suite \ + check-java-test-suite \ + check-javascript-test-suite \ + check-lua-test-suite \ check-mzscheme-test-suite \ - check-ruby-test-suite \ check-ocaml-test-suite \ check-octave-test-suite \ + check-perl5-test-suite \ check-php-test-suite \ - check-csharp-test-suite \ - check-lua-test-suite \ + check-python-test-suite \ check-r-test-suite \ + check-ruby-test-suite \ check-scilab-test-suite \ - check-go-test-suite \ - check-d-test-suite \ - check-javascript-test-suite + check-tcl-test-suite \ check-%-test-suite: @if test -z "$(skip-$*)"; then \ @@ -264,46 +264,46 @@ check: check-aliveness check-ccache check-versions check-examples check-test-sui # Run known-to-be-broken as well as not broken testcases in the test-suite all-test-suite: \ - all-tcl-test-suite \ - all-perl5-test-suite \ - all-python-test-suite \ - all-java-test-suite \ + all-csharp-test-suite \ + all-d-test-suite \ + all-go-test-suite \ all-guile-test-suite \ + all-java-test-suite \ + all-javascript-test-suite \ + all-lua-test-suite \ all-mzscheme-test-suite \ - all-ruby-test-suite \ all-ocaml-test-suite \ all-octave-test-suite \ + all-perl5-test-suite \ all-php-test-suite \ - all-csharp-test-suite \ - all-lua-test-suite \ + all-python-test-suite \ all-r-test-suite \ + all-ruby-test-suite \ all-scilab-test-suite \ - all-go-test-suite \ - all-d-test-suite \ - all-javascript-test-suite + all-tcl-test-suite \ all-%-test-suite: @$(MAKE) $(FLAGS) check-$*-test-suite ACTION=all # Run known-to-be-broken testcases in the test-suite broken-test-suite: \ - broken-tcl-test-suite \ - broken-perl5-test-suite \ - broken-python-test-suite \ - broken-java-test-suite \ + broken-csharp-test-suite \ + broken-d-test-suite \ + broken-go-test-suite \ broken-guile-test-suite \ + broken-java-test-suite \ + broken-javascript-test-suite \ + broken-lua-test-suite \ broken-mzscheme-test-suite \ - broken-ruby-test-suite \ broken-ocaml-test-suite \ broken-octave-test-suite \ + broken-perl5-test-suite \ broken-php-test-suite \ - broken-csharp-test-suite \ - broken-lua-test-suite \ + broken-python-test-suite \ broken-r-test-suite \ - broken-scilab-test-suite \ - broken-go-test-suite \ - broken-d-test-suite \ - broken-javascript-test-suite + broken-ruby-test-suite \ + broken-scilab-test-suite \ + broken-tcl-test-suite \ broken-%-test-suite: @$(MAKE) $(FLAGS) check-$*-test-suite ACTION=broken From cea25abca535fa27b89eedaf2dd978991b42e1a5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 6 Oct 2022 23:12:38 +0100 Subject: [PATCH 073/217] Completely remove CFFI No meaningful progress to update CFFI to experimental status has been made since CFFI was disabled in SWIG-4.0.0 as the first stage to removal. This commit is the final stage to remove it. See issue #1966 for an attempt at updating CFFI to experimental status. Anyone wishing for SWIG to support CFFI again might want to utilise this work. --- Doc/Manual/Lisp.html | 604 ------------- Examples/Makefile.in | 40 - Examples/test-suite/cffi/Makefile.in | 55 -- Lib/cffi/cffi.swg | 286 ------- Source/Modules/cffi.cxx | 1171 -------------------------- 5 files changed, 2156 deletions(-) delete mode 100644 Doc/Manual/Lisp.html delete mode 100644 Examples/test-suite/cffi/Makefile.in delete mode 100644 Lib/cffi/cffi.swg delete mode 100644 Source/Modules/cffi.cxx diff --git a/Doc/Manual/Lisp.html b/Doc/Manual/Lisp.html deleted file mode 100644 index 6d8463beb..000000000 --- a/Doc/Manual/Lisp.html +++ /dev/null @@ -1,604 +0,0 @@ - - - -SWIG and Common Lisp - - - - - -

    29 SWIG and Common Lisp

    - - - - - - -

    - Common Lisp is a high-level, all-purpose, object-oriented, - dynamic, functional programming language with long history. - Common Lisp is used in many fields, ranging from web development to - finance, and also common in computer science education. - There are more than 9 different implementations of common lisp which - are available, all have different foreign function - interfaces. SWIG currently supports the - Common Foreign Function Interface(CFFI). -

    - -

    29.2 Common Foreign Function Interface(CFFI)

    - - -

    - CFFI, the Common Foreign Function Interface, is a portable foreign - function interface for ANSI Common Lisp systems. - CFFI requires only a small set of - low-level functionality from the Lisp implementation, such as - calling a foreign function by name, allocating foreign memory, - and dereferencing pointers. -

    - -

    - To run the cffi module of SWIG requires very little effort, you - just need to run: -

    -
    -swig -cffi -module module-name   file-name 
    -
    -
    - -

    - But a better was of using all the power of SWIG is to write SWIG - interface files. Below we will explain how to write interface - files and the various things which you can do with them. -

    - -

    29.2.1 Additional Commandline Options

    - - - - - - - - - - - - - - - - - - - - - - -
    CFFI specific options
    -generate-typedefIf this option is given then defctype will be used to generate
    - shortcuts according to the typedefs in the input. -
    -[no]cwrapTurn on or turn off generation of an intermediate C file when
    - creating a C interface. By default this is only done for C++ code. -
    -[no]swig-lispTurns on or off generation of code for helper lisp macro, functions, - etc. which SWIG uses while generating wrappers. These macros, functions - may still be used by generated wrapper code. -
    - -

    29.2.2 Generating CFFI bindings

    - - -

    - -As we mentioned earlier the ideal way to use SWIG is to use interface - files. To illustrate the use of it, let's assume that we have a - file named test.h with the following C code: -

    - -
    -#define y 5
    -#define x (y >>  1)
    -
    -typedef int days;
    -
    -struct bar {
    -  short p, q;
    -  char a, b;
    -  int *z[1000];
    -  struct bar * n;
    -};
    -  
    -struct   bar * my_struct;
    -
    -struct foo {
    -  int a;
    -  struct foo * b[100];
    -};
    -
    -int pointer_func(void (*ClosureFun)( void* _fun, void* _data, void* _evt ), int p);
    -
    -int func123(div_t * p, int **q[100], int r[][1000][10]);
    -
    -void lispsort_double (int n, double * array);
    -
    -enum color { RED, BLUE, GREEN};
    -
    - -

    -Corresponding to this we will write a simple interface file: -

    - -
    -%module test
    -
    -%include "test.h"
    -
    -
    - -

    -The generated SWIG Code will be: -

    - -
    -;;;SWIG wrapper code starts here
    -
    -(cl:defmacro defanonenum (&body enums)
    -   "Converts anonymous enums to defconstants."
    -  `(cl:progn , @(cl:loop for value in enums
    -                        for index = 0 then (cl:1+ index)
    -                        when (cl:listp value) do (cl:setf index (cl:second value)
    -                                                          value (cl:first value))
    -                        collect `(cl:defconstant , value , index))))
    -
    -(cl:eval-when (:compile-toplevel :load-toplevel)
    -  (cl:unless (cl:fboundp 'swig-lispify)
    -    (cl:defun swig-lispify (name flag cl:&optional (package cl:*package*))
    -      (cl:labels ((helper (lst last rest cl:&aux (c (cl:car lst)))
    -                    (cl:cond
    -                      ((cl:null lst)
    -                       rest)
    -                      ((cl:upper-case-p c)
    -                       (helper (cl:cdr lst) 'upper
    -                               (cl:case last
    -                                 ((lower digit) (cl:list* c #\- rest))
    -                                 (cl:t (cl:cons c rest)))))
    -                      ((cl:lower-case-p c)
    -                       (helper (cl:cdr lst) 'lower (cl:cons (cl:char-upcase c) rest)))
    -                      ((cl:digit-char-p c)
    -                       (helper (cl:cdr lst) 'digit 
    -                               (cl:case last
    -                                 ((upper lower) (cl:list* c #\- rest))
    -                                 (cl:t (cl:cons c rest)))))
    -                      ((cl:char-equal c #\_)
    -                       (helper (cl:cdr lst) '_ (cl:cons #\- rest)))
    -                      (cl:t
    -                       (cl:error "Invalid character: ~A" c)))))
    -        (cl:let ((fix (cl:case flag
    -                        ((constant enumvalue) "+")
    -                        (variable "*")
    -                        (cl:t ""))))
    -          (cl:intern
    -           (cl:concatenate
    -            'cl:string
    -            fix
    -            (cl:nreverse (helper (cl:concatenate 'cl:list name) cl:nil cl:nil))
    -            fix)
    -           package))))))
    -
    -;;;SWIG wrapper code ends here
    -
    -
    -(cl:defconstant y 5)
    -
    -(cl:defconstant x (cl:ash 5 -1))
    -
    -(cffi:defcstruct bar
    -        (p :short)
    -        (q :short)
    -        (a :char)
    -        (b :char)
    -        (z :pointer)
    -        (n :pointer))
    -
    -(cffi:defcvar ("my_struct" my_struct)
    - :pointer)
    -
    -(cffi:defcstruct foo
    -        (a :int)
    -        (b :pointer))
    -
    -(cffi:defcfun ("pointer_func" pointer_func) :int
    -  (ClosureFun :pointer)
    -  (p :int))
    -
    -(cffi:defcfun ("func123" func123) :int
    -  (p :pointer)
    -  (q :pointer)
    -  (r :pointer))
    -
    -(cffi:defcfun ("lispsort_double" lispsort_double) :void
    -  (n :int)
    -  (array :pointer))
    -
    -(cffi:defcenum color
    -        :RED
    -        :BLUE
    -        :GREEN)
    -
    - -

    - The SWIG wrapper code refers to the special code which SWIG - may need to use while wrapping C code. You can turn on/off the - generation of this code by using the -[no]swig-lisp - option. You must have noticed that SWIG goes one extra step to - ensure that CFFI does not do automatic lispification of the C - function names. The reason SWIG does this is because quite often - developers want to build a nice CLOS based lispy API, and this one - to one correspondence between C function names and lisp function - name helps. -

    - -

    Maybe you want to have your own convention for generating lisp - function names for corresponding C function names, or you just - want to lispify the names, also, before we forget you want to - export the generated lisp names. To do this, we will use the - SWIG feature directive. -Let's edit the interface file such that the C type "div_t*" is changed - to Lisp type ":my-pointer", we lispify all names, - export everything, and do some more stuff. - -

    -
    -%module test
    -
    -%typemap(cin) div_t* ":my-pointer"
    -
    -%feature("intern_function", "1");
    -%feature("export");
    -
    -%feature("inline") lispsort_double;
    -%feature("intern_function", "my-lispify") lispsort_double;
    -%feature("export", package="'some-other-package") lispsort_double;
    -
    -%rename func123 renamed_cool_func;
    -
    -%ignore "pointer_func";
    -
    -%include "test.h"
    -
    -
    - -

    -The typemap(cin) ensures that for all arguments which are input - to C with the type "div_t*", the ":my-pointer" type be - used. Similarly typemap(cout) are used for all types which - are returned from C. -

    -

    -The feature intern_function ensures that all C names are - interned using the swig-lispify function. The "1" given - to the feature is optional. The use of feature like - %feature("intern_function", "1"); globally enables - interning for everything. If you want to target a single - function, or declaration then use the targeted version of - feature, %feature("intern_function", "my-lispify") - lispsort_double;, here we are using an additional feature - which allows us to use our lispify function. -

    -

    The export feature allows us to export the symbols. If - the package argument is given, then the symbol will be exported to - the specified Lisp package. The inline feature declaims the - declared function as inline. The rename directive allows us to - change the name(it is useful when generating C wrapper code for handling - overloaded functions). The ignore directive ignores a certain - declaration. -

    -

    There are several other things which are possible, to see some - example of usage of SWIG look at the Lispbuilder and wxCL - projects. The generated code with 'noswig-lisp' option is: -

    - -
    -(cl:defconstant #.(swig-lispify "y" 'constant) 5)
    -
    -(cl:export '#.(swig-lispify "y" 'constant))
    -
    -(cl:defconstant #.(swig-lispify "x" 'constant) (cl:ash 5 -1))
    -
    -(cl:export '#.(swig-lispify "x" 'constant))
    -
    -(cffi:defcstruct #.(swig-lispify "bar" 'classname)
    -        (#.(swig-lispify "p" 'slotname) :short)
    -        (#.(swig-lispify "q" 'slotname) :short)
    -        (#.(swig-lispify "a" 'slotname) :char)
    -        (#.(swig-lispify "b" 'slotname) :char)
    -        (#.(swig-lispify "z" 'slotname) :pointer)
    -        (#.(swig-lispify "n" 'slotname) :pointer))
    -
    -(cl:export '#.(swig-lispify "bar" 'classname))
    -
    -(cl:export '#.(swig-lispify "p" 'slotname))
    -
    -(cl:export '#.(swig-lispify "q" 'slotname))
    -
    -(cl:export '#.(swig-lispify "a" 'slotname))
    -
    -(cl:export '#.(swig-lispify "b" 'slotname))
    -
    -(cl:export '#.(swig-lispify "z" 'slotname))
    -
    -(cl:export '#.(swig-lispify "n" 'slotname))
    -
    -(cffi:defcvar ("my_struct" #.(swig-lispify "my_struct" 'variable))
    - :pointer)
    -
    -(cl:export '#.(swig-lispify "my_struct" 'variable))
    -
    -(cffi:defcstruct #.(swig-lispify "foo" 'classname)
    -        (#.(swig-lispify "a" 'slotname) :int)
    -        (#.(swig-lispify "b" 'slotname) :pointer))
    -
    -(cl:export '#.(swig-lispify "foo" 'classname))
    -
    -(cl:export '#.(swig-lispify "a" 'slotname))
    -
    -(cl:export '#.(swig-lispify "b" 'slotname))
    -
    -(cffi:defcfun ("renamed_cool_func" #.(swig-lispify "renamed_cool_func" 'function)) :int
    -  (p :my-pointer)
    -  (q :pointer)
    -  (r :pointer))
    -
    -(cl:export '#.(swig-lispify "renamed_cool_func" 'function))
    -
    -(cl:declaim (cl:inline #.(my-lispify "lispsort_double" 'function)))
    -
    -(cffi:defcfun ("lispsort_double" #.(my-lispify "lispsort_double" 'function)) :void
    -  (n :int)
    -  (array :pointer))
    -
    -(cl:export '#.(my-lispify "lispsort_double" 'function) 'some-other-package)
    -
    -(cffi:defcenum #.(swig-lispify "color" 'enumname)
    -        #.(swig-lispify "RED" 'enumvalue :keyword)
    -        #.(swig-lispify "BLUE" 'enumvalue :keyword)
    -        #.(swig-lispify "GREEN" 'enumvalue :keyword))
    -
    -(cl:export '#.(swig-lispify "color" 'enumname))
    -
    -
    - -

    29.2.3 Generating CFFI bindings for C++ code

    - - -

    This feature to SWIG (for CFFI) is very new and still far from - complete. Pitch in with your patches, bug reports and feature - requests to improve it. -

    -

    Generating bindings for C++ code, requires -c++ option to be - present and it first generates C binding which will wrap the C++ - code, and then generates the - corresponding CFFI wrapper code. In the generated C wrapper - code, you will often want to put your own C code, such as the - code to include various files. This can be done by making use of - "%{" and "%}" as shown below. -

    -
    -%{
    - #include "Test/test.h"
    -%}
    -
    -

    -Also, while parsing the C++ file and generating C wrapper code SWIG - may need to be able to understand various symbols used in other - header files. To help SWIG in doing this while ensuring that - wrapper code is generated for the target file, use the "import" - directive. The "include" directive specifies the target file for - which wrapper code will be generated. -

    -
    -
    -%import "ancillary/header.h"
    -
    -%include "target/header.h"
    -
    -
    -

    -Various features which were available for C headers can also be used - here. The target header which we are going to use here is: -

    -
    -namespace OpenDemo {
    -  class Test
    -  {
    -    public:
    -      float x;
    -      // constructors
    -      Test (void) {x = 0;}
    -      Test (float X) {x = X;}
    -
    -      // vector addition
    -      Test operator+ (const Test& v) const {return Test (x+v.x);}
    -
    -      // length squared
    -      float lengthSquared (void) const {return this->dot (*this);}
    -
    -      static float distance (const Test& a, const Test& b){return(a-b).length();}
    -
    -      inline Test parallelComponent (const Test& unitBasis) const {
    -        return unitBasis * projection;
    -      }
    -
    -      Test setYtoZero (void) const {return Test (this->x);}
    -
    -      static const Test zero;
    -  };
    -
    -  inline Test operator* (float s, const Test& v) {return v*s;}
    -
    -  inline std::ostream& operator<< (std::ostream& o, const Test& v)
    -  {
    -    return o << "(" << v.x << ")";
    -  }
    -
    -  inline Test RandomUnitVectorOnXZPlane (void)
    -  {
    -    return RandomVectorInUnitRadiusSphere().setYtoZero().normalize();
    -  }
    -}
    -
    -

    The interface used is:

    -
    -%module test
    -%include "test.cpp"
    -
    - -

    -SWIG generates 3 files, the first one is a C wrap which we don't show, - the second is the plain CFFI wrapper which is as shown below: -

    -
    -(cffi:defcfun ("_wrap_Test_x_set" Test_x_set) :void
    -  (self :pointer)
    -  (x :float))
    -
    -(cffi:defcfun ("_wrap_Test_x_get" Test_x_get) :float
    -  (self :pointer))
    -
    -(cffi:defcfun ("_wrap_new_Test__SWIG_0" new_Test) :pointer)
    -
    -(cffi:defcfun ("_wrap_new_Test__SWIG_1" new_Test) :pointer
    -  (X :float))
    -
    -(cffi:defcfun ("_wrap_Test___add__" Test___add__) :pointer
    -  (self :pointer)
    -  (v :pointer))
    -
    -(cffi:defcfun ("_wrap_Test_lengthSquared" Test_lengthSquared) :float
    -  (self :pointer))
    -
    -(cffi:defcfun ("_wrap_Test_distance" Test_distance) :float
    -  (a :pointer)
    -  (b :pointer))
    -
    -(cffi:defcfun ("_wrap_Test_parallelComponent" Test_parallelComponent) :pointer
    -  (self :pointer)
    -  (unitBasis :pointer))
    -
    -(cffi:defcfun ("_wrap_Test_setYtoZero" Test_setYtoZero) :pointer
    -  (self :pointer))
    -
    -(cffi:defcvar ("Test_zero" Test_zero)
    - :pointer)
    -
    -(cffi:defcfun ("_wrap_delete_Test" delete_Test) :void
    -  (self :pointer))
    -
    -(cffi:defcfun ("_wrap___mul__" __mul__) :pointer
    -  (s :float)
    -  (v :pointer))
    -
    -(cffi:defcfun ("_wrap___lshift__" __lshift__) :pointer
    -  (o :pointer)
    -  (v :pointer))
    -
    -(cffi:defcfun ("_wrap_RandomUnitVectorOnXZPlane" RandomUnitVectorOnXZPlane) :pointer)
    -
    - -

    -The output is pretty good but it fails in disambiguating overloaded - functions such as the constructor, in this case. One way of - resolving this problem is to make the interface use the rename - directiv, but hopefully there are better solutions. - In addition SWIG also generates, a CLOS file -

    - - -
    -(clos:defclass test()
    -  ((ff :reader ff-pointer)))
    -
    -(clos:defmethod (cl:setf x) (arg0 (obj test))
    -  (Test_x_set (ff-pointer obj) arg0))
    -
    -(clos:defmethod x ((obj test))
    -  (Test_x_get (ff-pointer obj)))
    -
    -(cl:shadow "+")
    -(clos:defmethod + ((obj test) (self test) (v test))
    -  (Test___add__ (ff-pointer obj) (ff-pointer self) (ff-pointer v)))
    -
    -(clos:defmethod length-squared ((obj test) (self test))
    -  (Test_lengthSquared (ff-pointer obj) (ff-pointer self)))
    -
    -(clos:defmethod parallel-component ((obj test) (self test) (unitBasis test))
    -  (Test_parallelComponent (ff-pointer obj) (ff-pointer self) (ff-pointer unitBasis)))
    -
    -(clos:defmethod set-yto-zero ((obj test) (self test))
    -  (Test_setYtoZero (ff-pointer obj) (ff-pointer self)))
    -
    - -

    I agree that the CFFI C++ module needs lot more work. But I hope it - provides a starting point, on which you can base your work of - importing C++ libraries to Lisp. -

    -

    -If you have any questions, suggestions, patches, etc., related to CFFI - module feel free to contact us on the SWIG mailing list, and - also please add a "[CFFI]" tag in the subject line. - -

    29.2.4 Inserting user code into generated files

    - - -

    -It is often necessary to include user-defined code -into the automatically generated interface files. For example, when building -a C++ interface, example_wrap.cxx will likely not compile unless -you add a #include "header.h" directive. This can be done -using the SWIG %insert(section) %{ ...code... %} directive: -

    - -
    -
    -%module example
    -
    -%{
    -#include "header.h"
    -%}
    -
    -%include "header.h"
    -
    -int fact(int n);
    -
    -
    - -

    -Additional sections have been added for inserting into the -generated lisp interface file: -

    -
      -
    • lisphead - inserts before type declarations
    • -
    • swiglisp - inserts after type declarations according to - where it appears in the .i file
    • -
    -

    -Note that the block %{ ... %} is effectively a shortcut for -%insert("header") %{ ... %}. -

    - - - - diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 28c87862c..e28e48149 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -202,46 +202,6 @@ android_clean: rm -f `find $(PACKAGEDIR) -name \*.java | grep -v $(PROJECTNAME).java` rm -rf obj -################################################################## -##### CFFI ###### -################################################################## - -CFFI = @CFFIBIN@ -CFFI_SCRIPT=$(RUNME).lisp - -cffi: $(SRCDIR_SRCS) - $(SWIG) -cffi $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) -# $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCDIR_SRCS) -# $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) - -cffi_cpp: $(SRCDIR_SRCS) - $(SWIG) -c++ -cffi $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) - $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) - -# ----------------------------------------------------------------- -# Run CFFI example -# ----------------------------------------------------------------- - -cffi_run: - $(RUNTOOL) $(CFFI) -batch -s $(CFFI_SCRIPT) $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -cffi_version: - $(CFFI) --version - -# ----------------------------------------------------------------- -# Cleaning the CFFI examples -# ----------------------------------------------------------------- - -cffi_clean: - rm -f *_wrap* *~ .~* - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@SO@ - ################################################################## ##### CSHARP ###### ################################################################## diff --git a/Examples/test-suite/cffi/Makefile.in b/Examples/test-suite/cffi/Makefile.in deleted file mode 100644 index e27b2c85d..000000000 --- a/Examples/test-suite/cffi/Makefile.in +++ /dev/null @@ -1,55 +0,0 @@ -####################################################################### -# Makefile for cffi test-suite -####################################################################### - -LANGUAGE = cffi -CFFI = @CFFIBIN@ -SCRIPTSUFFIX = _runme.lisp - -HAVE_CXX11 = @HAVE_CXX11@ -HAVE_CXX14 = @HAVE_CXX14@ -HAVE_CXX17 = @HAVE_CXX17@ -HAVE_CXX20 = @HAVE_CXX20@ -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -top_builddir = @top_builddir@ - -include $(srcdir)/../common.mk - -# Overridden variables here -# no C++ tests for now -CPP_TEST_CASES = -#C_TEST_CASES += - -# Custom tests - tests with additional commandline options -# none! - -# Rules for the different types of tests -%.cpptest: - $(setup) - +$(swig_and_compile_cpp) - $(run_testcase) - -%.ctest: - $(setup) - +$(swig_and_compile_c) - $(run_testcase) - -%.multicpptest: - $(setup) - +$(swig_and_compile_multi_cpp) - $(run_testcase) - -# Runs the testcase. A testcase is only run if -# a file is found which has _runme.lisp appended after the testcase name. -run_testcase = \ - if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(CFFI) -batch -s $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ - fi - -# Clean: (does nothing, we don't generate extra cffi code) -%.clean: - @exit 0 - -clean: - $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' cffi_clean diff --git a/Lib/cffi/cffi.swg b/Lib/cffi/cffi.swg deleted file mode 100644 index b96d3d4fd..000000000 --- a/Lib/cffi/cffi.swg +++ /dev/null @@ -1,286 +0,0 @@ -/* Define a C preprocessor symbol that can be used in interface files - to distinguish between the SWIG language modules. */ - -#define SWIG_CFFI - -/* Typespecs for basic types. */ - -%typemap(cin) void ":void" - -%typemap(cin) char ":char" -%typemap(cin) char * ":string" -%typemap(cin) unsigned char ":unsigned-char" -%typemap(cin) signed char ":char" - -%typemap(cin) short ":short" -%typemap(cin) signed short ":short" -%typemap(cin) unsigned short ":unsigned-short" - -%typemap(cin) int ":int" -%typemap(cin) signed int ":int" -%typemap(cin) unsigned int ":unsigned-int" - -%typemap(cin) long ":long" -%typemap(cin) signed long ":long" -%typemap(cin) unsigned long ":unsigned-long" - -%typemap(cin) long long ":long-long" -%typemap(cin) signed long long ":long-long" -%typemap(cin) unsigned long long ":unsigned-long-long" - -%typemap(cin) float ":float" -%typemap(cin) double ":double" -%typemap(cin) SWIGTYPE ":pointer" - -%typemap(cout) void ":void" - -%typemap(cout) char ":char" -%typemap(cout) char * ":string" -%typemap(cout) unsigned char ":unsigned-char" -%typemap(cout) signed char ":char" - -%typemap(cout) short ":short" -%typemap(cout) signed short ":short" -%typemap(cout) unsigned short ":unsigned-short" - -%typemap(cout) int ":int" -%typemap(cout) signed int ":int" -%typemap(cout) unsigned int ":unsigned-int" - -%typemap(cout) long ":long" -%typemap(cout) signed long ":long" -%typemap(cout) unsigned long ":unsigned-long" - -%typemap(cout) long long ":long-long" -%typemap(cout) signed long long ":long-long" -%typemap(cout) unsigned long long ":unsigned-long-long" - -%typemap(cout) float ":float" -%typemap(cout) double ":double" -%typemap(cout) SWIGTYPE ":pointer" - - -%typemap(ctype) bool "int" -%typemap(ctype) char, unsigned char, signed char, - short, signed short, unsigned short, - int, signed int, unsigned int, - long, signed long, unsigned long, - float, double, long double, char *, void *, void, - enum SWIGTYPE, SWIGTYPE *, - SWIGTYPE[ANY], SWIGTYPE &, SWIGTYPE && "$1_ltype"; -%typemap(ctype) SWIGTYPE "$&1_type" - -%typemap(in) bool "$1 = (bool)$input;" -%typemap(in) char, unsigned char, signed char, - short, signed short, unsigned short, - int, signed int, unsigned int, - long, signed long, unsigned long, - float, double, long double, char *, void *, void, - enum SWIGTYPE, SWIGTYPE *, - SWIGTYPE[ANY], SWIGTYPE &, SWIGTYPE && "$1 = $input;"; -%typemap(in) SWIGTYPE "$1 = *$input;" - -%typemap(out) void "" -%typemap(out) bool "$result = (int)$1;" -%typemap(out) char, unsigned char, signed char, - short, signed short, unsigned short, - int, signed int, unsigned int, - long, signed long, unsigned long, - float, double, long double, char *, void *, - enum SWIGTYPE, SWIGTYPE *, - SWIGTYPE[ANY], SWIGTYPE &, SWIGTYPE && "$result = $1;"; -#ifdef __cplusplus -%typemap(out) SWIGTYPE -%{ $result = new $1_ltype($1); %} -#else -%typemap(out) SWIGTYPE { - $result = ($&1_ltype) malloc(sizeof($1_type)); - memmove($result, &$1, sizeof($1_type)); -} -#endif - -%typecheck(SWIG_TYPECHECK_BOOL) bool { $1 = 1; }; -%typecheck(SWIG_TYPECHECK_CHAR) char { $1 = 1; }; -%typecheck(SWIG_TYPECHECK_FLOAT) float { $1 = 1; }; -%typecheck(SWIG_TYPECHECK_DOUBLE) double { $1 = 1; }; -%typecheck(SWIG_TYPECHECK_STRING) char * { $1 = 1; }; -%typecheck(SWIG_TYPECHECK_INTEGER) - unsigned char, signed char, - short, signed short, unsigned short, - int, signed int, unsigned int, - long, signed long, unsigned long, - enum SWIGTYPE { $1 = 1; }; -%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, - SWIGTYPE[ANY], SWIGTYPE { $1 = 1; }; -/* This maps C/C++ types to Lisp classes for overload dispatch */ - -%typemap(lisptype) bool "cl:boolean" -%typemap(lisptype) char "cl:character" -%typemap(lisptype) unsigned char "cl:integer" -%typemap(lisptype) signed char "cl:integer" - -%typemap(lispclass) bool "t" -%typemap(lispclass) char "cl:character" -%typemap(lispclass) unsigned char, signed char, - short, signed short, unsigned short, - int, signed int, unsigned int, - long, signed long, unsigned long, - enum SWIGTYPE "cl:integer"; -/* CLOS methods can't be specialized on single-float or double-float */ -%typemap(lispclass) float "cl:number" -%typemap(lispclass) double "cl:number" -%typemap(lispclass) char * "cl:string" - -/* Array reference typemaps */ -%apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) } -%apply SWIGTYPE && { SWIGTYPE ((&&)[ANY]) } - -/* const pointers */ -%apply SWIGTYPE * { SWIGTYPE *const } -%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } -%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } - -%{ - -#ifdef __cplusplus -# define EXTERN extern "C" -#else -# define EXTERN extern -#endif - -#define EXPORT EXTERN SWIGEXPORT - -#include -%} - -%insert("swiglisp") %{ -;;;SWIG wrapper code starts here - -(cl:defmacro defanonenum (cl:&body enums) - "Converts anonymous enums to defconstants." - `(cl:progn ,@(cl:loop for value in enums - for index = 0 then (cl:1+ index) - when (cl:listp value) do (cl:setf index (cl:second value) - value (cl:first value)) - collect `(cl:defconstant ,value ,index)))) - -(cl:eval-when (:compile-toplevel :load-toplevel) - (cl:unless (cl:fboundp 'swig-lispify) - (cl:defun swig-lispify (name flag cl:&optional (package cl:*package*)) - (cl:labels ((helper (lst last rest cl:&aux (c (cl:car lst))) - (cl:cond - ((cl:null lst) - rest) - ((cl:upper-case-p c) - (helper (cl:cdr lst) 'upper - (cl:case last - ((lower digit) (cl:list* c #\- rest)) - (cl:t (cl:cons c rest))))) - ((cl:lower-case-p c) - (helper (cl:cdr lst) 'lower (cl:cons (cl:char-upcase c) rest))) - ((cl:digit-char-p c) - (helper (cl:cdr lst) 'digit - (cl:case last - ((upper lower) (cl:list* c #\- rest)) - (cl:t (cl:cons c rest))))) - ((cl:char-equal c #\_) - (helper (cl:cdr lst) '_ (cl:cons #\- rest))) - (cl:t - (cl:error "Invalid character: ~A" c))))) - (cl:let ((fix (cl:case flag - ((constant enumvalue) "+") - (variable "*") - (cl:t "")))) - (cl:intern - (cl:concatenate - 'cl:string - fix - (cl:nreverse (helper (cl:concatenate 'cl:list name) cl:nil cl:nil)) - fix) - package)))))) - -;;;SWIG wrapper code ends here -%} - -////////////////////////////////////////////////////////////// - -/* name conversion for overloaded operators. */ -#ifdef __cplusplus -%rename(__add__) *::operator+; -%rename(__pos__) *::operator+(); -%rename(__pos__) *::operator+() const; - -%rename(__sub__) *::operator-; -%rename(__neg__) *::operator-() const; -%rename(__neg__) *::operator-(); - -%rename(__mul__) *::operator*; -%rename(__deref__) *::operator*(); -%rename(__deref__) *::operator*() const; - -%rename(__div__) *::operator/; -%rename(__mod__) *::operator%; -%rename(__logxor__) *::operator^; -%rename(__logand__) *::operator&; -%rename(__logior__) *::operator|; -%rename(__lognot__) *::operator~(); -%rename(__lognot__) *::operator~() const; - -%rename(__not__) *::operator!(); -%rename(__not__) *::operator!() const; - -%rename(__assign__) *::operator=; - -%rename(__add_assign__) *::operator+=; -%rename(__sub_assign__) *::operator-=; -%rename(__mul_assign__) *::operator*=; -%rename(__div_assign__) *::operator/=; -%rename(__mod_assign__) *::operator%=; -%rename(__logxor_assign__) *::operator^=; -%rename(__logand_assign__) *::operator&=; -%rename(__logior_assign__) *::operator|=; - -%rename(__lshift__) *::operator<<; -%rename(__lshift_assign__) *::operator<<=; -%rename(__rshift__) *::operator>>; -%rename(__rshift_assign__) *::operator>>=; - -%rename(__eq__) *::operator==; -%rename(__ne__) *::operator!=; -%rename(__lt__) *::operator<; -%rename(__gt__) *::operator>; -%rename(__lte__) *::operator<=; -%rename(__gte__) *::operator>=; - -%rename(__and__) *::operator&&; -%rename(__or__) *::operator||; - -%rename(__preincr__) *::operator++(); -%rename(__postincr__) *::operator++(int); -%rename(__predecr__) *::operator--(); -%rename(__postdecr__) *::operator--(int); - -%rename(__comma__) *::operator,(); -%rename(__comma__) *::operator,() const; - -%rename(__member_ref__) *::operator->; -%rename(__member_func_ref__) *::operator->*; - -%rename(__funcall__) *::operator(); -%rename(__aref__) *::operator[]; -#endif - - -%{ - -#ifdef __cplusplus -# define EXTERN extern "C" -#else -# define EXTERN extern -#endif - -#define EXPORT EXTERN SWIGEXPORT - -#include -#include -%} diff --git a/Source/Modules/cffi.cxx b/Source/Modules/cffi.cxx deleted file mode 100644 index f517ef1d3..000000000 --- a/Source/Modules/cffi.cxx +++ /dev/null @@ -1,1171 +0,0 @@ -/* ----------------------------------------------------------------------------- - * 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. - * - * cffi.cxx - * - * cffi language module for SWIG. - * ----------------------------------------------------------------------------- */ - -#include "swigmod.h" -#include "cparse.h" -#include - -//#define CFFI_DEBUG -//#define CFFI_WRAP_DEBUG - -static const char *usage = "\ -CFFI Options (available with -cffi)\n\ - -generate-typedef - Use defctype to generate shortcuts according to the\n\ - typedefs in the input.\n\ - -[no]cwrap - Turn on or turn off generation of an intermediate C\n\ - file when creating a C interface. By default this is\n\ - only done for C++ code.\n\ - -[no]swig-lisp - Turn on or off generation of code for helper lisp\n\ - macro, functions, etc. which SWIG uses while\n\ - generating wrappers. These macros, functions may still\n\ - be used by generated wrapper code.\n\ -"; - -class CFFI:public Language { -public: - String *f_cl; - String *f_clhead; - String *f_clwrap; - bool CWrap; // generate wrapper file for C code? - File *f_begin; - File *f_runtime; - File *f_cxx_header; - File *f_cxx_wrapper; - File *f_clos; - - String *module; - virtual void main(int argc, char *argv[]); - virtual int top(Node *n); - virtual int functionWrapper(Node *n); - virtual int variableWrapper(Node *n); - virtual int constantWrapper(Node *n); - // virtual int classDeclaration(Node *n); - virtual int enumDeclaration(Node *n); - virtual int typedefHandler(Node *n); - - //c++ specific code - virtual int constructorHandler(Node *n); - virtual int destructorHandler(Node *n); - virtual int memberfunctionHandler(Node *n); - virtual int membervariableHandler(Node *n); - virtual int classHandler(Node *n); - -private: - static void checkConstraints(ParmList *parms, Wrapper *f); - static void argout(ParmList *parms, Wrapper *f); - static String *freearg(ParmList *parms); - static void cleanupFunction(Node *n, Wrapper *f, ParmList *parms); - - void emit_defun(Node *n, String *name); - void emit_defmethod(Node *n); - void emit_initialize_instance(Node *n); - void emit_getter(Node *n); - void emit_setter(Node *n); - void emit_class(Node *n); - void emit_struct_union(Node *n, bool un); - void emit_export(Node *n, String *name); - void emit_inline(Node *n, String *name); - String *lispy_name(char *name); - String *lispify_name(Node *n, String *ty, const char *flag, bool kw = false); - String *convert_literal(String *num_param, String *type, bool try_to_split = true); - String *infix_to_prefix(String *val, char split_op, const String *op, String *type); - String *strip_parens(String *string); - String *trim(String *string); - int generate_typedef_flag; - bool no_swig_lisp; -}; - -void CFFI::main(int argc, char *argv[]) { - int i; - - Preprocessor_define("SWIGCFFI 1", 0); - SWIG_library_directory("cffi"); - SWIG_config_file("cffi.swg"); - generate_typedef_flag = 0; - no_swig_lisp = false; - CWrap = false; - for (i = 1; i < argc; i++) { - if (!Strcmp(argv[i], "-help")) { - Printf(stdout, "%s\n", usage); - } else if (!strcmp(argv[i], "-cwrap")) { - CWrap = true; - Swig_mark_arg(i); - } else if ((Strcmp(argv[i], "-generate-typedef") == 0)) { - generate_typedef_flag = 1; - Swig_mark_arg(i); - } else if (!strcmp(argv[i], "-nocwrap")) { - CWrap = false; - Swig_mark_arg(i); - } else if (!strcmp(argv[i], "-swig-lisp")) { - no_swig_lisp = false; - Swig_mark_arg(i); - } else if (!strcmp(argv[i], "-noswig-lisp")) { - no_swig_lisp = true; - Swig_mark_arg(i); - } - - } - f_clhead = NewString(""); - f_clwrap = NewString(""); - f_cl = NewString(""); - - allow_overloading(); -} - -int CFFI::top(Node *n) { - File *f_null = NewString(""); - module = Getattr(n, "name"); - - String *cxx_filename = Getattr(n, "outfile"); - String *lisp_filename = NewString(""); - - Printf(lisp_filename, "%s%s.lisp", SWIG_output_directory(), module); - - File *f_lisp = NewFile(lisp_filename, "w", SWIG_output_files()); - if (!f_lisp) { - FileErrorDisplay(lisp_filename); - Exit(EXIT_FAILURE); - } - - if (CPlusPlus || CWrap) { - f_begin = NewFile(cxx_filename, "w", SWIG_output_files()); - if (!f_begin) { - Delete(f_lisp); - Printf(stderr, "Unable to open %s for writing\n", cxx_filename); - Exit(EXIT_FAILURE); - } - - String *clos_filename = NewString(""); - Printf(clos_filename, "%s%s-clos.lisp", SWIG_output_directory(), module); - f_clos = NewFile(clos_filename, "w", SWIG_output_files()); - if (!f_clos) { - Delete(f_lisp); - Printf(stderr, "Unable to open %s for writing\n", cxx_filename); - Exit(EXIT_FAILURE); - } - } else { - f_begin = NewString(""); - f_clos = NewString(""); - } - - f_runtime = NewString(""); - f_cxx_header = f_runtime; - f_cxx_wrapper = NewString(""); - - Swig_register_filebyname("header", f_cxx_header); - Swig_register_filebyname("wrapper", f_cxx_wrapper); - Swig_register_filebyname("begin", f_begin); - Swig_register_filebyname("runtime", f_runtime); - Swig_register_filebyname("lisphead", f_clhead); - if (!no_swig_lisp) - Swig_register_filebyname("swiglisp", f_cl); - else - Swig_register_filebyname("swiglisp", f_null); - - Swig_banner(f_begin); - - Printf(f_runtime, "\n\n#ifndef SWIGCFFI\n#define SWIGCFFI\n#endif\n\n"); - - Swig_banner_target_lang(f_lisp, ";;;"); - - Language::top(n); - Printf(f_lisp, "%s\n", f_clhead); - Printf(f_lisp, "%s\n", f_cl); - Printf(f_lisp, "%s\n", f_clwrap); - - Delete(f_lisp); - Delete(f_cl); - Delete(f_clhead); - Delete(f_clwrap); - Dump(f_runtime, f_begin); - Delete(f_runtime); - Delete(f_begin); - Delete(f_cxx_wrapper); - Delete(f_null); - - return SWIG_OK; -} - -int CFFI::classHandler(Node *n) { -#ifdef CFFI_DEBUG - Printf(stderr, "class %s::%s\n", "some namespace", //current_namespace, - Getattr(n, "sym:name")); -#endif - String *name = Getattr(n, "sym:name"); - String *kind = Getattr(n, "kind"); - - // maybe just remove this check and get rid of the else clause below. - if (Strcmp(kind, "struct") == 0) { - emit_struct_union(n, false); - return SWIG_OK; - } else if (Strcmp(kind, "union") == 0) { - emit_struct_union(n, true); - return SWIG_OK; - } else if (Strcmp(kind, "class") == 0) { - emit_class(n); - Language::classHandler(n); - } else { - Printf(stderr, "Don't know how to deal with %s kind of class yet.\n", kind); - Printf(stderr, " (name: %s)\n", name); - Exit(EXIT_FAILURE); - return SWIG_OK; - } - - return SWIG_OK; -} - -int CFFI::constructorHandler(Node *n) { -#ifdef CFFI_DEBUG - Printf(stderr, "constructor %s\n", Getattr(n, "name")); - Printf(stderr, "constructor %s\n and %s", Getattr(n, "kind"), Getattr(n, "sym:name")); -#endif - Setattr(n, "cffi:constructorfunction", "1"); - // Let SWIG generate a global forwarding function. - return Language::constructorHandler(n); -} - -int CFFI::destructorHandler(Node *n) { -#ifdef CFFI_DEBUG - Printf(stderr, "destructor %s\n", Getattr(n, "name")); -#endif - - // Let SWIG generate a global forwarding function. - return Language::destructorHandler(n); -} - -void CFFI::emit_defmethod(Node *n) { - String *args_placeholder = NewStringf(""); - String *args_call = NewStringf(""); - - ParmList *pl = Getattr(n, "parms"); - int argnum = 0; - Node *parent = getCurrentClass(); - bool first = 0; - - for (Parm *p = pl; p; p = nextSibling(p), argnum++) { - String *argname = Getattr(p, "name"); - String *ffitype = Swig_typemap_lookup("lispclass", p, "", 0); - - int tempargname = 0; - - if(!first) - first = true; - else - Printf(args_placeholder, " "); - - if (!argname) { - argname = NewStringf("arg%d", argnum); - tempargname = 1; - } else if (Strcmp(argname, "t") == 0 || Strcmp(argname, "T") == 0) { - argname = NewStringf("t-arg%d", argnum); - tempargname = 1; - } - if (Len(ffitype) > 0) - Printf(args_placeholder, "(%s %s)", argname, ffitype); - else - Printf(args_placeholder, "%s", argname); - - if (ffitype && Strcmp(ffitype, lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'classname")) == 0) - Printf(args_call, " (ff-pointer %s)", argname); - else - Printf(args_call, " %s", argname); - - Delete(ffitype); - - if (tempargname) - Delete(argname); - } - - String *method_name = Getattr(n, "name"); - int x = Replace(method_name, "operator ", "", DOH_REPLACE_FIRST); // - - if (x == 1) - Printf(f_clos, "(cl:shadow \"%s\")\n", method_name); - - Printf(f_clos, "(cl:defmethod %s (%s)\n (%s%s))\n\n", - lispify_name(n, lispy_name(Char(method_name)), "'method"), args_placeholder, - lispify_name(n, Getattr(n, "sym:name"), "'function"), args_call); - -} - -void CFFI::emit_initialize_instance(Node *n) { - String *args_placeholder = NewStringf(""); - String *args_call = NewStringf(""); - - ParmList *pl = Getattr(n, "parms"); - int argnum = 0; - Node *parent = getCurrentClass(); - - for (Parm *p = pl; p; p = nextSibling(p), argnum++) { - String *argname = Getattr(p, "name"); - String *ffitype = Swig_typemap_lookup("lispclass", p, "", 0); - - int tempargname = 0; - if (!argname) { - argname = NewStringf("arg%d", argnum); - tempargname = 1; - } else if (Strcmp(argname, "t") == 0 || Strcmp(argname, "T") == 0) { - argname = NewStringf("t-arg%d", argnum); - tempargname = 1; - } - if (Len(ffitype) > 0) - Printf(args_placeholder, " (%s %s)", argname, ffitype); - else - Printf(args_placeholder, " %s", argname); - - if (ffitype && Strcmp(ffitype, lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'classname")) == 0) - Printf(args_call, " (ff-pointer %s)", argname); - else - Printf(args_call, " %s", argname); - - Delete(ffitype); - - if (tempargname) - Delete(argname); - } - - Printf(f_clos, "(cl:defmethod initialize-instance :after ((obj %s) &key%s)\n (setf (slot-value obj 'ff-pointer) (%s%s)))\n\n", - lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'class"), args_placeholder, - lispify_name(n, Getattr(n, "sym:name"), "'function"), args_call); - -} - -void CFFI::emit_setter(Node *n) { - Node *parent = getCurrentClass(); - Printf(f_clos, "(cl:defmethod (cl:setf %s) (arg0 (obj %s))\n (%s (ff-pointer obj) arg0))\n\n", - lispify_name(n, Getattr(n, "name"), "'method"), - lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'class"), lispify_name(n, Getattr(n, "sym:name"), "'function")); -} - - -void CFFI::emit_getter(Node *n) { - Node *parent = getCurrentClass(); - Printf(f_clos, "(cl:defmethod %s ((obj %s))\n (%s (ff-pointer obj)))\n\n", - lispify_name(n, Getattr(n, "name"), "'method"), - lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'class"), lispify_name(n, Getattr(n, "sym:name"), "'function")); -} - -int CFFI::memberfunctionHandler(Node *n) { - // Let SWIG generate a global forwarding function. - Setattr(n, "cffi:memberfunction", "1"); - return Language::memberfunctionHandler(n); -} - -int CFFI::membervariableHandler(Node *n) { - // Let SWIG generate a get/set function pair. - Setattr(n, "cffi:membervariable", "1"); - return Language::membervariableHandler(n); -} - - -void CFFI::checkConstraints(ParmList *parms, Wrapper *f) { - Parm *p = parms; - while (p) { - String *tm = Getattr(p, "tmap:check"); - if (!tm) { - p = nextSibling(p); - } else { - tm = Copy(tm); - Replaceall(tm, "$input", Getattr(p, "emit:input")); - Printv(f->code, tm, "\n\n", NULL); - Delete(tm); - p = Getattr(p, "tmap:check:next"); - } - } -} - -void CFFI::argout(ParmList *parms, Wrapper *f) { - Parm *p = parms; - while (p) { - String *tm = Getattr(p, "tmap:argout"); - if (!tm) { - p = nextSibling(p); - } else { - tm = Copy(tm); - Replaceall(tm, "$result", Swig_cresult_name()); - Replaceall(tm, "$input", Getattr(p, "emit:input")); - Printv(f->code, tm, "\n", NULL); - Delete(tm); - p = Getattr(p, "tmap:argout:next"); - } - } -} - -String *CFFI::freearg(ParmList *parms) { - String *ret = NewString(""); - Parm *p = parms; - while (p) { - String *tm = Getattr(p, "tmap:freearg"); - if (!tm) { - p = nextSibling(p); - } else { - tm = Copy(tm); - Replaceall(tm, "$input", Getattr(p, "emit:input")); - Printv(ret, tm, "\n", NULL); - Delete(tm); - p = Getattr(p, "tmap:freearg:next"); - } - } - return ret; -} - -void CFFI::cleanupFunction(Node *n, Wrapper *f, ParmList *parms) { - String *cleanup = freearg(parms); - Printv(f->code, cleanup, NULL); - - if (GetFlag(n, "feature:new")) { - String *tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0); - if (tm) { - Printv(f->code, tm, "\n", NULL); - Delete(tm); - } - } - - Replaceall(f->code, "$cleanup", cleanup); - Delete(cleanup); - - Replaceall(f->code, "$symname", Getattr(n, "sym:name")); -} - -int CFFI::functionWrapper(Node *n) { - - ParmList *parms = Getattr(n, "parms"); - String *iname = Getattr(n, "sym:name"); - Wrapper *f = NewWrapper(); - - String *raw_return_type = Swig_typemap_lookup("ctype", n, "", 0); - SwigType *return_type = Swig_cparse_type(raw_return_type); - SwigType *resolved = SwigType_typedef_resolve_all(return_type); - int is_void_return = (Cmp(resolved, "void") == 0); - Delete(resolved); - - if (!is_void_return) { - String *lresult_init = NewStringf("lresult = (%s)0", raw_return_type); - Wrapper_add_localv(f, "lresult", raw_return_type, lresult_init, NIL); - Delete(lresult_init); - } - - String *overname = 0; - if (Getattr(n, "sym:overloaded")) { - overname = Getattr(n, "sym:overname"); - } else { - if (!addSymbol(iname, n)) { - DelWrapper(f); - return SWIG_ERROR; - } - } - - String *wname = Swig_name_wrapper(iname); - if (overname) { - Append(wname, overname); - } - Setattr(n, "wrap:name", wname); - - // Emit all of the local variables for holding arguments. - emit_parameter_variables(parms, f); - - // Attach the standard typemaps - Swig_typemap_attach_parms("ctype", parms, f); - emit_attach_parmmaps(parms, f); - - int num_arguments = emit_num_arguments(parms); - String *name_and_parms = NewStringf("%s (", wname); - int i; - Parm *p; - int gencomma = 0; - -#ifdef CFFI_DEBUG - Printf(stderr, "function - %s - %d\n", Getattr(n, "name"), num_arguments); -#endif - - for (i = 0, p = parms; i < num_arguments; i++) { - - while (checkAttribute(p, "tmap:in:numinputs", "0")) { - p = Getattr(p, "tmap:in:next"); - } - - SwigType *c_parm_type = Swig_cparse_type(Getattr(p, "tmap:ctype")); - String *arg = NewStringf("l%s", Getattr(p, "lname")); - - // Emit parameter declaration - if (gencomma) - Printf(name_and_parms, ", "); - String *parm_decl = SwigType_str(c_parm_type, arg); - Printf(name_and_parms, "%s", parm_decl); -#ifdef CFFI_DEBUG - Printf(stderr, " param: %s\n", parm_decl); -#endif - Delete(parm_decl); - gencomma = 1; - - // Emit parameter conversion code - String *parm_code = Getattr(p, "tmap:in"); - { - Replaceall(parm_code, "$input", arg); - Setattr(p, "emit:input", arg); - Printf(f->code, "%s\n", parm_code); - p = Getattr(p, "tmap:in:next"); - } - - Delete(arg); - } - Printf(name_and_parms, ")"); - - // Emit the function definition - String *signature = SwigType_str(return_type, name_and_parms); - Printf(f->def, "EXPORT %s {", signature); - - checkConstraints(parms, f); - - Printf(f->code, " try {\n"); - - String *actioncode = emit_action(n); - - String *result_convert = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode); - if (result_convert) { - Replaceall(result_convert, "$result", "lresult"); - Printf(f->code, "%s\n", result_convert); - } - Delete(result_convert); - - argout(parms, f); - - cleanupFunction(n, f, parms); - - /* See if there is any return cleanup code */ - String *tm = 0; - if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) { - Printf(f->code, "%s\n", tm); - Delete(tm); - } - - if (!is_void_return) { - Printf(f->code, " return lresult;\n"); - } - - emit_return_variable(n, Getattr(n, "type"), f); - - Printf(f->code, " } catch (...) {\n"); - if (!is_void_return) - Printf(f->code, " return (%s)0;\n", raw_return_type); - Printf(f->code, " }\n"); - Printf(f->code, "}\n"); - - if (CPlusPlus) - Wrapper_print(f, f_runtime); - - if (CPlusPlus) { - emit_defun(n, wname); - if (Getattr(n, "cffi:memberfunction")) - emit_defmethod(n); - else if (Getattr(n, "cffi:membervariable")) { - if (Getattr(n, "memberget")) - emit_getter(n); - else if (Getattr(n, "memberset")) - emit_setter(n); - } - else if (Getattr(n, "cffi:constructorfunction")) { - emit_initialize_instance(n); - } - } else - emit_defun(n, iname); - - // if (!overloaded || !Getattr(n, "sym:nextSibling")) { - // update_package_if_needed(n); - // emit_buffered_defuns(n); - // // this is the last overload. - // if (overloaded) { - // emit_dispatch_defun(n); - // } - // } - - Delete(wname); - DelWrapper(f); - - return SWIG_OK; -} - - -void CFFI::emit_defun(Node *n, String *name) { - String *func_name = Getattr(n, "sym:name"); - - ParmList *pl = Getattr(n, "parms"); - - int argnum = 0; - - func_name = lispify_name(n, func_name, "'function"); - - emit_inline(n, func_name); - - Printf(f_cl, "\n(cffi:defcfun (\"%s\" %s)", name, func_name); - String *ffitype = Swig_typemap_lookup("cout", n, ":pointer", 0); - - Printf(f_cl, " %s", ffitype); - Delete(ffitype); - - for (Parm *p = pl; p; p = nextSibling(p), argnum++) { - - if (SwigType_isvarargs(Getattr(p, "type"))) { - Printf(f_cl, "\n %s", NewString("&rest")); - continue; - } - - String *argname = Getattr(p, "name"); - - ffitype = Swig_typemap_lookup("cin", p, "", 0); - - int tempargname = 0; - if (!argname) { - - argname = NewStringf("arg%d", argnum); - tempargname = 1; - } else if (Strcmp(argname, "t") == 0 || Strcmp(argname, "T") == 0) { - argname = NewStringf("t_arg%d", argnum); - tempargname = 1; - } - - Printf(f_cl, "\n (%s %s)", argname, ffitype); - - Delete(ffitype); - - if (tempargname) - Delete(argname); - } - Printf(f_cl, ")\n"); /* finish arg list */ - - emit_export(n, func_name); -} - - -int CFFI::constantWrapper(Node *n) { - String *type = Getattr(n, "type"); - String *converted_value; - if (SwigType_type(type) == T_STRING) { - converted_value = NewString(Getattr(n, "rawval")); - } else { - converted_value = convert_literal(Getattr(n, "value"), type); - } - - String *name = lispify_name(n, Getattr(n, "sym:name"), "'constant"); - - if (Strcmp(name, "t") == 0 || Strcmp(name, "T") == 0) - name = NewStringf("t_var"); - - Printf(f_cl, "\n(cl:defconstant %s %s)\n", name, converted_value); - Delete(converted_value); - - emit_export(n, name); - return SWIG_OK; -} - -int CFFI::variableWrapper(Node *n) { - String *var_name = Getattr(n, "sym:name"); - String *lisp_type = Swig_typemap_lookup("cin", n, "", 0); - String *lisp_name = lispify_name(n, var_name, "'variable"); - - if (Strcmp(lisp_name, "t") == 0 || Strcmp(lisp_name, "T") == 0) - lisp_name = NewStringf("t_var"); - - Printf(f_cl, "\n(cffi:defcvar (\"%s\" %s)\n %s)\n", var_name, lisp_name, lisp_type); - - Delete(lisp_type); - - emit_export(n, lisp_name); - return SWIG_OK; -} - -int CFFI::typedefHandler(Node *n) { - if (generate_typedef_flag && strncmp(Char(Getattr(n, "type")), "enum", 4)) { - String *lisp_name = lispify_name(n, Getattr(n, "name"), "'typename"); - Printf(f_cl, "\n(cffi:defctype %s %s)\n", lisp_name, Swig_typemap_lookup("cin", n, "", 0)); - emit_export(n, lisp_name); - } - return Language::typedefHandler(n); -} - -int CFFI::enumDeclaration(Node *n) { - if (getCurrentClass() && (cplus_mode != PUBLIC)) - return SWIG_NOWRAP; - - String *name = Getattr(n, "sym:name"); - bool slot_name_keywords; - String *lisp_name = 0; - if (name && Len(name) != 0) { - lisp_name = lispify_name(n, name, "'enumname"); - if (GetFlag(n, "feature:bitfield")) { - Printf(f_cl, "\n(cffi:defbitfield %s", lisp_name); - } else { - Printf(f_cl, "\n(cffi:defcenum %s", lisp_name); - } - slot_name_keywords = true; - - //Registering the enum name to the cin and cout typemaps - Parm *pattern = NewParm(name, NULL, n); - Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL); - Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL); - Delete(pattern); - //Registering with the kind, i.e., enum - pattern = NewParm(NewStringf("enum %s", name), NULL, n); - Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL); - Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL); - Delete(pattern); - - } else { - Printf(f_cl, "\n(defanonenum %s", name); - slot_name_keywords = false; - } - - for (Node *c = firstChild(n); c; c = nextSibling(c)) { - - String *slot_name = lispify_name(c, Getattr(c, "name"), "'enumvalue", slot_name_keywords); - String *value = Getattr(c, "enumvalue"); - - if (!value || GetFlag(n, "feature:bitfield:ignore_values")) - Printf(f_cl, "\n\t%s", slot_name); - else { - String *type = Getattr(c, "type"); - String *converted_value = convert_literal(value, type); - Printf(f_cl, "\n\t(%s #.%s)", slot_name, converted_value); - Delete(converted_value); - } - Delete(value); - } - - Printf(f_cl, ")\n"); - - // No need to export keywords - if (lisp_name && Len(lisp_name) != 0) { - emit_export(n, lisp_name); - } else { - for (Node *c = firstChild(n); c; c = nextSibling(c)) - emit_export(c, lispify_name(c, Getattr(c, "name"), "'enumvalue")); - } - - return SWIG_OK; -} -void CFFI::emit_class(Node *n) { - -#ifdef CFFI_WRAP_DEBUG - Printf(stderr, "emit_class: ENTER... '%s'(%p)\n", Getattr(n, "sym:name"), n); -#endif - - String *name = Getattr(n, "sym:name"); - String *lisp_name = lispify_name(n, lispy_name(Char(name)), "'classname"); - - String *bases = Getattr(n, "bases"); - String *supers = NewString("("); - if (bases) { - int first = 1; - for (Iterator i = First(bases); i.item; i = Next(i)) { - if (!first) - Printf(supers, " "); - String *s = Getattr(i.item, "name"); - Printf(supers, "%s", lispify_name(i.item, lispy_name(Char(s)), "'classname")); - } - } else { - // Printf(supers,"ff:foreign-pointer"); - } - - Printf(supers, ")"); - Printf(f_clos, "\n(cl:defclass %s%s", lisp_name, supers); - Printf(f_clos, "\n ((ff-pointer :reader ff-pointer)))\n\n"); - - Parm *pattern = NewParm(Getattr(n, "name"), NULL, n); - - Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL); - SwigType_add_pointer(Getattr(pattern, "type")); - Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL); - SwigType_add_qualifier(Getattr(pattern, "type"), "const"); - Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL); - SwigType_del_pointer(Getattr(pattern, "type")); - SwigType_add_reference(Getattr(pattern, "type")); - Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL); - -#ifdef CFFI_WRAP_DEBUG - Printf(stderr, " pattern %s name %s .. ... %s .\n", pattern, lisp_name); -#endif - - Delete(pattern); - - // Walk children to generate type definition. - String *slotdefs = NewString(" "); - -#ifdef CFFI_WRAP_DEBUG - Printf(stderr, " walking children...\n"); -#endif - - Node *c; - for (c = firstChild(n); c; c = nextSibling(c)) { - String *storage_type = Getattr(c, "storage"); - if ((!Strcmp(nodeType(c), "cdecl") && (!storage_type || Strcmp(storage_type, "typedef")))) { - String *access = Getattr(c, "access"); - - // hack. why would decl have a value of "variableHandler" and now "0"? - String *childDecl = Getattr(c, "decl"); - // Printf(stderr,"childDecl = '%s' (%s)\n", childDecl, Getattr(c,"view")); - if (!Strcmp(childDecl, "0")) - childDecl = NewString(""); - - SwigType *childType = NewStringf("%s%s", childDecl, - Getattr(c, "type")); - String *cname = (access && Strcmp(access, "public")) ? NewString("nil") : Copy(Getattr(c, "name")); - - if (!SwigType_isfunction(childType)) { - // Printf(slotdefs, ";;; member functions don't appear as slots.\n "); - // Printf(slotdefs, ";; "); - // String *ns = listify_namespace(Getattr(n, "cffi:package")); - String *ns = NewString(""); -#ifdef CFFI_WRAP_DEBUG - Printf(stderr, "slot name = '%s' ns = '%s' class-of '%s' and type = '%s'\n", cname, ns, name, childType); -#endif - Printf(slotdefs, "(#.(swig-insert-id \"%s\" %s :type :slot :class \"%s\") %s)", cname, ns, name, childType); //compose_foreign_type(childType) - Delete(ns); - if (access && Strcmp(access, "public")) - Printf(slotdefs, " ;; %s member", access); - - Printf(slotdefs, "\n "); - } - Delete(childType); - Delete(cname); - } - } - - - // String *ns_list = listify_namespace(Getattr(n,"cffi:namespace")); - // update_package_if_needed(n,f_clhead); - // Printf(f_clos, - // "(swig-def-foreign-class \"%s\"\n %s\n (:%s\n%s))\n\n", - // name, supers, kind, slotdefs); - - Delete(supers); - // Delete(ns_list); - - // Parm *pattern = NewParm(name, NULL, n); - // Swig_typemap_register("cin",pattern,lisp_name,NULL,NULL); - //Swig_typemap_register("cout",pattern,lisp_name,NULL,NULL); - //Delete(pattern); - -#ifdef CFFI_WRAP_DEBUG - Printf(stderr, "emit_class: EXIT\n"); -#endif -} - -// Includes structs -void CFFI::emit_struct_union(Node *n, bool un = false) { -#ifdef CFFI_DEBUG - Printf(stderr, "struct/union %s\n", Getattr(n, "name")); - Printf(stderr, "struct/union %s\n and %s", Getattr(n, "kind"), Getattr(n, "sym:name")); -#endif - - String *name = Getattr(n, "sym:name"); - String *kind = Getattr(n, "kind"); - - if (Strcmp(kind, "struct") != 0 && Strcmp(kind, "union") != 0) { - Printf(stderr, "Don't know how to deal with %s kind of class yet.\n", kind); - Printf(stderr, " (name: %s)\n", name); - Exit(EXIT_FAILURE); - } - String *lisp_name = lispify_name(n, name, "'classname"); - - //Register the struct/union name to the cin and cout typemaps - - Parm *pattern = NewParm(name, NULL, n); - Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL); - Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL); - Delete(pattern); - //Registering with the kind, i.e., struct or union - pattern = NewParm(NewStringf("%s %s", kind, name), NULL, n); - Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL); - Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL); - Delete(pattern); - - if (un) { - Printf(f_cl, "\n(cffi:defcunion %s", lisp_name); - } else - Printf(f_cl, "\n(cffi:defcstruct %s", lisp_name); - - - for (Node *c = firstChild(n); c; c = nextSibling(c)) { -#ifdef CFFI_DEBUG - Printf(stderr, "struct/union %s\n", Getattr(c, "name")); - Printf(stderr, "struct/union %s and %s \n", Getattr(c, "kind"), Getattr(c, "sym:name")); -#endif - - if (Strcmp(nodeType(c), "cdecl")) { - //C declaration ignore - // Printf(stderr, "Structure %s has a slot that we can't deal with.\n", - // name); - // Printf(stderr, "nodeType: %s, name: %s, type: %s\n", - // nodeType(c), - // Getattr(c, "name"), - // Getattr(c, "type")); - // Exit(EXIT_FAILURE); - } else { - SwigType *childType = NewStringf("%s%s", Getattr(c, "decl"), Getattr(c, "type")); - - Node *node = NewHash(); - Setattr(node, "type", childType); - Setfile(node, Getfile(n)); - Setline(node, Getline(n)); - const String *tm = Swig_typemap_lookup("cin", node, "", 0); - - String *typespec = tm ? NewString(tm) : NewString(""); - - String *slot_name = lispify_name(c, Getattr(c, "sym:name"), "'slotname"); - if (slot_name && (Strcmp(slot_name, "t") == 0 || Strcmp(slot_name, "T") == 0)) - slot_name = NewStringf("t_var"); - - if (SwigType_isarray(childType) && SwigType_array_ndim(childType) == 1) { - String *dim = SwigType_array_getdim(childType, 0); - Printf(f_cl, "\n\t(%s %s :count %s)", slot_name, typespec, dim); - Delete(dim); - } else - Printf(f_cl, "\n\t(%s %s)", slot_name, typespec); - - Delete(node); - Delete(childType); - Delete(typespec); - } - } - - Printf(f_cl, ")\n"); - - emit_export(n, lisp_name); - for (Node *child = firstChild(n); child; child = nextSibling(child)) { - if (!Strcmp(nodeType(child), "cdecl")) { - emit_export(child, lispify_name(child, Getattr(child, "sym:name"), "'slotname")); - } - } - - /* Add this structure to the known lisp types */ - //Printf(stdout, "Adding %s foreign type\n", name); - // add_defined_foreign_type(name); - -} - -void CFFI::emit_export(Node *n, String *name) { - if (GetInt(n, "feature:export")) { - String* package = Getattr(n, "feature:export:package"); - Printf(f_cl, "\n(cl:export '%s%s%s)\n", name, package ? " " : "", - package ? package : ""); - } -} - -void CFFI::emit_inline(Node *n, String *name) { - if (GetInt(n, "feature:inline")) - Printf(f_cl, "\n(cl:declaim (cl:inline %s))\n", name); -} - -String *CFFI::lispify_name(Node *n, String *ty, const char *flag, bool kw) { - String *intern_func = Getattr(n, "feature:intern_function"); - if (intern_func) { - if (Strcmp(intern_func, "1") == 0) - intern_func = NewStringf("swig-lispify"); - return NewStringf("#.(%s \"%s\" %s%s)", intern_func, ty, flag, kw ? " :keyword" : ""); - } else if (kw) - return NewStringf(":%s", ty); - else - return ty; -} - -/* utilities */ -/* returns new string w/ parens stripped */ -String *CFFI::strip_parens(String *string) { - char *s = Char(string); - int len = Len(string); - - if (len == 0 || s[0] != '(' || s[len - 1] != ')') { - return NewString(string); - } - - return NewStringWithSize(s + 1, len - 2); -} - -String *CFFI::trim(String *str) { - char *c = Char(str); - while (*c != '\0' && isspace((int) *c)) - ++c; - String *result = NewString(c); - Chop(result); - return result; -} - -String *CFFI::infix_to_prefix(String *val, char split_op, const String *op, String *type) { - List *ored = Split(val, split_op, -1); - - // some float hackery - //i don't understand it, if you do then please explain - // if ( ((split_op == '+') || (split_op == '-')) && Len(ored) == 2 && - // (SwigType_type(type) == T_FLOAT || SwigType_type(type) == T_DOUBLE || - // SwigType_type(type) == T_LONGDOUBLE) ) { - // // check that we're not splitting a float - // String *possible_result = convert_literal(val, type, false); - // if (possible_result) return possible_result; - - // } - - // try parsing the split results. if any part fails, kick out. - bool part_failed = false; - if (Len(ored) > 1) { - String *result = NewStringf("(%s", op); - for (Iterator i = First(ored); i.item; i = Next(i)) { - String *converted = convert_literal(i.item, type); - if (converted) { - Printf(result, " %s", converted); - Delete(converted); - } else { - part_failed = true; - break; - } - } - Printf(result, ")"); - Delete(ored); - return part_failed ? 0 : result; - } else { - Delete(ored); - } - return 0; -} - -/* To be called by code generating the lisp interface - Will return a String containing the literal based on type. - Will return null if there are problems. - - try_to_split defaults to true (see stub above). -*/ -String *CFFI::convert_literal(String *literal, String *type, bool try_to_split) { - String *num_param = Copy(literal); - String *trimmed = trim(num_param); - String *num = strip_parens(trimmed), *res = 0; - Delete(trimmed); - char *s = Char(num); - - // very basic parsing of infix expressions. - if (try_to_split) { - if ((res = infix_to_prefix(num, '|', "cl:logior", type))) - return res; - if ((res = infix_to_prefix(num, '&', "cl:logand", type))) - return res; - if ((res = infix_to_prefix(num, '^', "cl:logxor", type))) - return res; - if ((res = infix_to_prefix(num, '*', "cl:*", type))) - return res; - if ((res = infix_to_prefix(num, '/', "cl:/", type))) - return res; - if ((res = infix_to_prefix(num, '+', "cl:+", type))) - return res; - if ((res = infix_to_prefix(num, '-', "cl:-", type))) - return res; - } - - if (SwigType_type(type) == T_FLOAT || SwigType_type(type) == T_DOUBLE || SwigType_type(type) == T_LONGDOUBLE) { - // Use CL syntax for float literals - - // careful. may be a float identifier or float constant. - char *num_start = Char(num); - char *num_end = num_start + strlen(num_start) - 1; - - bool is_literal = isdigit(*num_start) || (*num_start == '.') || (*num_start == '+') || (*num_start == '-'); - - String *lisp_exp = 0; - if (is_literal) { - if (*num_end == 'f' || *num_end == 'F') { - lisp_exp = NewString("f"); - } else { - lisp_exp = NewString("d"); - } - - if (*num_end == 'l' || *num_end == 'L' || *num_end == 'f' || *num_end == 'F') { - *num_end = '\0'; - num_end--; - } - - int exponents = Replaceall(num, "e", lisp_exp) + Replaceall(num, "E", lisp_exp); - - if (!exponents) - Printf(num, "%s0", lisp_exp); - - if (exponents > 1 || (exponents + Replaceall(num, ".", ".") == 0)) { - Delete(num); - num = 0; - } - } - return num; - } else if (SwigType_type(type) == T_CHAR) { - /* Use CL syntax for character literals */ - String* result = NewStringf("#\\%s", s); - Delete(num); - return result; - } else if (SwigType_type(type) == T_STRING) { - /* Use CL syntax for string literals */ - String* result = NewStringf("\"%s\"", num_param); - Delete(num); - return result; - } else if (SwigType_type(type) == T_INT || SwigType_type(type) == T_UINT) { - // Printf(stderr, "Is a T_INT or T_UINT %s, before replaceall\n", s); - const char *num_start = Char(num); - bool is_literal = isdigit(*num_start) || (*num_start == '.') || (*num_start == '+') || (*num_start == '-'); - if (is_literal) { - Replaceall(num, "u", ""); - Replaceall(num, "U", ""); - Replaceall(num, "l", ""); - Replaceall(num, "L", ""); - } - - int i, j; - if (sscanf(s, "%d >> %d", &i, &j) == 2) { - String* result = NewStringf("(cl:ash %d -%d)", i, j); - Delete(num); - return result; - } else if (sscanf(s, "%d << %d", &i, &j) == 2) { - String* result = NewStringf("(cl:ash %d %d)", i, j); - Delete(num); - return result; - } - } - - if (Len(num) >= 2 && s[0] == '0') { /* octal or hex */ - if (s[1] == 'x'){ - Replace(num,"0","#",DOH_REPLACE_FIRST); - } - else{ - Replace(num,"0","#o",DOH_REPLACE_FIRST); - } - } - return num; -} - -//less flexible as it does the conversion in C, the lispify name does the conversion in lisp -String *CFFI::lispy_name(char *name) { - bool helper = false; - String *new_name = NewString(""); - for (unsigned int i = 0; i < strlen(name); i++) { - if (name[i] == '_' || name[i] == '-') { - Printf(new_name, "%c", '-'); - helper = false; - } else if (name[i] >= 'A' && name[i] <= 'Z') { - if (helper) - Printf(new_name, "%c", '-'); - Printf(new_name, "%c", ('a' + (name[i] - 'A'))); - helper = false; - } else { - helper = true; - Printf(new_name, "%c", name[i]); - } - } - return new_name; -} - -extern "C" Language *swig_cffi(void) { - return new CFFI(); -} From e1fdb67f094d3cb616a2b1b999b95f969f6096cb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 6 Oct 2022 23:24:46 +0100 Subject: [PATCH 074/217] Document CFFI removal --- CHANGES.current | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index b4eeaf3a2..224ea36d7 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-06: wsfulton + [CFFI] #1966 #2200 Remove code for Common Lisp CFFI. We dropped support + for it in SWIG 4.0.0 by disabling it as the first stage. This is the + final stage for complete removal as there has been no meaningful + progress to revive it to the status of experimental language. + 2022-10-06: olly [Python] #2390 Remove deprecated and apparently useless defarg.swg From 2f55379687a394e941a20e2224eb1125d66720cd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 10 Oct 2022 08:27:44 +0100 Subject: [PATCH 075/217] Improve director unwrap detection for the return type Resolve the return type to correctly determine if the type is a pointer or reference to a director class. SwigType_refptr_count_return() recently added as a simpler fix is no longer needed. The conventional approach of using the "type" rather than "decl" to analyse the return type is used instead too. Issue #1823 --- CHANGES.current | 7 +++ Examples/test-suite/director_unwrap_result.i | 11 +++++ .../ruby/director_unwrap_result_runme.rb | 14 ++++++ Source/CParse/templ.c | 6 +-- Source/Modules/directors.cxx | 35 +++++++++++++++ Source/Modules/python.cxx | 24 ++--------- Source/Modules/ruby.cxx | 24 ++--------- Source/Modules/swigmod.h | 1 + Source/Swig/swig.h | 1 - Source/Swig/typeobj.c | 43 ------------------- 10 files changed, 76 insertions(+), 90 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 224ea36d7..bc9f386d8 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,13 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-10: treitmayr, wsfulton + [Python, Ruby] #1811 #1823 Fix invalid code generated in some cases when + returning a pointer or reference to a director-enabled class instance. + This previously only worked in very simple cases, now return types are + resolved to fix. A bug in template instantations using pointers also + works now. + 2022-10-06: wsfulton [CFFI] #1966 #2200 Remove code for Common Lisp CFFI. We dropped support for it in SWIG 4.0.0 by disabling it as the first stage. This is the diff --git a/Examples/test-suite/director_unwrap_result.i b/Examples/test-suite/director_unwrap_result.i index bcb7f0fcc..1acc6146f 100644 --- a/Examples/test-suite/director_unwrap_result.i +++ b/Examples/test-suite/director_unwrap_result.i @@ -25,6 +25,8 @@ class Element { return &selfptr; } }; +typedef Element * element_ptr_t; +typedef Element & element_ref_t; class Storage { public: @@ -45,6 +47,15 @@ class Storage { Element *&getElementPtrRef() { return *getIt(); } + element_ref_t getElementRefTypedef() { + return **getIt(); + } + element_ptr_t getElementPtrTypedef() { + return *getIt(); + } + element_ptr_t &getElementPtrRefTypedef() { + return *getIt(); + } }; template class StorageTmpl { diff --git a/Examples/test-suite/ruby/director_unwrap_result_runme.rb b/Examples/test-suite/ruby/director_unwrap_result_runme.rb index 56970b3e8..26206ae5c 100644 --- a/Examples/test-suite/ruby/director_unwrap_result_runme.rb +++ b/Examples/test-suite/ruby/director_unwrap_result_runme.rb @@ -41,12 +41,26 @@ swig_assert_equal('s.getElementPtr', 'e', binding) swig_assert_equal('s.getElementRef.class', 'MyElement', binding) swig_assert_equal('s.getElementRef', 'e', binding) +# this shows that the director class was unwrapped: +swig_assert_equal('s.getElementPtrTypedef.class', 'MyElement', binding) +swig_assert_equal('s.getElementPtrTypedef', 'e', binding) + +# this shows that the director class was unwrapped: +swig_assert_equal('s.getElementRefTypedef.class', 'MyElement', binding) +swig_assert_equal('s.getElementRefTypedef', 'e', binding) + +# this is not unwrapped: swig_assert_equal('s.getElementPtrPtr.class', 'SWIG::TYPE_p_p_Element', binding) swig_assert_equal('s.getElementPtrPtr.class', 'SWIG::TYPE_p_p_Element', binding) +# this is not unwrapped: swig_assert_equal('s.getElementPtrRef.class', 'SWIG::TYPE_p_p_Element', binding) swig_assert_equal('s.getElementPtrRef.class', 'SWIG::TYPE_p_p_Element', binding) +# this is not unwrapped: +swig_assert_equal('s.getElementPtrRefTypedef.class', 'SWIG::TYPE_p_p_Element', binding) +swig_assert_equal('s.getElementPtrRefTypedef.class', 'SWIG::TYPE_p_p_Element', binding) + ############################ # test with a template class diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index e6c1da4a6..0dec21586 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -248,7 +248,7 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri static void cparse_fix_function_decl(String *name, SwigType *decl, SwigType *type) { String *prefix; int prefixLen; - SwigType* last; + SwigType *last; /* The type's prefix is what potentially has to be moved to the end of 'decl' */ prefix = SwigType_prefix(type); @@ -275,8 +275,7 @@ static void cparse_fix_function_decl(String *name, SwigType *decl, SwigType *typ Append(decl, prefix); Delslice(type, 0, prefixLen); if (template_debug) { - Printf(stdout, " change function '%s' to type='%s', decl='%s'\n", - name, type, decl); + Printf(stdout, " change function '%s' to type='%s', decl='%s'\n", name, type, decl); } } @@ -510,7 +509,6 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab } } } - cparse_postprocess_expanded_template(n); /* Patch bases */ diff --git a/Source/Modules/directors.cxx b/Source/Modules/directors.cxx index fbef70aa1..14e2e8466 100644 --- a/Source/Modules/directors.cxx +++ b/Source/Modules/directors.cxx @@ -233,3 +233,38 @@ void Swig_director_parms_fixup(ParmList *parms) { } } +/* ----------------------------------------------------------------------------- + * Swig_director_can_unwrap() + * + * Determine whether a function's return type can be returned as an existing + * target language object instead of creating a new target language object. + * Must be a director class and only for return by pointer or reference only + * (not by value or by pointer to pointer etc). + * ----------------------------------------------------------------------------- */ + +bool Swig_director_can_unwrap(Node *n) { + + // FIXME: this will not try to unwrap directors returned as non-director + // base class pointers! + + bool unwrap = false; + + String *type = Getattr(n, "type"); + SwigType *t = SwigType_typedef_resolve_all(type); + SwigType *t1 = SwigType_strip_qualifiers(t); + SwigType *prefix = SwigType_prefix(t1); + + if (Strcmp(prefix, "p.") == 0 || Strcmp(prefix, "r.") == 0) { + Node *parent = Swig_methodclass(n); + Node *module = Getattr(parent, "module"); + Node *target = Swig_directormap(module, t1); + if (target) + unwrap = true; + } + + Delete(prefix); + Delete(t1); + Delete(t); + + return unwrap; +} diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 6a1c0a0a2..a8175eb0e 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -3150,25 +3150,9 @@ public: Replaceall(tm, "$owner", "0"); } } - // FIXME: this will not try to unwrap directors returned as non-director - // base class pointers! - /* New addition to unwrap director return values so that the original - * python object is returned instead. - */ -#if 1 - int unwrap = 0; - String *decl = Getattr(n, "decl"); - if (SwigType_refptr_count_return(decl) == 1) { - String *type = Getattr(n, "type"); - //Node *classNode = Swig_methodclass(n); - //Node *module = Getattr(classNode, "module"); - Node *module = Getattr(parent, "module"); - Node *target = Swig_directormap(module, type); - if (target) - unwrap = 1; - } - if (unwrap) { + // Unwrap return values that are director classes so that the original Python object is returned instead. + if (!constructor && Swig_director_can_unwrap(n)) { Wrapper_add_local(f, "director", "Swig::Director *director = 0"); Printf(f->code, "director = SWIG_DIRECTOR_CAST(%s);\n", Swig_cresult_name()); Append(f->code, "if (director) {\n"); @@ -3180,9 +3164,7 @@ public: } else { Printf(f->code, "%s\n", tm); } -#else - Printf(f->code, "%s\n", tm); -#endif + Delete(tm); } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name); diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 855e8d57d..268cb2775 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -1871,24 +1871,8 @@ public: else Replaceall(tm, "$owner", "0"); -#if 1 - // FIXME: this will not try to unwrap directors returned as non-director - // base class pointers! - - /* New addition to unwrap director return values so that the original - * Ruby object is returned instead. - */ - bool unwrap = false; - String *decl = Getattr(n, "decl"); - if (SwigType_refptr_count_return(decl) == 1) { - String *type = Getattr(n, "type"); - Node *parent = Swig_methodclass(n); - Node *modname = Getattr(parent, "module"); - Node *target = Swig_directormap(modname, type); - if (target) - unwrap = true; - } - if (unwrap) { + // Unwrap return values that are director classes so that the original Ruby object is returned instead. + if (Swig_director_can_unwrap(n)) { Wrapper_add_local(f, "director", "Swig::Director *director = 0"); Printf(f->code, "director = dynamic_cast(%s);\n", Swig_cresult_name()); Printf(f->code, "if (director) {\n"); @@ -1900,9 +1884,7 @@ public: } else { Printf(f->code, "%s\n", tm); } -#else - Printf(f->code, "%s\n", tm); -#endif + Delete(tm); } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s.\n", SwigType_str(t, 0)); diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index 11b13f9fc..c605edf9d 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -405,6 +405,7 @@ String *Swig_method_decl(SwigType *return_base_type, SwigType *decl, const_Strin String *Swig_director_declaration(Node *n); void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f); void Swig_director_parms_fixup(ParmList *parms); +bool Swig_director_can_unwrap(Node *n); /* directors.cxx end */ /* Utilities */ diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 943f5daf0..e9f7c92ef 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -140,7 +140,6 @@ extern "C" { extern String *SwigType_pop(SwigType *t); extern void SwigType_push(SwigType *t, String *s); extern SwigType *SwigType_last(SwigType *t); - extern int SwigType_refptr_count_return(const 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); diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c index 581362520..8cd2e28e9 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -249,49 +249,6 @@ SwigType *SwigType_last(SwigType *t) { return result; } -/* ----------------------------------------------------------------------------- - * SwigType_refptr_count_return() - * - * Returns the number of pointer and reference indirections found in the given - * type. For functions this concerns the return type. - * For example: - * r.p. => 2 - * q(const).p. => 1 - * r.f(int).p.p. => 2 - * f().p.q(const).p. => 2 - * ----------------------------------------------------------------------------- */ - -int SwigType_refptr_count_return(const SwigType *t) { - char *c; - char *last; - int sz; - int result = 0; - - if (!t) - return 0; - - c = Char(t); - last = c; - while (*c) { - last = c; - sz = element_size(c); - c = c + sz; - if (*(c-1) == '.') { - if (((last[0] == 'p') || (last[0] == 'r')) && (last[1] == '.')) { - result++; - } else if (strncmp(last, "f(", 2) == 0) { - /* restart counter if this is a function type */ - result = 0; - } - } - if (*c == '.') { - c++; - } - } - - return result; -} - /* ----------------------------------------------------------------------------- * SwigType_parm() * From cf7733e4b8ccbd92e0aac4f5fa74a66b9dd024ca Mon Sep 17 00:00:00 2001 From: Alba Mendez Date: Mon, 10 Oct 2022 12:49:57 +0200 Subject: [PATCH 076/217] refactor integers JS testcase to avoid repeating code --- .../test-suite/javascript/integers_runme.js | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Examples/test-suite/javascript/integers_runme.js b/Examples/test-suite/javascript/integers_runme.js index 0356176ad..6cb896fbf 100644 --- a/Examples/test-suite/javascript/integers_runme.js +++ b/Examples/test-suite/javascript/integers_runme.js @@ -1,18 +1,16 @@ var integers = require("integers"); -var val = 3902408827 -ret = integers.signed_long_identity(val) -if (ret != val) - throw "Incorrect value: " + ret +function checkOne(val, fn) { + ret = fn(val) + if (ret !== val) + throw "Incorrect value: expected " + val + ", got " + ret +} -ret = integers.unsigned_long_identity(val) -if (ret != val) - throw "Incorrect value: " + ret +function checkAll(val) { + checkOne(val, integers.signed_long_identity) + checkOne(val, integers.unsigned_long_identity) + checkOne(val, integers.signed_long_long_identity) + checkOne(val, integers.unsigned_long_long_identity) +} -ret = integers.signed_long_long_identity(val) -if (ret != val) - throw "Incorrect value: " + ret - -ret = integers.unsigned_long_long_identity(val) -if (ret != val) - throw "Incorrect value: " + ret +checkAll(3902408827) From 5b02dc93d67ed3ca6098207835e1b06f3fd143f2 Mon Sep 17 00:00:00 2001 From: Alba Mendez Date: Mon, 10 Oct 2022 13:27:30 +0200 Subject: [PATCH 077/217] skip tests when value is out of range --- .../test-suite/javascript/integers_runme.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Examples/test-suite/javascript/integers_runme.js b/Examples/test-suite/javascript/integers_runme.js index 6cb896fbf..1feadaed0 100644 --- a/Examples/test-suite/javascript/integers_runme.js +++ b/Examples/test-suite/javascript/integers_runme.js @@ -1,16 +1,22 @@ var integers = require("integers"); -function checkOne(val, fn) { - ret = fn(val) +function checkOne(val, signed, typeName) { + typeName = (signed ? 'signed_' : 'unsigned_') + typeName + + var size = integers[typeName + '_size']() + if ((!signed && val < 0) || (size < 8)) + return // out of range, skip test + + ret = integers[typeName + '_identity'](val) if (ret !== val) throw "Incorrect value: expected " + val + ", got " + ret } function checkAll(val) { - checkOne(val, integers.signed_long_identity) - checkOne(val, integers.unsigned_long_identity) - checkOne(val, integers.signed_long_long_identity) - checkOne(val, integers.unsigned_long_long_identity) + checkOne(val, true, 'long') + checkOne(val, false, 'long') + checkOne(val, true, 'long_long') + checkOne(val, false, 'long_long') } checkAll(3902408827) From 55d7a513436bc61cc1ac1017a9c732b5a11a3209 Mon Sep 17 00:00:00 2001 From: Alba Mendez Date: Mon, 10 Oct 2022 12:50:12 +0200 Subject: [PATCH 078/217] add tests for new casting behavior more integers are preserved now --- Examples/test-suite/javascript/integers_runme.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Examples/test-suite/javascript/integers_runme.js b/Examples/test-suite/javascript/integers_runme.js index 1feadaed0..4aeb13d7a 100644 --- a/Examples/test-suite/javascript/integers_runme.js +++ b/Examples/test-suite/javascript/integers_runme.js @@ -20,3 +20,5 @@ function checkAll(val) { } checkAll(3902408827) +checkAll(Number.MAX_SAFE_INTEGER) +checkAll(Number.MIN_SAFE_INTEGER) From 0239ba5536105bec1ac4c2386b10a300e9a483cd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 10 Oct 2022 18:55:37 +0100 Subject: [PATCH 079/217] OCaml director return fix Fixes director_unwrap_result testcase when returning Element *const *& --- Source/Modules/ocaml.cxx | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx index 7ea453132..c6748f571 100644 --- a/Source/Modules/ocaml.cxx +++ b/Source/Modules/ocaml.cxx @@ -1647,20 +1647,13 @@ public: /* any existing helper functions to handle this? */ if (!is_void) { if (!(ignored_method && !pure_virtual)) { - /* A little explanation: - * The director_enum test case makes a method whose return type - * is an enum type. returntype here is "int". gcc complains - * about an implicit enum conversion, and although i don't strictly - * agree with it, I'm working on fixing the error: - * - * Below is what I came up with. It's not great but it should - * always essentially work. - */ + String *rettype = SwigType_str(returntype, 0); if (!SwigType_isreference(returntype)) { - Printf(w->code, "CAMLreturn_type((%s)c_result);\n", SwigType_lstr(returntype, "")); + Printf(w->code, "CAMLreturn_type((%s)c_result);\n", rettype); } else { - Printf(w->code, "CAMLreturn_type(*c_result);\n"); + Printf(w->code, "CAMLreturn_type((%s)*c_result);\n", rettype); } + Delete(rettype); } } else { Printf(w->code, "CAMLreturn0;\n"); From 2268d6ee96a380f628169e364711cf38d3db1460 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 10 Oct 2022 19:51:08 +0100 Subject: [PATCH 080/217] Fix compile error when using directors Fix when using templates with more than one template parameter and used as an input parameter in a virtual method in a director class (problem affecting most of the scripting languages). Fixes #2160 --- CHANGES.current | 5 +++++ Examples/test-suite/common.mk | 1 + Examples/test-suite/director_template.i | 28 +++++++++++++++++++++++++ Lib/php/php.swg | 2 +- Lib/typemaps/swigtype.swg | 2 +- 5 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 Examples/test-suite/director_template.i diff --git a/CHANGES.current b/CHANGES.current index bc9f386d8..27caf2c1a 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-10: wsfulton + #2160 Fix compile error when using templates with more than one template + parameter and used as an input parameter in a virtual method in a + director class (problem affecting most of the scripting languages). + 2022-10-10: treitmayr, wsfulton [Python, Ruby] #1811 #1823 Fix invalid code generated in some cases when returning a pointer or reference to a director-enabled class instance. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 2808763c7..1c70ece4c 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -216,6 +216,7 @@ CPP_TEST_CASES += \ director_ref \ director_simple \ director_smartptr \ + director_template \ director_thread \ director_unroll \ director_unwrap_result \ diff --git a/Examples/test-suite/director_template.i b/Examples/test-suite/director_template.i new file mode 100644 index 000000000..fdc5bfbd1 --- /dev/null +++ b/Examples/test-suite/director_template.i @@ -0,0 +1,28 @@ +%module(directors="1") director_template + +%{ +#include +%} + +%include + +%feature("director") HandleBytes; + +%inline %{ + template class TwoTemplateParms {}; +%} + +%template(TT_int_double) TwoTemplateParms; + +%inline %{ + class HandleBytes { + public: + virtual void handle(const std::vector data) = 0; // Note: not instantiated with %template + virtual void handle2(TwoTemplateParms data) = 0; + virtual ~HandleBytes() {} + }; + + void bytes_wrapper(const std::vector data, HandleBytes *handler) { + handler->handle(data); + } +%} diff --git a/Lib/php/php.swg b/Lib/php/php.swg index b22166593..e14401236 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -473,7 +473,7 @@ %typemap(directorin) SWIGTYPE %{ ZVAL_UNDEF($input); - SWIG_SetPointerZval($input, SWIG_as_voidptr(new $1_ltype(SWIG_STD_MOVE($1))), $&1_descriptor, 1); + SWIG_SetPointerZval($input, (new $1_ltype(SWIG_STD_MOVE($1))), $&1_descriptor, 1); %} %typemap(out, phptype="void") void "" diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg index 42c9c54eb..69f83794d 100644 --- a/Lib/typemaps/swigtype.swg +++ b/Lib/typemaps/swigtype.swg @@ -390,7 +390,7 @@ /* directorin */ %typemap(directorin,noblock=1) SWIGTYPE { - $input = SWIG_NewPointerObj(%as_voidptr(new $1_ltype(SWIG_STD_MOVE($1))), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags); + $input = SWIG_NewPointerObj((new $1_ltype(SWIG_STD_MOVE($1))), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags); } %typemap(directorin,noblock=1) SWIGTYPE * { From 87a677b8b387db2111b3dc518f4a3da806ebbf80 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 9 Oct 2022 23:42:44 +1300 Subject: [PATCH 081/217] Fix doc typos --- CHANGES.current | 3 ++- Doc/Manual/Lua.html | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 27caf2c1a..301370780 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -16,7 +16,7 @@ Version 4.1.0 (in progress) [Python, Ruby] #1811 #1823 Fix invalid code generated in some cases when returning a pointer or reference to a director-enabled class instance. This previously only worked in very simple cases, now return types are - resolved to fix. A bug in template instantations using pointers also + resolved to fix. A bug in template instantiations using pointers also works now. 2022-10-06: wsfulton @@ -42,6 +42,7 @@ Version 4.1.0 (in progress) 2022-10-05: benjamin-sch [Python] added an interpreter counter to fix deinitialization issues if multiple subinterpreters are used + 2022-10-05: olly, wsfulton #672 Add support for parsing C++11 final classes such as: diff --git a/Doc/Manual/Lua.html b/Doc/Manual/Lua.html index 1c48a3705..8ea385b49 100644 --- a/Doc/Manual/Lua.html +++ b/Doc/Manual/Lua.html @@ -566,7 +566,7 @@ If the -no-old-metatable-bindings option is used, then these old-style

    It is worth mentioning, that example.Test.TEST1 and example.Test_TEST1 are different entities and changing one does not change the other. -Given the fact that these are constantes and they are not supposed to be changed, it is up to you to avoid such issues. +Given the fact that these are constants and they are not supposed to be changed, it is up to you to avoid such issues.

    29.3.5 Pointers

    From abf5c8a35770d506e7b2edfa547045ec50ddbb1c Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 9 Oct 2022 23:49:12 +1300 Subject: [PATCH 082/217] [python] Remove doc caveat for Python < 2.1 The minimum version we now support is Python 2.7. --- Doc/Manual/Python.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index cc21bc011..a8c7d4c86 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -3128,9 +3128,7 @@ likely cause your program to segfault.

    To help ensure that no references to the Python object remain after calling __disown__(), this method returns a weak reference to -the Python object. Weak references are only available in Python versions -2.1 and higher, so for older versions you must explicitly delete all -references. Here is an example: +the Python object. Here is an example:

    From ac00c7ad98059f355a6fab615c8f56bc2d99d7e4 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 10 Oct 2022 00:16:39 +1300 Subject: [PATCH 083/217] Fix php example comment typo --- Examples/php/extend/runme.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/php/extend/runme.php b/Examples/php/extend/runme.php index 93eedee99..b770e5ce4 100644 --- a/Examples/php/extend/runme.php +++ b/Examples/php/extend/runme.php @@ -25,7 +25,7 @@ print "----------------------\n"; $list = new EmployeeList(); # EmployeeList owns its items, so we must surrender ownership of objects -# we add. This involves first clearing the ->disown member to tell the +# we add. This involves first clearing the ->thisown member to tell the # C++ director to start reference counting. $e->thisown = 0; From 5be76e6dcc1013656f2c10f2dd6f4817e11b2b0d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 11 Oct 2022 10:28:19 +1300 Subject: [PATCH 084/217] Makefile.in: Remove unused variables dd and srpm srpm is no longer used since the recent removal of the srcrpm target in 623b7d97a79baea923f3a64825d3afbd94c1b24d. dd hasn't been used since 4ce80105c8c923c53bb9c0733c9f1e90d309649f back in 2006! --- Makefile.in | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Makefile.in b/Makefile.in index a20245b5a..3e8f93d19 100644 --- a/Makefile.in +++ b/Makefile.in @@ -496,10 +496,6 @@ uninstall-ccache: # DIST and other maintenance ############################################################################ -# distribution directory -dd = @PACKAGE_NAME@-@PACKAGE_VERSION@ -srpm = @PACKAGE_NAME@-@PACKAGE_VERSION@ - dist: @echo "'make dist' not implemented - use Tools/mkdist.py instead - e.g.:" @echo "Tools/mkdist.py @VERSION@ master" From d5a0201c54e815180bdffa67e037fe0183428cfd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 10 Oct 2022 22:34:40 +0100 Subject: [PATCH 085/217] XML whitespace changes Remove non-conventional whitespace before closing tag with '>'. --- Source/Modules/xml.cxx | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Source/Modules/xml.cxx b/Source/Modules/xml.cxx index 5830754b4..ed4213cc5 100644 --- a/Source/Modules/xml.cxx +++ b/Source/Modules/xml.cxx @@ -118,7 +118,7 @@ public: String *k; indent_level += 4; print_indent(0); - Printf(out, "\n", ++id, obj); + Printf(out, "\n", ++id, obj); indent_level += 4; Iterator ki; ki = First(obj); @@ -175,7 +175,7 @@ public: } indent_level -= 4; print_indent(0); - Printf(out, "\n"); + Printf(out, "\n"); indent_level -= 4; } @@ -183,7 +183,7 @@ public: Node *cobj; print_indent(0); - Printf(out, "<%s id=\"%ld\" addr=\"%p\" >\n", nodeType(obj), ++id, obj); + Printf(out, "<%s id=\"%ld\" addr=\"%p\">\n", nodeType(obj), ++id, obj); Xml_print_attributes(obj); cobj = firstChild(obj); if (cobj) { @@ -196,32 +196,32 @@ public: Printf(out, "\n"); } print_indent(0); - Printf(out, "\n", nodeType(obj)); + Printf(out, "\n", nodeType(obj)); } void Xml_print_parmlist(ParmList *p, const char* markup = "parmlist") { print_indent(0); - Printf(out, "<%s id=\"%ld\" addr=\"%p\" >\n", markup, ++id, p); + Printf(out, "<%s id=\"%ld\" addr=\"%p\">\n", markup, ++id, p); indent_level += 4; while (p) { print_indent(0); Printf(out, "\n", ++id); Xml_print_attributes(p); print_indent(0); - Printf(out, "\n"); + Printf(out, "\n"); p = nextSibling(p); } indent_level -= 4; print_indent(0); - Printf(out, "\n", markup); + Printf(out, "\n", markup); } void Xml_print_baselist(List *p) { print_indent(0); - Printf(out, "\n", ++id, p); + Printf(out, "\n", ++id, p); indent_level += 4; Iterator s; for (s = First(p); s.item; s = Next(s)) { @@ -232,7 +232,7 @@ public: } indent_level -= 4; print_indent(0); - Printf(out, "\n"); + Printf(out, "\n"); } String *Xml_escape_string(String *str) { @@ -272,21 +272,21 @@ public: void Xml_print_hash(Hash *p, const char *markup) { print_indent(0); - Printf(out, "<%s id=\"%ld\" addr=\"%p\" >\n", markup, ++id, p); + Printf(out, "<%s id=\"%ld\" addr=\"%p\">\n", markup, ++id, p); Xml_print_attributes(p); indent_level += 4; Iterator n = First(p); while (n.key) { print_indent(0); - Printf(out, "<%ssitem id=\"%ld\" addr=\"%p\" >\n", markup, ++id, n.item); + Printf(out, "<%ssitem id=\"%ld\" addr=\"%p\">\n", markup, ++id, n.item); Xml_print_attributes(n.item); print_indent(0); - Printf(out, "\n", markup); + Printf(out, "\n", markup); n = Next(n); } indent_level -= 4; print_indent(0); - Printf(out, "\n", markup); + Printf(out, "\n", markup); } }; From 6b6761abacd5db9afcdf59a7b8019c11bff4ec5b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 10 Oct 2022 22:36:39 +0100 Subject: [PATCH 086/217] Update 4.1.0 release notes summary --- RELEASENOTES | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES b/RELEASENOTES index 237afa8c9..39bc80cc4 100644 --- a/RELEASENOTES +++ b/RELEASENOTES @@ -8,14 +8,26 @@ Detailed release notes are available with the release and are also published on the SWIG web site at https://swig.org/release.html. SWIG-4.1.0 summary: +- Add Javascript Node v12-v18 support, remove support prior to v6. +- Octave 6.0 to 6.4 support added. - Add PHP 8 support. - PHP wrapping is now done entirely via PHP's C API - no more .php wrapper. - Perl 5.8.0 is now the oldest version SWIG supports. - Python 3.3 is now the oldest Python 3 version SWIG supports. -- Common cases of `<` and `>` comparisons in constant expressions are now - supported. +- Python 3.9-3.11 support added. +- Various memory leak fixes in Python generated code. +- Scilab 5.5-6.1 support improved. +- Many improvements for each and every target language. +- Various preprocessor expression handling improvements. +- Improved C99, C++11, C++14, C++17 support. Start adding C++20 standard. +- Make SWIG much more move semantics friendly. +- Add C++ std::unique_ptr support. +- Few minor C++ template handling improvements. +- Various C++ using declaration fixes. +- Few fixes for handling Doxygen comments. - GitHub Actions is now used instead of Travis CI for continuous integration. -- The "XML" target language has been reclassified as "Experimental". +- Add building SWIG using CMake as a secondary build system. +- Update optional SWIG build dependency for regex support from PCRE to PCRE2. SWIG-4.0.2 summary: - A few fixes around doxygen comment handling. From c82aa3bb4123b3c06cce359e63019fff983e7ec0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 13 Oct 2022 07:56:38 +0100 Subject: [PATCH 087/217] Quick fix SWIG_VERSION not being defined correctly in wrappers --- Examples/test-suite/preproc_predefined.i | 10 ++++++++++ Lib/typemaps/swigversion.swg | 1 - 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/preproc_predefined.i b/Examples/test-suite/preproc_predefined.i index 7db5352f5..63aab6c89 100644 --- a/Examples/test-suite/preproc_predefined.i +++ b/Examples/test-suite/preproc_predefined.i @@ -10,6 +10,16 @@ #endif %} +%define %generate_swig_version_from_preprocessor()%#define SWIG_VERSION_FROM_SWIG_PREPROCESSOR SWIG_VERSION %enddef +%insert("header") { +%generate_swig_version_from_preprocessor() +} +%insert("header") %{ +#if SWIG_VERSION != SWIG_VERSION_FROM_SWIG_PREPROCESSOR +# error SWIG_VERSION in SWIG preprocessor does not match SWIG_VERSION from C preprocessor +#endif +%} + /* Test that SWIGVERSION is NOT defined at SWIG-time or in the wrapper. * It used to be defined in the wrapper as a side-effect of how SWIG_VERSION * was defined in the wrapper but was never documented and is redundant. diff --git a/Lib/typemaps/swigversion.swg b/Lib/typemaps/swigversion.swg index 18f897cad..ac2e42439 100644 --- a/Lib/typemaps/swigversion.swg +++ b/Lib/typemaps/swigversion.swg @@ -12,6 +12,5 @@ %insert("header") { %define_swig_version_() %#define SWIG_VERSION SWIG_VERSION_ -%#undef SWIG_VERSION_ } #undef %define_swig_version_ From e123c2afe84ea29c5a7c9561c7e3355283001477 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 13 Oct 2022 08:09:13 +0100 Subject: [PATCH 088/217] Additional SWIG_VERSION testing --- Examples/test-suite/preproc_predefined.i | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Examples/test-suite/preproc_predefined.i b/Examples/test-suite/preproc_predefined.i index 63aab6c89..252ef9a1a 100644 --- a/Examples/test-suite/preproc_predefined.i +++ b/Examples/test-suite/preproc_predefined.i @@ -10,6 +10,18 @@ #endif %} +/* Test that SWIG_VERSION has a plausible value - in particular catch if + * it isn't defined to a numeric value (which will get replaced by 0). + */ +#if SWIG_VERSION < 0x040100 +# error SWIG_VERSION value not plausible at SWIG-time +#endif +%{ +#if SWIG_VERSION < 0x040100 +# error SWIG_VERSION value not plausible in the generated wrapper +#endif +%} + %define %generate_swig_version_from_preprocessor()%#define SWIG_VERSION_FROM_SWIG_PREPROCESSOR SWIG_VERSION %enddef %insert("header") { %generate_swig_version_from_preprocessor() From 46f7501d94f8fb3432863344aeda6d4fd85fb1a4 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 13 Oct 2022 19:46:51 +0100 Subject: [PATCH 089/217] Cleanup SWIG_VERSION definition Add Swig_obligatory_macros which must be called by each target language to define SWIG_VERSION correctly in the generated code, as well as the language specific macro SWIGXXX where XXX is the target language name. Drop the #ifdef SWIGXXX that was previously generated - I can't see the point of this and if users are defining this macro somehow, then users will need to change this Closes #1050 --- Lib/csharp/csharp.swg | 2 -- Lib/go/go.swg | 2 -- Lib/guile/guile.i | 2 -- Lib/java/java.swg | 2 -- Lib/lua/lua.swg | 2 -- Lib/mzscheme/mzscheme.swg | 2 -- Lib/ocaml/ocaml.i | 2 -- Lib/php/php.swg | 2 -- Lib/typemaps/README | 1 - Lib/typemaps/swigmacros.swg | 2 -- Lib/typemaps/swigversion.swg | 16 --------------- Source/Modules/csharp.cxx | 2 +- Source/Modules/d.cxx | 2 +- Source/Modules/go.cxx | 4 +++- Source/Modules/guile.cxx | 2 +- Source/Modules/java.cxx | 2 +- Source/Modules/javascript.cxx | 4 ++-- Source/Modules/lua.cxx | 2 +- Source/Modules/main.cxx | 20 +++--------------- Source/Modules/mzscheme.cxx | 2 +- Source/Modules/ocaml.cxx | 2 +- Source/Modules/octave.cxx | 2 +- Source/Modules/perl5.cxx | 2 +- Source/Modules/php.cxx | 12 +++++------ Source/Modules/python.cxx | 2 +- Source/Modules/r.cxx | 3 +-- Source/Modules/ruby.cxx | 2 +- Source/Modules/scilab.cxx | 2 +- Source/Modules/tcl8.cxx | 2 +- Source/Swig/misc.c | 38 +++++++++++++++++++++++++++++++++++ Source/Swig/swig.h | 2 ++ 31 files changed, 68 insertions(+), 76 deletions(-) delete mode 100644 Lib/typemaps/swigversion.swg diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg index 8514a7705..1f80d12a1 100644 --- a/Lib/csharp/csharp.swg +++ b/Lib/csharp/csharp.swg @@ -4,8 +4,6 @@ * C# typemaps * ----------------------------------------------------------------------------- */ -%include - %include /* The ctype, imtype and cstype typemaps work together and so there should be one of each. diff --git a/Lib/go/go.swg b/Lib/go/go.swg index 47486ab75..348ae5f0d 100644 --- a/Lib/go/go.swg +++ b/Lib/go/go.swg @@ -4,8 +4,6 @@ * Go configuration module. * ------------------------------------------------------------ */ -%include - %include /* Code insertion directives */ diff --git a/Lib/guile/guile.i b/Lib/guile/guile.i index 10438f483..ef270d74b 100644 --- a/Lib/guile/guile.i +++ b/Lib/guile/guile.i @@ -4,8 +4,6 @@ * SWIG Configuration File for Guile. * ----------------------------------------------------------------------------- */ -%include - /* Macro for inserting Scheme code into the stub */ #define %scheme %insert("scheme") #define %goops %insert("goops") diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 28eb8fd0d..8719818bb 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -4,8 +4,6 @@ * Java typemaps * ----------------------------------------------------------------------------- */ -%include - %include /* The jni, jtype and jstype typemaps work together and so there should be one of each. diff --git a/Lib/lua/lua.swg b/Lib/lua/lua.swg index 263c3966f..12c635d77 100644 --- a/Lib/lua/lua.swg +++ b/Lib/lua/lua.swg @@ -5,8 +5,6 @@ * This file is parsed by SWIG before reading any other interface file. * ----------------------------------------------------------------------------- */ -%include - /* ----------------------------------------------------------------------------- * includes * ----------------------------------------------------------------------------- */ diff --git a/Lib/mzscheme/mzscheme.swg b/Lib/mzscheme/mzscheme.swg index 8ded91f3e..f45c87250 100644 --- a/Lib/mzscheme/mzscheme.swg +++ b/Lib/mzscheme/mzscheme.swg @@ -5,8 +5,6 @@ * This file is parsed by SWIG before reading any other interface file. * ----------------------------------------------------------------------------- */ -%include - /* Include headers */ %runtime "swigrun.swg" // Common C API type-checking code %runtime "swigerrors.swg" // SWIG errors diff --git a/Lib/ocaml/ocaml.i b/Lib/ocaml/ocaml.i index 117d0a9b5..cc26d1859 100644 --- a/Lib/ocaml/ocaml.i +++ b/Lib/ocaml/ocaml.i @@ -4,8 +4,6 @@ * SWIG Configuration File for Ocaml * ----------------------------------------------------------------------------- */ -%include - /* Insert common stuff */ %insert(runtime) "swigrun.swg" diff --git a/Lib/php/php.swg b/Lib/php/php.swg index e14401236..fd0928076 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -4,8 +4,6 @@ * PHP configuration file * ----------------------------------------------------------------------------- */ -%include - // Default to generating PHP type declarations (for PHP >= 8) except for // cases which are liable to cause compatibility issues with existing // bindings. diff --git a/Lib/typemaps/README b/Lib/typemaps/README index 22a0fc0bb..65134578d 100644 --- a/Lib/typemaps/README +++ b/Lib/typemaps/README @@ -48,7 +48,6 @@ std_strings.swg Common macros to implemented the std::string/std::wstring typem strings.swg Common macros and typemaps for string and wstring (char *, wchar_t *) swigmacros.swg Basic macros -swigversion.swg Define SWIG_VERSION fragments.swg Macros for fragment manipulations diff --git a/Lib/typemaps/swigmacros.swg b/Lib/typemaps/swigmacros.swg index 7db6871d4..b772eb04b 100644 --- a/Lib/typemaps/swigmacros.swg +++ b/Lib/typemaps/swigmacros.swg @@ -109,8 +109,6 @@ nocppval #endif %enddef -%include - /* ----------------------------------------------------------------------------- * Casting operators * ----------------------------------------------------------------------------- */ diff --git a/Lib/typemaps/swigversion.swg b/Lib/typemaps/swigversion.swg deleted file mode 100644 index ac2e42439..000000000 --- a/Lib/typemaps/swigversion.swg +++ /dev/null @@ -1,16 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Define SWIG_VERSION - * ----------------------------------------------------------------------------- */ - -/* Define SWIG_VERSION in the interface and the wrapper code. - * - * Best practice is to use SWIG-time checks for SWIG_VERSION, but SWIG_VERSION - * was unintentionally defined like this for many years, and while it was never - * documented there are likely user interface files which rely on it. - */ -%define %define_swig_version_()%#define SWIG_VERSION_ SWIG_VERSION %enddef -%insert("header") { -%define_swig_version_() -%#define SWIG_VERSION SWIG_VERSION_ -} -#undef %define_swig_version_ diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 3cebb346c..240a002b4 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -399,7 +399,7 @@ public: Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGCSHARP\n#define SWIGCSHARP\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "CSHARP"); if (directorsEnabled()) { Printf(f_runtime, "#define SWIG_DIRECTORS\n"); diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index 4704d8d54..31f300f2e 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -472,7 +472,7 @@ public: Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGD\n#define SWIGD\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "D"); if (directorsEnabled()) { Printf(f_runtime, "#define SWIG_DIRECTORS\n"); diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index d39d396fc..bf63bec63 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -512,6 +512,9 @@ private: Swig_register_filebyname("cgo_comment_typedefs", f_cgo_comment_typedefs); Swig_banner(f_c_begin); + + Swig_obligatory_macros(f_c_runtime, "GO"); + if (CPlusPlus) { Printf(f_c_begin, "\n// source: %s\n\n", swig_filename); } else { @@ -519,7 +522,6 @@ private: } Printf(f_c_runtime, "#define SWIGMODULE %s\n", module); - Printf(f_c_runtime, "#ifndef SWIGGO\n#define SWIGGO\n#endif\n\n"); if (gccgo_flag) { Printf(f_c_runtime, "#define SWIGGO_PREFIX %s\n", go_prefix); diff --git a/Source/Modules/guile.cxx b/Source/Modules/guile.cxx index 874150e3a..605e03197 100644 --- a/Source/Modules/guile.cxx +++ b/Source/Modules/guile.cxx @@ -321,7 +321,7 @@ public: Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGGUILE\n#define SWIGGUILE\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "GUILE"); /* Write out directives and declarations */ diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 93d623703..773945af2 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -456,7 +456,7 @@ public: Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGJAVA\n#define SWIGJAVA\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "JAVA"); if (directorsEnabled()) { Printf(f_runtime, "#define SWIG_DIRECTORS\n"); diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx index bf0f471b0..17effc220 100644 --- a/Source/Modules/javascript.cxx +++ b/Source/Modules/javascript.cxx @@ -1615,7 +1615,7 @@ int JSCEmitter::initialize(Node *n) { Swig_banner(f_wrap_cpp); - Printf(f_runtime, "#ifndef SWIGJAVASCRIPT\n#define SWIGJAVASCRIPT\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "JAVASCRIPT"); return SWIG_OK; } @@ -1947,7 +1947,7 @@ int V8Emitter::initialize(Node *n) { Swig_banner(f_wrap_cpp); - Printf(f_runtime, "#ifndef SWIGJAVASCRIPT\n#define SWIGJAVASCRIPT\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "JAVASCRIPT"); return SWIG_OK; } diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx index 855acc69d..c2e65dba6 100644 --- a/Source/Modules/lua.cxx +++ b/Source/Modules/lua.cxx @@ -329,7 +329,7 @@ public: /* Standard stuff for the SWIG runtime section */ Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGLUA\n#define SWIGLUA\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "LUA"); emitLuaFlavor(f_runtime); diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index d2960e9f8..f5bdec644 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -911,25 +911,11 @@ int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm) { Preprocessor_define((DOH *) "SWIG 1", 0); Preprocessor_define((DOH *) "__STDC__", 0); - // Set the SWIG version value in format 0xAABBCC from package version expected to be in format A.B.C - String *package_version = NewString(PACKAGE_VERSION); /* Note that the fakeversion has not been set at this point */ - 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 - - /* Turn on contracts */ + String *vers = Swig_package_version_hex(); + Preprocessor_define(vers, 0); + Delete(vers); Swig_contract_mode_set(1); - Preprocessor_define(vers, 0); /* Turn off directors mode */ Wrapper_director_mode_set(0); diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx index 6e412a09c..e22f8bb7a 100644 --- a/Source/Modules/mzscheme.cxx +++ b/Source/Modules/mzscheme.cxx @@ -147,7 +147,7 @@ public: Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGMZSCHEME\n#define SWIGMZSCHEME\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "MZSCHEME"); module = Getattr(n, "name"); diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx index c6748f571..963a0c2d1 100644 --- a/Source/Modules/ocaml.cxx +++ b/Source/Modules/ocaml.cxx @@ -276,7 +276,7 @@ public: Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGOCAML\n#define SWIGOCAML\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "OCAML"); Printf(f_runtime, "#define SWIG_MODULE \"%s\"\n", module); /* Module name */ diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index 04609b017..352105b9b 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -190,7 +190,7 @@ public: Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGOCTAVE\n#define SWIGOCTAVE\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "OCTAVE"); Printf(f_runtime, "#define SWIG_name_d \"%s\"\n", module); Printf(f_runtime, "#define SWIG_name %s\n", module); diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index add4fd0b6..0cbf6b17a 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -319,7 +319,7 @@ public: Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGPERL\n#define SWIGPERL\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "PERL"); if (directorsEnabled()) { Printf(f_runtime, "#define SWIG_DIRECTORS\n"); diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 13b3df686..a2e741215 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -609,6 +609,12 @@ public: Swig_banner(f_begin); + Swig_obligatory_macros(f_runtime, "PHP"); + + if (directorsEnabled()) { + Printf(f_runtime, "#define SWIG_DIRECTORS\n"); + } + // We need to include php.h before string.h gets included, at least with // PHP 8.2. Otherwise string.h is included without _GNU_SOURCE being // included and memrchr() doesn't get declared, and then inline code in @@ -636,12 +642,6 @@ public: "# endif\n" "#endif\n\n"); - Printf(f_runtime, "#ifndef SWIGPHP\n#define SWIGPHP\n#endif\n\n"); - - if (directorsEnabled()) { - Printf(f_runtime, "#define SWIG_DIRECTORS\n"); - } - /* Set the module name */ module = Copy(Getattr(n, "name")); cap_module = NewStringf("%(upper)s", module); diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index a8175eb0e..6f30c1faa 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -587,7 +587,7 @@ public: Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGPYTHON\n#define SWIGPYTHON\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "PYTHON"); if (directorsEnabled()) { Printf(f_runtime, "#define SWIG_DIRECTORS\n"); diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 3283c96ab..565145327 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -740,8 +740,7 @@ int R::top(Node *n) { Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGR\n#define SWIGR\n#endif\n\n"); - + Swig_obligatory_macros(f_runtime, "R"); Swig_banner_target_lang(s_init, "#"); outputCommandLineArguments(s_init); diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 268cb2775..0208435f0 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -1087,7 +1087,7 @@ public: Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGRUBY\n#define SWIGRUBY\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "RUBY"); if (directorsEnabled()) { Printf(f_runtime, "#define SWIG_DIRECTORS\n"); diff --git a/Source/Modules/scilab.cxx b/Source/Modules/scilab.cxx index a99ce0025..aabd2d842 100644 --- a/Source/Modules/scilab.cxx +++ b/Source/Modules/scilab.cxx @@ -200,7 +200,7 @@ public: /* Output module initialization code */ Swig_banner(beginSection); - Printf(runtimeSection, "\n\n#ifndef SWIGSCILAB\n#define SWIGSCILAB\n#endif\n\n"); + Swig_obligatory_macros(runtimeSection, "SCILAB"); // Gateway header source merged with wrapper source in nobuilder mode if (!generateBuilder) diff --git a/Source/Modules/tcl8.cxx b/Source/Modules/tcl8.cxx index f65b3eccf..975230e84 100644 --- a/Source/Modules/tcl8.cxx +++ b/Source/Modules/tcl8.cxx @@ -161,7 +161,7 @@ public: Swig_banner(f_begin); - Printf(f_runtime, "\n\n#ifndef SWIGTCL\n#define SWIGTCL\n#endif\n\n"); + Swig_obligatory_macros(f_runtime, "TCL"); /* Set the module name, namespace, and prefix */ diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index 92e45fbe0..18c29f76a 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -62,6 +62,44 @@ 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() * diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index e9f7c92ef..19e61b455 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -308,6 +308,8 @@ extern int ParmList_is_compactdefargs(ParmList *p); 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); From f13de56e5f88aaed94a2fe143ee766755ee82cf1 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 13 Oct 2022 21:14:44 +0100 Subject: [PATCH 090/217] Revert "[xml] Move to "Experimental" target language status" This reverts commit 22a4355f340e9a844d5e5d8d0528d767c4808ebb. Conflicts: CHANGES.current RELEASENOTES --- CHANGES.current | 6 ------ Doc/Manual/SWIG.html | 2 +- Examples/xml/Makefile.in | 4 +--- Source/Modules/swigmain.cxx | 2 +- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 301370780..4a94edca2 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -290,12 +290,6 @@ Version 4.1.0 (in progress) 2022-07-12: erezgeva [Perl] Add std::unique_ptr support in std_unique_ptr.i library file. -2022-07-07: olly - [xml] #2213 XML has been moved to "Experimental" target language - status. It's not in good shape and is likely to be removed unless - somebody steps up to bring it up to the expected standard (it fails - to even meet the criteria for "Experimental" currently). - 2022-07-07: jmarrec #1158 #2286 Add basic support for C++11 attributes. These are now crudely ignored by SWIG's parser's tokeniser, which is better that diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index 68c980771..3fb41e522 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -134,11 +134,11 @@ Supported Target Language Options -ruby - Generate Ruby wrappers -scilab - Generate Scilab wrappers -tcl8 - Generate Tcl 8 wrappers + -xml - Generate XML wrappers Experimental Target Language Options -mzscheme - Generate MzScheme/Racket wrappers -ocaml - Generate OCaml wrappers - -xml - Generate XML wrappers General Options -addextern - Add extra extern declarations diff --git a/Examples/xml/Makefile.in b/Examples/xml/Makefile.in index eaabe0ac5..44894b8ea 100644 --- a/Examples/xml/Makefile.in +++ b/Examples/xml/Makefile.in @@ -5,11 +5,9 @@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ SWIGEXE = $(top_builddir)/swig -# Suppress "experimental target language" warning -SWIGOPT = -w524 SWIG_LIB_DIR = $(top_srcdir)/Lib SWIG_LIB_SET = @SWIG_LIB_SET@ -SWIGINVOKE = $(SWIG_LIB_SET) $(SWIGTOOL) $(SWIGEXE) $(SWIGOPT) +SWIGINVOKE = $(SWIG_LIB_SET) $(SWIGTOOL) $(SWIGEXE) cleanup = tail +2 \ | sed -e 's/ident="ID[0-9A-F]*"//g' \ diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx index bb5bf34e5..ad24d0fee 100644 --- a/Source/Modules/swigmain.cxx +++ b/Source/Modules/swigmain.cxx @@ -80,7 +80,7 @@ static TargetLanguageModule modules[] = { {"-tcl", swig_tcl, NULL, Supported}, {"-tcl8", swig_tcl, "Tcl 8", Supported}, {"-uffi", NULL, "Common Lisp / UFFI", Disabled}, - {"-xml", swig_xml, "XML", Experimental}, + {"-xml", swig_xml, "XML", Supported}, {NULL, NULL, NULL, Disabled} }; From 752b7e82cd61a80eb0f5dd80f134ba80bcae4973 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 13 Oct 2022 22:22:18 +0100 Subject: [PATCH 091/217] Add missing SWIGTYPE *const& typemaps --- CHANGES.current | 4 ++++ Examples/test-suite/r/constant_pointers_runme.R | 13 +++++++++++++ Lib/r/rtype.swg | 9 +++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 Examples/test-suite/r/constant_pointers_runme.R diff --git a/CHANGES.current b/CHANGES.current index 4a94edca2..d0246156b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-13: wsfulton + [R] Add missing SWIGTYPE *const& typemaps for supporting pointers + by const reference. + 2022-10-10: wsfulton #2160 Fix compile error when using templates with more than one template parameter and used as an input parameter in a virtual method in a diff --git a/Examples/test-suite/r/constant_pointers_runme.R b/Examples/test-suite/r/constant_pointers_runme.R new file mode 100644 index 000000000..d6f1c945d --- /dev/null +++ b/Examples/test-suite/r/constant_pointers_runme.R @@ -0,0 +1,13 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + +dyn.load(paste("constant_pointers", .Platform$dynlib.ext, sep="")) +source("constant_pointers.R") +cacheMetaData(1) + +myb <- B() +bret = bar(myb) +bret2 = cbar(myb) +bret3 = bar(bret2) + +q(save="no") diff --git a/Lib/r/rtype.swg b/Lib/r/rtype.swg index 41f0affe1..a9c067589 100644 --- a/Lib/r/rtype.swg +++ b/Lib/r/rtype.swg @@ -14,12 +14,13 @@ %typemap("rtype") bool, bool * "logical" %typemap("rtype") enum SWIGTYPE "character" %typemap("rtype") enum SWIGTYPE * "character" -%typemap("rtype") enum SWIGTYPE *const "character" +%typemap("rtype") enum SWIGTYPE *const& "character" %typemap("rtype") enum SWIGTYPE & "character" %typemap("rtype") const enum SWIGTYPE & "character" %typemap("rtype") enum SWIGTYPE && "character" %typemap("rtype") SWIGTYPE * "$R_class" %typemap("rtype") SWIGTYPE *const "$R_class" +%typemap("rtype") SWIGTYPE *const& "$*R_class" %typemap("rtype") SWIGTYPE & "$R_class" %typemap("rtype") SWIGTYPE && "$R_class" %typemap("rtype") SWIGTYPE "$&R_class" @@ -93,7 +94,7 @@ %typemap(scoercein) enum SWIGTYPE *const %{ $input = enumToInteger($input, "$R_class"); %} -%typemap(scoercein) SWIGTYPE, SWIGTYPE *, SWIGTYPE *const, SWIGTYPE &, SWIGTYPE && +%typemap(scoercein) SWIGTYPE, SWIGTYPE *, SWIGTYPE *const, SWIGTYPE *const&, SWIGTYPE &, SWIGTYPE && %{ if (inherits($input, "ExternalReference")) $input = slot($input,"ref"); %} /* @@ -172,6 +173,10 @@ string &, std::string & %{ $result <- if (is.null($result)) $result else new("$R_class", ref=$result); %} +%typemap(scoerceout) SWIGTYPE *const& + %{ $result <- if (is.null($result)) $result + else new("$*R_class", ref=$result); %} + /* Override the SWIGTYPE * above. */ %typemap(scoerceout) char, From c3f17b415dc63906218306135da49bf1f941588f Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Thu, 13 Oct 2022 23:25:52 +0200 Subject: [PATCH 092/217] Define PY_SSIZE_T_CLEAN only when not defined yet Users of swig 4.0.2 and python 3.10 will likely define the PY_SSIZE_T_CLEAN macro by hand when relevant because their bindings won't build otherwise. Unconditionally defining PY_SSIZE_T_CLEAN in swig 4.10 will lead to macro redefinition warning. Signed-off-by: Michal Suchanek --- Lib/python/embed.i | 2 +- Lib/python/pyruntime.swg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/python/embed.i b/Lib/python/embed.i index 505dd9b57..3fc2d14e5 100644 --- a/Lib/python/embed.i +++ b/Lib/python/embed.i @@ -29,7 +29,7 @@ As far as I know, this module is C++ safe. #endif %wrapper %{ -#ifndef SWIG_NO_PY_SSIZE_T_CLEAN +#if !defined(PY_SSIZE_T_CLEAN) && !defined(SWIG_NO_PY_SSIZE_T_CLEAN) #define PY_SSIZE_T_CLEAN #endif diff --git a/Lib/python/pyruntime.swg b/Lib/python/pyruntime.swg index aa2ecfe08..1d028adaf 100644 --- a/Lib/python/pyruntime.swg +++ b/Lib/python/pyruntime.swg @@ -4,7 +4,7 @@ # include #endif -#ifndef SWIG_NO_PY_SSIZE_T_CLEAN +#if !defined(PY_SSIZE_T_CLEAN) && !defined(SWIG_NO_PY_SSIZE_T_CLEAN) #define PY_SSIZE_T_CLEAN #endif From 3dd7e93c77c0685e043da92d135a22b39a350484 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 14 Oct 2022 09:36:03 +1300 Subject: [PATCH 093/217] Fix issues with exception_memory_leak testcase The out typemap uses a function name which doesn't match the name of the function we want it to apply to, so this testcase wasn't actually triggering an exception so wasn't actually testing anything! With that fixed, the testcase fails to compile for PHP due to use of SWIG_exception_fail() (which not all target languages implement), and with that fixed, the _runme.php needs a try ... catch adding to handle the raised exception. --- Examples/test-suite/exception_memory_leak.i | 11 ++++++++--- .../test-suite/php/exception_memory_leak_runme.php | 6 +++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/exception_memory_leak.i b/Examples/test-suite/exception_memory_leak.i index 835c936fc..2589107b2 100644 --- a/Examples/test-suite/exception_memory_leak.i +++ b/Examples/test-suite/exception_memory_leak.i @@ -1,6 +1,7 @@ %module exception_memory_leak %include +%include %typemap(in) Foo* foo { @@ -11,10 +12,14 @@ Foo::inc_freearg_count(); delete $1; } -%typemap(out) Foo* verify_no_memory_leak +%typemap(out) Foo* trigger_internal_swig_exception { - if ($1 == NULL) - SWIG_exception_fail(SWIG_RuntimeError, "Let's see how the bindings manage this exception!"); + if ($1 == NULL) { + SWIG_exception(SWIG_RuntimeError, "Let's see how the bindings manage this exception!"); +#ifdef SWIG_fail + SWIG_fail; +#endif + } $1 = NULL; } diff --git a/Examples/test-suite/php/exception_memory_leak_runme.php b/Examples/test-suite/php/exception_memory_leak_runme.php index 6ff035cde..3972bb90f 100644 --- a/Examples/test-suite/php/exception_memory_leak_runme.php +++ b/Examples/test-suite/php/exception_memory_leak_runme.php @@ -18,6 +18,10 @@ check::equal(Foo::get_count(), 2, "Should have 2 Foo objects"); check::equal(Foo::get_freearg_count(), 1, "freearg should have been used once"); // SWIG exception triggered and handled. -trigger_internal_swig_exception("null", $b); +try { + trigger_internal_swig_exception("null", $b); + check::fail("Expected exception not thrown"); +} catch (Exception $e) { +} check::equal(Foo::get_count(), 2, "Should have 2 Foo objects"); check::equal(Foo::get_freearg_count(), 2, "freearg should have been used twice"); From 9ab9c716239d2855bdd6c0771e2e980c0767fb57 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 13 Oct 2022 18:27:48 +1300 Subject: [PATCH 094/217] [lua] Run destructors of local C++ objects on SWIG_fail Arrange that destructors of local C++ objects in the wrapper function get run on SWIG_fail (which calls lua_error() which calls longjmp()). We achieve this by putting almost everything in the function in its own block, and end that right before lua_error() at which point those destructors will get called. --- CHANGES.current | 5 ++++ Examples/test-suite/exception_memory_leak.i | 12 ++++++++ .../lua/exception_memory_leak_runme.lua | 29 +++++++++++++++++++ Source/Modules/lua.cxx | 16 +++++++--- 4 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 Examples/test-suite/lua/exception_memory_leak_runme.lua diff --git a/CHANGES.current b/CHANGES.current index d0246156b..e10a46072 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-14: olly + [Lua] Arrange that destructors of local C++ objects in the wrapper + function get run on SWIG_fail (which calls lua_error() which calls + longjmp()). + 2022-10-13: wsfulton [R] Add missing SWIGTYPE *const& typemaps for supporting pointers by const reference. diff --git a/Examples/test-suite/exception_memory_leak.i b/Examples/test-suite/exception_memory_leak.i index 2589107b2..27d199c9f 100644 --- a/Examples/test-suite/exception_memory_leak.i +++ b/Examples/test-suite/exception_memory_leak.i @@ -22,6 +22,13 @@ } $1 = NULL; } +%typemap(out) Foo trigger_internal_swig_exception +{ + SWIG_exception(SWIG_RuntimeError, "Let's see how the bindings manage this exception!"); +#ifdef SWIG_fail + SWIG_fail; +#endif +} %inline %{ #include @@ -47,4 +54,9 @@ return (message == "null") ? NULL : foo; } + static Foo trigger_internal_swig_exception(const std::string& message) + { + return Foo(); + } + %} diff --git a/Examples/test-suite/lua/exception_memory_leak_runme.lua b/Examples/test-suite/lua/exception_memory_leak_runme.lua new file mode 100644 index 000000000..f3fc0f27b --- /dev/null +++ b/Examples/test-suite/lua/exception_memory_leak_runme.lua @@ -0,0 +1,29 @@ +require("import") -- the import fn +import("exception_memory_leak") -- import code +eml=exception_memory_leak --alias + +-- catch "undefined" global variables +local env = _ENV -- Lua 5.2 +if not env then env = getfenv () end -- Lua 5.1 +setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end}) + +a = eml.Foo() +assert(eml.Foo_get_count() == 1) +b = eml.Foo() +assert(eml.Foo_get_count() == 2) + +-- Normal behaviour +eml.trigger_internal_swig_exception("no problem", a) +assert(eml.Foo_get_count() == 2) +assert(eml.Foo_get_freearg_count() == 1) + +-- SWIG exception triggered and handled (return new object case) +ok,ex=pcall(eml.trigger_internal_swig_exception, "null", b) +assert(ok==false) +assert(eml.Foo_get_count() == 2) +assert(eml.Foo_get_freearg_count() == 2) + +-- SWIG exception triggered and handled (return by value case). +ok,ex=pcall(eml.trigger_internal_swig_exception, "null") +assert(ok==false) +assert(eml.Foo_get_count() == 2) diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx index c2e65dba6..d3cf96b52 100644 --- a/Source/Modules/lua.cxx +++ b/Source/Modules/lua.cxx @@ -556,6 +556,12 @@ public: this line adds this into the wrapper code NEW LANGUAGE NOTE:END *********************************************** */ Printv(f->def, "static int ", wname, "(lua_State* L) {", NIL); + // SWIG_fail in lua leads to a call to lua_error() which calls longjmp() + // which means the destructors of any live function-local C++ objects won't + // get run. To avoid this happening, we wrap almost everything in the + // function in a block, and end that right before lua_error() at which + // point those destructors will get called. + if (CPlusPlus) Append(f->def, "\n{"); /* NEW LANGUAGE NOTE:*********************************************** this prints the list of args, eg for a C fn @@ -766,10 +772,12 @@ public: /* Close the function */ Printv(f->code, "return SWIG_arg;\n", NIL); // add the failure cleanup code: - Printv(f->code, "\nif(0) SWIG_fail;\n", NIL); - Printv(f->code, "\nfail:\n", NIL); - Printv(f->code, "$cleanup", "lua_error(L);\n", NIL); - Printv(f->code, "return SWIG_arg;\n", NIL); + Printv(f->code, "\nfail: SWIGUNUSED;\n", "$cleanup", NIL); + if (CPlusPlus) Append(f->code, "}\n"); + Printv(f->code, "lua_error(L);\n", NIL); + // lua_error() calls longjmp() but we need a dummy return to avoid compiler + // warnings. + Printv(f->code, "return 0;\n", NIL); Printf(f->code, "}\n"); /* Substitute the cleanup code */ From fefb231bd858885168d6af86a0bfb2af3e62961e Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 14 Oct 2022 13:09:01 +1300 Subject: [PATCH 095/217] [php] Update exception_memory_leak_runme.php Test the new "return by value" case too. --- .../test-suite/php/exception_memory_leak_runme.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/php/exception_memory_leak_runme.php b/Examples/test-suite/php/exception_memory_leak_runme.php index 3972bb90f..116ab2f0e 100644 --- a/Examples/test-suite/php/exception_memory_leak_runme.php +++ b/Examples/test-suite/php/exception_memory_leak_runme.php @@ -17,7 +17,7 @@ trigger_internal_swig_exception("no problem", $a); check::equal(Foo::get_count(), 2, "Should have 2 Foo objects"); check::equal(Foo::get_freearg_count(), 1, "freearg should have been used once"); -// SWIG exception triggered and handled. +// SWIG exception triggered and handled (return new object case). try { trigger_internal_swig_exception("null", $b); check::fail("Expected exception not thrown"); @@ -25,3 +25,11 @@ try { } check::equal(Foo::get_count(), 2, "Should have 2 Foo objects"); check::equal(Foo::get_freearg_count(), 2, "freearg should have been used twice"); + +// SWIG exception triggered and handled (return by value case). +try { + trigger_internal_swig_exception("null"); + check::fail("Expected exception not thrown"); +} catch (Exception $e) { +} +check::equal(Foo::get_count(), 2, "Should have 2 Foo objects"); From 5f96d15943ccf3e588dccbe8a9c3267070b61bbe Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 14 Oct 2022 13:18:56 +1300 Subject: [PATCH 096/217] [R] Run destructors of local C++ objects on SWIG_fail Arrange that destructors of local C++ objects in the wrapper function get run on SWIG_fail (which calls Rf_error() which calls longjmp()). We achieve this by putting almost everything in the function in its own block, and end that right before Rf_error() at which point those destructors will get called. --- CHANGES.current | 5 +++++ Examples/test-suite/r/exception_memory_leak_runme.R | 13 ++++++++++++- Source/Modules/r.cxx | 8 ++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index e10a46072..ae2fb8ffe 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-14: olly + [R] Arrange that destructors of local C++ objects in the wrapper + function get run on SWIG_fail (which calls Rf_error() which calls + longjmp()). + 2022-10-14: olly [Lua] Arrange that destructors of local C++ objects in the wrapper function get run on SWIG_fail (which calls lua_error() which calls diff --git a/Examples/test-suite/r/exception_memory_leak_runme.R b/Examples/test-suite/r/exception_memory_leak_runme.R index 1f770420a..889fbedc9 100644 --- a/Examples/test-suite/r/exception_memory_leak_runme.R +++ b/Examples/test-suite/r/exception_memory_leak_runme.R @@ -14,7 +14,7 @@ unittest(Foo_get_count(), 2); invisible(trigger_internal_swig_exception("no problem", a)); unittest(Foo_get_count(), 2); unittest(Foo_get_freearg_count(), 1); -# SWIG exception introduced +# SWIG exception introduced (return new object case). result <- tryCatch({ trigger_internal_swig_exception("null", b); }, warning = function(w) { @@ -26,3 +26,14 @@ result <- tryCatch({ }) unittest(Foo_get_count(), 2); unittest(Foo_get_freearg_count(), 2); +# SWIG exception introduced (return by value case). +result <- tryCatch({ + trigger_internal_swig_exception("null"); +}, warning = function(w) { + # print(" Hum... We received a warning, but this should be an error"); + unittest(1,0); +}, error = function(e) { + # print(" Gotcha!"); + unittest(1,1); +}) +unittest(Foo_get_count(), 2); diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 565145327..526d959f4 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -1970,6 +1970,13 @@ int R::functionWrapper(Node *n) { } Printv(f->def, ")\n{\n", NIL); + // SWIG_fail in R leads to a call to Rf_error() which calls longjmp() + // which means the destructors of any live function-local C++ objects won't + // get run. To avoid this happening, we wrap almost everything in the + // function in a block, and end that right before Rf_error() at which + // point those destructors will get called. + if (CPlusPlus) Append(f->def, "{\n"); + Printv(sfun->def, ")\n{\n", NIL); @@ -2123,6 +2130,7 @@ int R::functionWrapper(Node *n) { if (need_cleanup) { Printv(f->code, cleanup, NIL); } + if (CPlusPlus) Append(f->code, "}\n"); Printv(f->code, " Rf_error(\"%s %s\", SWIG_ErrorType(SWIG_lasterror_code), SWIG_lasterror_msg);\n", NIL); Printv(f->code, " return R_NilValue;\n", NIL); Delete(cleanup); From 54497fce49485f138211f6188009dc103b7e05cc Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 14 Oct 2022 08:45:38 +0100 Subject: [PATCH 097/217] html fixes --- Doc/Manual/Contents.html | 1 + Doc/Manual/Php.html | 2 +- Doc/Manual/Windows.html | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index d3106bf09..fd74ab299 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -1351,6 +1351,7 @@
  • Static Member Variables
  • Static Member Functions
  • Specifying Implemented Interfaces +
  • Dynamic Properties
  • PHP Pragmas, Startup and Shutdown code diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 49d0474f7..97a48b707 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -866,7 +866,7 @@ not work by default in PHP 9.0. In PHP code dynamic properties can be enabled for a class by marking that class with the attribute #[AllowDynamicProperties].

    - +

    To follow this PHP change, as of SWIG 4.1.0 you now need enable dynamic properties for any classes you want to support them. To enable for class diff --git a/Doc/Manual/Windows.html b/Doc/Manual/Windows.html index 80f4be3f9..3bbfc9028 100644 --- a/Doc/Manual/Windows.html +++ b/Doc/Manual/Windows.html @@ -240,7 +240,7 @@ For fully working build steps always check the Continuous Integration (CI) setup

  • Install CMake-win64 Nuget package using the following command:
    C:\Tools\nuget install CMake-win64 -Version 3.15.5 -OutputDirectory C:\Tools\CMake
    - Using PowerShell the equivalent syntax is:
    &"C:\Tools\nuget" install CMake-win64 -Version 3.15.5 -OutputDirectory C:\Tools\CMake
    + Using PowerShell the equivalent syntax is:
    & "C:\Tools\nuget" install CMake-win64 -Version 3.15.5 -OutputDirectory C:\Tools\CMake
    Alternatively you can download CMake from https://cmake.org/download/.
  • From 1b5c4546baff28c7820cc45902841b7deb3e4872 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 14 Oct 2022 19:25:13 +0100 Subject: [PATCH 098/217] Add v8 numeric change to changes file --- CHANGES.current | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index ae2fb8ffe..9d4160d37 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-14: murillo128 + [Javascript] #2109 Tweak unsigned long and unsigned long long typemaps + to create a v8::Number instead of v8::Integer if the value exceeds + the size of v8::Integer. Note that the v8::Number value will be + imprecise if the value is > MAX_SAFE_INTEGER. + 2022-10-14: olly [R] Arrange that destructors of local C++ objects in the wrapper function get run on SWIG_fail (which calls Rf_error() which calls From 15c433c5f9fdc1f1b330b042fe01c5ca8426c1ee Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 14 Oct 2022 22:34:18 +0100 Subject: [PATCH 099/217] C89 fixes --- Source/Swig/cwrap.c | 2 +- Source/Swig/misc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index 36d207050..b7d01bc11 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -15,7 +15,7 @@ #include "swig.h" #include "cparse.h" -extern int UseWrapperSuffix; // from main.cxx +extern int UseWrapperSuffix; static const char *cresult_variable_name = "result"; diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index 18c29f76a..7d1119c5e 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -81,7 +81,7 @@ String *Swig_package_version_hex(void) { count++; } Delete(package_version); - assert(count == 3); // Check version format is correct + assert(count == 3); /* Check version format is correct */ return vers; } From fd2420cdcc37941ba5f599f016ceab2b685b7d23 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 14 Oct 2022 22:48:54 +0100 Subject: [PATCH 100/217] Remove STRING_VALUE to keep supporting older versions of R STRING_VALUE does not work with R_NO_REMAP in older versions (it broke 3.0.2) --- Lib/r/r.swg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/r/r.swg b/Lib/r/r.swg index eeabcf4ba..6907375d6 100644 --- a/Lib/r/r.swg +++ b/Lib/r/r.swg @@ -28,7 +28,7 @@ SWIGEXPORT void SWIG_init(void) { %runtime %{ void SWIG_R_Raise(SEXP obj, const char *msg) { - Rf_error(Rf_isString(obj) ? STRING_VALUE(obj) : msg); + Rf_error(Rf_isString(obj) ? CHAR(Rf_asChar(obj)) : msg); } %} From 0e60d6b7a40e79e1d8a2ad73384acd410f846085 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 14 Oct 2022 22:51:26 +0100 Subject: [PATCH 101/217] Correct new Raise functions to be static --- Lib/octave/octtypemaps.swg | 2 +- Lib/r/r.swg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/octave/octtypemaps.swg b/Lib/octave/octtypemaps.swg index 652112312..4984fddf7 100644 --- a/Lib/octave/octtypemaps.swg +++ b/Lib/octave/octtypemaps.swg @@ -33,7 +33,7 @@ // raise %runtime %{ -void SWIG_Octave_Raise(const octave_value &obj, const char *type) { +SWIGINTERN void SWIG_Octave_Raise(const octave_value &obj, const char *type) { if (obj.is_string()) error("%s", obj.string_value().c_str()); else diff --git a/Lib/r/r.swg b/Lib/r/r.swg index 6907375d6..c1ce37c3e 100644 --- a/Lib/r/r.swg +++ b/Lib/r/r.swg @@ -27,7 +27,7 @@ SWIGEXPORT void SWIG_init(void) { %end_block %enddef %runtime %{ -void SWIG_R_Raise(SEXP obj, const char *msg) { +SWIGINTERN void SWIG_R_Raise(SEXP obj, const char *msg) { Rf_error(Rf_isString(obj) ? CHAR(Rf_asChar(obj)) : msg); } %} From 7be1217d3ecb57b48111b47e543e793bcc917c18 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 15 Oct 2022 00:20:22 +0100 Subject: [PATCH 102/217] Allow wkhtmltopdf to access current directory Fix for version 0.12.6, see https://github.com/wkhtmltopdf/wkhtmltopdf/issues/4536 --- Doc/Manual/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/Manual/Makefile b/Doc/Manual/Makefile index 440b3153f..0f9fe0e96 100644 --- a/Doc/Manual/Makefile +++ b/Doc/Manual/Makefile @@ -1,7 +1,7 @@ # Makefile for generating the SWIG documentation # # Note that the htmldoc package needs to be installed. wkhtmltopdf patched with qt is also required -# and can be installed from https://wkhtmltopdf.org/downloads.html. +# and the prebuilt binaries can be installed from https://wkhtmltopdf.org/downloads.html. # # The .html files are first processed and updated with chapter numbering and anchor names # are added to the HTML headings using the python scripts. The htmldoc program is then @@ -44,7 +44,7 @@ check: # Courier font to fix - these have been added to style.css. generate: SWIGDocumentation.html wkhtmltopdf --version | grep "with patched qt" || (echo "wkhtmltopdf is not the patched qt version and so cannot be used - download it from https://wkhtmltopdf.org/downloads.html" && false) - wkhtmltopdf --margin-top 20mm --margin-bottom 20mm --margin-left 10mm --margin-right 10mm --header-font-size 6 --footer-font-size 6 --header-spacing 6 --footer-spacing 6 --header-center '[doctitle]' --footer-left '[subsection]' --footer-right '[page]' SWIGDocumentation.html SWIGDocumentation.pdf + wkhtmltopdf --margin-top 20mm --margin-bottom 20mm --margin-left 10mm --margin-right 10mm --header-font-size 6 --footer-font-size 6 --header-spacing 6 --footer-spacing 6 --header-center '[doctitle]' --footer-left '[subsection]' --footer-right '[page]' --allow . SWIGDocumentation.html SWIGDocumentation.pdf SWIGDocumentation.html: swightml.book htmldoc --batch swightml.book || true From 1c70dbdb6c23a64c58c55ce1e509b908e972eabb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 15 Oct 2022 00:27:52 +0100 Subject: [PATCH 103/217] Bump doc version to SWIG-4.1 --- Doc/Manual/Sections.html | 4 ++-- Doc/Manual/index.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html index 13a9a2181..2a0d023a2 100644 --- a/Doc/Manual/Sections.html +++ b/Doc/Manual/Sections.html @@ -1,11 +1,11 @@ -SWIG-4.0 Documentation +SWIG-4.1 Documentation -

    SWIG-4.0 Documentation

    +

    SWIG-4.1 Documentation

    Last update : SWIG-4.1.0 (in progress) diff --git a/Doc/Manual/index.html b/Doc/Manual/index.html index e720e70d0..2c44e6759 100644 --- a/Doc/Manual/index.html +++ b/Doc/Manual/index.html @@ -1,11 +1,11 @@ -SWIG-4.0 Documentation +SWIG-4.1 Documentation -

    SWIG-4.0 Documentation

    +

    SWIG-4.1 Documentation

    The SWIG documentation is available in one of the following formats.
      From 4c86f45c54fbeffc43cd56e9c973aabb97841634 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 15 Oct 2022 00:51:58 +0100 Subject: [PATCH 104/217] Fix for Java 7 - std::set and std::unordered_set --- Lib/java/std_set.i | 4 ++++ Lib/java/std_unordered_set.i | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Lib/java/std_set.i b/Lib/java/std_set.i index 73e0c2cf9..053866bc7 100644 --- a/Lib/java/std_set.i +++ b/Lib/java/std_set.i @@ -96,6 +96,10 @@ class set { public boolean hasNext() { return curr.isNot(end); } + + public void remove() { + throw new java.lang.UnsupportedOperationException(); + } }.init(); } diff --git a/Lib/java/std_unordered_set.i b/Lib/java/std_unordered_set.i index 59726e94d..ddcedf052 100644 --- a/Lib/java/std_unordered_set.i +++ b/Lib/java/std_unordered_set.i @@ -92,6 +92,10 @@ class unordered_set { public boolean hasNext() { return curr.isNot(end); } + + public void remove() { + throw new java.lang.UnsupportedOperationException(); + } }.init(); } From e622a708d22049ba5565bf32b8c64b4245c3906f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 15 Oct 2022 11:25:47 +0100 Subject: [PATCH 105/217] Fix Javascript node test-suite to use desired c++ standard Passes the -std determined in configure.ac to node-gyp --- Examples/test-suite/javascript/Makefile.in | 3 ++- Examples/test-suite/javascript/node_template/binding.gyp.in | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/javascript/Makefile.in b/Examples/test-suite/javascript/Makefile.in index 8772851a8..4835453cc 100644 --- a/Examples/test-suite/javascript/Makefile.in +++ b/Examples/test-suite/javascript/Makefile.in @@ -8,6 +8,7 @@ NODEJS = @NODEJS@ SCRIPTSUFFIX = _runme.js OBJEXT = @OBJEXT@ SO = @SO@ +GYP_CXXFLAGS = @BOOST_CPPFLAGS@ @PLATCXXFLAGS@ HAVE_CXX11 = @HAVE_CXX11@ HAVE_CXX14 = @HAVE_CXX14@ @@ -63,7 +64,7 @@ ifeq (node,$(JSENGINE)) setup_node = \ test -d $* || mkdir $* && \ - sed -e 's|$$testcase|$*|g; s|$$cflags|$(GYP_CFLAGS)|g; s|$$srcdir|$(srcdir)|g' \ + sed -e 's|$$testcase|$*|g; s|$$cflags|$(GYP_CFLAGS)|g; s|$$cxxflags|"$(GYP_CXXFLAGS)"|g; s|$$srcdir|$(srcdir)|g' \ $(srcdir)/node_template/binding.gyp.in > $*/binding.gyp && \ sed -e 's|$$testcase|$*|g;' \ $(srcdir)/node_template/index.js.in > $*/index.js diff --git a/Examples/test-suite/javascript/node_template/binding.gyp.in b/Examples/test-suite/javascript/node_template/binding.gyp.in index a82ac2f3e..87e70bb5b 100644 --- a/Examples/test-suite/javascript/node_template/binding.gyp.in +++ b/Examples/test-suite/javascript/node_template/binding.gyp.in @@ -19,7 +19,7 @@ ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', { 'cflags': [ "-Wno-unused-variable", "-Wno-unused-but-set-variable", "-Wno-unused-but-set-parameter", $cflags], - 'cflags_cc': [ "-Wno-unused-variable", "-Wno-unused-but-set-variable", "-Wno-unused-but-set-parameter", $cflags], + 'cflags_cc': [ "-Wno-unused-variable", "-Wno-unused-but-set-variable", "-Wno-unused-but-set-parameter", $cxxflags, $cflags], 'cflags!': [ '-fno-exceptions' ], 'cflags_cc!': [ '-fno-exceptions', '-fno-rtti' ] } From d58eb86821d2da4e97bf0a1f729fbf8172edfa98 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 15 Oct 2022 14:56:39 +0100 Subject: [PATCH 106/217] Testcase warning fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Workaround for seemingly bogus warning: ‘[0]’ may be used uninitialized [-Wmaybe-uninitialized] --- Examples/test-suite/cpp11_initializer_list.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/test-suite/cpp11_initializer_list.i b/Examples/test-suite/cpp11_initializer_list.i index c1646248c..7e86cc025 100644 --- a/Examples/test-suite/cpp11_initializer_list.i +++ b/Examples/test-suite/cpp11_initializer_list.i @@ -39,7 +39,7 @@ class C { public: C(std::initializer_list init) { for (auto& val : init) - joined += val; + joined = joined + val; } C() {} const char * get_joined_string() { From d8a028601247e96c15bbaac08100cce0401f186e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 17 Oct 2022 20:13:32 +0100 Subject: [PATCH 107/217] R - Add support for std::vector> Closes #2385 --- CHANGES.current | 3 ++ Examples/test-suite/common.mk | 1 + Examples/test-suite/li_std_vector_vector.i | 50 +++++++++++++++++++ .../test-suite/r/li_std_vector_vector_runme.R | 28 +++++++++++ Examples/test-suite/r/unittest.R | 13 ++++- Lib/r/std_vector.i | 38 ++++++++++++-- 6 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 Examples/test-suite/li_std_vector_vector.i create mode 100644 Examples/test-suite/r/li_std_vector_vector_runme.R diff --git a/CHANGES.current b/CHANGES.current index 9d4160d37..0a23158a2 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-17: wsfulton + [R] #2385 Add support for std::vector>. + 2022-10-14: murillo128 [Javascript] #2109 Tweak unsigned long and unsigned long long typemaps to create a v8::Number instead of v8::Integer if the value exceeds diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 1c70ece4c..4681571e2 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -714,6 +714,7 @@ CPP_STD_TEST_CASES += \ li_std_vector_enum \ li_std_vector_member_var\ li_std_vector_ptr \ + li_std_vector_vector \ li_std_wstring \ smart_pointer_inherit \ template_typedef_fnc \ diff --git a/Examples/test-suite/li_std_vector_vector.i b/Examples/test-suite/li_std_vector_vector.i new file mode 100644 index 000000000..fbffc8d81 --- /dev/null +++ b/Examples/test-suite/li_std_vector_vector.i @@ -0,0 +1,50 @@ +%module li_std_vector_vector + +%include +%include + +namespace std { + %template(VectorInt) vector; + %template(VectorString) vector; + %template(VectorVectorInt) vector>; + %template(VectorVectorString) vector>; +}; + +%inline %{ +std::vector make_vector_int() { + std::vector v = {"1", "2", "3", "4", "5"}; + return v; +} + +std::vector > make_vector_vector_int() { + std::vector > vv; + std::vector v = {1, 2, 3, 4, 5}; + vv.push_back(v); + return vv; +} + +std::vector make_vector_bool() { + std::vector v = {true, false, false, false, true}; + return v; +} + +std::vector > make_vector_vector_bool() { + std::vector > vv; + std::vector v = {false, true, true, true, false}; + vv.push_back(v); + return vv; +} + +std::vector make_vector_string() { + std::vector v = {"aa", "bb", "cc", "dd", "ee"}; + return v; +} + +std::vector > make_vector_vector_string() { + std::vector > vv; + std::vector v = {"1", "2", "3", "4", "5"}; + vv.push_back(v); + return vv; +} + +%} diff --git a/Examples/test-suite/r/li_std_vector_vector_runme.R b/Examples/test-suite/r/li_std_vector_vector_runme.R new file mode 100644 index 000000000..c2c8853b2 --- /dev/null +++ b/Examples/test-suite/r/li_std_vector_vector_runme.R @@ -0,0 +1,28 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + +dyn.load(paste("li_std_vector_vector", .Platform$dynlib.ext, sep="")) +source("li_std_vector_vector.R") +cacheMetaData(1) + +v = make_vector_int() +unittest_sequence(v, list(1, 2, 3, 4, 5)) +v = make_vector_vector_int() +unittest(length(v), 1) +unittest_sequence(v[[1]], list(1, 2, 3, 4, 5)) + +v = make_vector_bool() +unittest_sequence(v, list(TRUE, FALSE, FALSE, FALSE, TRUE)) +print(v) +v = make_vector_vector_bool() +unittest(length(v), 1) +print(v) +unittest_sequence(v[[1]], list(FALSE, TRUE, TRUE, TRUE, FALSE)) # Does not actually fail if no match, arg, needs fixing + +v = make_vector_string() +unittest_sequence(v, list("aa", "bb", "cc", "dd", "ee")) +v = make_vector_vector_string() +unittest(length(v), 1) +unittest_sequence(v[[1]], list("1", "2", "3", "4", "5")) + +q(save="no") diff --git a/Examples/test-suite/r/unittest.R b/Examples/test-suite/r/unittest.R index b55b4a3f3..481be8ecc 100644 --- a/Examples/test-suite/r/unittest.R +++ b/Examples/test-suite/r/unittest.R @@ -1,8 +1,8 @@ unittest <- function (x,y) { if (all(x==y)) { - print("PASS") + print("PASS") } else { - print("FAIL") + print("FAIL") stop("Test failed") } } @@ -15,3 +15,12 @@ unittesttol <- function(x,y,z) { stop("Test failed") } } + +unittest_sequence <- function (x,y) { + if (setequal(x, y)) { + print("PASS") + } else { + print("FAIL") + stop("Test failed") + } +} diff --git a/Lib/r/std_vector.i b/Lib/r/std_vector.i index 93d1c6256..62478fe6a 100644 --- a/Lib/r/std_vector.i +++ b/Lib/r/std_vector.i @@ -660,6 +660,27 @@ } }; + template <> + struct traits_from_ptr > > > { + static SEXP from (std::vector< std::vector > > *val, int owner = 0) { + SEXP result; + // allocate the R list + PROTECT(result = Rf_allocVector(VECSXP, val->size())); + for (unsigned pos = 0; pos < val->size(); pos++) + { + // allocate the R vector + SET_VECTOR_ELT(result, pos, Rf_allocVector(STRSXP, val->at(pos).size())); + // Fill the R vector + for (unsigned vpos = 0; vpos < val->at(pos).size(); ++vpos) + { + CHARACTER_POINTER(VECTOR_ELT(result, pos))[vpos] = Rf_mkChar(val->at(pos).at(vpos).c_str()); + } + } + UNPROTECT(1); + return(result); + } + }; + template struct traits_from_ptr< std::vector < std::vector< T > > > { static SEXP from (std::vector < std::vector< T > > *val, int owner = 0) { @@ -887,8 +908,6 @@ std::vector< std::basic_string > *, std::vector< std::basic_string > & %{ %} -%apply std::vector< std::basic_string > { std::vector< std::string> }; - // all the related integer vectors // signed %typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector); @@ -1005,6 +1024,13 @@ std::vector< std::basic_string > *, %typemap("rtype") std::vector >, std::vector > *, std::vector > & "list" %typemap("scoercein") std::vector< std::vector >, std::vector > *, std::vector > & "$input = lapply($input, as.logical);" +%typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector > >); +%traits_type_name(std::vector< std::vector > >); +%typemap("rtypecheck") std::vector > >, std::vector > > *, std::vector > > & + %{ is.list($arg) && all(sapply($arg , is.character)) %} +%typemap("rtype") std::vector > >, std::vector > > *, std::vector > > & "list" +%typemap("scoercein") std::vector< std::vector > >, std::vector > > *, std::vector > > & "$input = lapply($input, as.character);" + // we don't want these to be given R classes as they // have already been turned into R vectors. %typemap(scoerceout) std::vector, @@ -1049,7 +1075,10 @@ std::vector< std::basic_string > *, std::vector< std::vector >&, std::vector< std::vector >, std::vector< std::vector >*, - std::vector< std::vector >& + std::vector< std::vector >&, + std::vector< std::vector > >, + std::vector< std::vector > >*, + std::vector< std::vector > >& %{ %} #if defined(SWIGWORDSIZE64) @@ -1071,3 +1100,6 @@ std::vector< std::basic_string > *, %{ %} #endif + +%apply std::vector< std::basic_string > { std::vector }; +%apply std::vector< std::vector< std::basic_string > > { std::vector< std::vector > }; From 747a6a264f56711c7b725cf883ef623e01b65922 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 18 Oct 2022 10:28:17 +1300 Subject: [PATCH 108/217] [php] Fix handling of multi-module cases Look up unknown base classes using SWIG_MangledTypeQueryModule(). Revert to using SWIG_TypeCheck() instead of SWIG_TypeCheckStruct() as the latter doesn't seem to work for this case (at least for PHP right now). Add mod_runme.php as a regression test for this. Adjust the PHP test harness not to set up reflection for the module unless it's actually needed for a testcase. Currently the approach to find the module name doesn't work for multi-module testcases. See #2126 --- Examples/Makefile.in | 3 +++ Examples/test-suite/php/Makefile.in | 23 ++++++++++++++++--- Examples/test-suite/php/mod_runme.php | 9 ++++++++ Examples/test-suite/php/tests.php | 33 +++++++++++++-------------- Lib/php/phprun.swg | 2 +- Source/Modules/php.cxx | 9 ++++++-- 6 files changed, 56 insertions(+), 23 deletions(-) create mode 100644 Examples/test-suite/php/mod_runme.php diff --git a/Examples/Makefile.in b/Examples/Makefile.in index e28e48149..46193348d 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -1215,6 +1215,9 @@ php_cpp: $(SRCDIR_SRCS) php_run: $(RUNTOOL) $(PHP) -n -d extension_dir=. -d extension=$(PHP_EXTENSION) -d display_errors=stderr -r 'set_error_handler(function($$n,$$s,$$f,$$l){if($$f!==Null){print$$f;if($$l!==Null)print":$$l";print": ";}print"$$s\n";exit(1);});if(strlen($$argv[1]))include($$argv[1]);' '$(PHP_SCRIPT)' $(RUNPIPE) +php_run_multi: + $(RUNTOOL) $(PHP) -n -d extension_dir=. `while read e ; do echo ' -d extension=$(TARGETPREFIX)'"$$e"'@PHP_SO@' ; done < $(PHP_EXTENSION_LIST)` -d display_errors=stderr -r 'set_error_handler(function($$n,$$s,$$f,$$l){if($$f!==Null){print$$f;if($$l!==Null)print":$$l";print": ";}print"$$s\n";exit(1);});if(strlen($$argv[1]))include($$argv[1]);' '$(PHP_SCRIPT)' $(RUNPIPE) + # ----------------------------------------------------------------- # Version display # ----------------------------------------------------------------- diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index c918581bf..3811bd024 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -57,10 +57,18 @@ missingtests: missingcpptests missingctests +$(swig_and_compile_c) +$(run_testcase) +# Trying to load the modules for imports.multicpptest fails with: +# +# Warning: Function registration failed - duplicate name - global_test in Unknown on line 0 +# Segmentation fault +# +# This was previously hidden because we didn't even try to load the modules for +# .multicpptest testcases, so for now just do the parts of the test we did +# before. FIXME: Fix this! %.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) - +$(run_testcase) + +[ "$*" = "imports" ] || $(run_multi_testcase) # Smart target %.test: @@ -72,14 +80,23 @@ missingtests: missingcpptests missingctests $(MAKE) $*.multicpptest # Runs the testcase. Tries to run testcase_runme.php, and if that's not found, -# at least test that the module loads without errors, except for multicpptests. +# at least test that the module loads without errors. run_testcase = \ if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION=$(TARGETPREFIX)$*@PHP_SO@ PHP_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) RUNTOOL='$(RUNTOOL)' php_run; \ - elif [ ! -f $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list ]; then \ + else \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION=$(TARGETPREFIX)$*@PHP_SO@ PHP_SCRIPT= RUNTOOL='$(RUNTOOL)' php_run; \ fi +# Runs a multicpptest testcase. Tries to run testcase_runme.php, and if that's +# not found, at least test that the modules load without errors. +run_multi_testcase = \ + if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION_LIST=$(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list PHP_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) RUNTOOL='$(RUNTOOL)' php_run_multi; \ + else \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION_LIST=$(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list PHP_SCRIPT= RUNTOOL='$(RUNTOOL)' php_run_multi; \ + fi + # Clean: remove the generated PHP-specific files %.clean: @rm -f php_$*.h diff --git a/Examples/test-suite/php/mod_runme.php b/Examples/test-suite/php/mod_runme.php new file mode 100644 index 000000000..6e485ce80 --- /dev/null +++ b/Examples/test-suite/php/mod_runme.php @@ -0,0 +1,9 @@ +DoSomething($c); + +check::done(); diff --git a/Examples/test-suite/php/tests.php b/Examples/test-suite/php/tests.php index 0ff20e377..7213d7094 100644 --- a/Examples/test-suite/php/tests.php +++ b/Examples/test-suite/php/tests.php @@ -9,18 +9,19 @@ class check { private static $_werror = false; - // This is called automatically at the end of this file. - static function init() { - foreach(get_included_files() as $f) { - $module_name = preg_filter('/.*\/([^\/]+)_runme\.php$/', '\1', $f); - if ($module_name !== null) break; + static function get_extension() { + if (self::$_extension === null) { + foreach(get_included_files() as $f) { + $module_name = preg_filter('/.*\/([^\/]+)_runme\.php$/', '\1', $f); + if ($module_name !== null) break; + } + if ($module_name === null) { + print("Failed to determine module name from get_included_files()\n"); + exit(1); + } + self::$_extension = new ReflectionExtension($module_name); } - if ($module_name === null) { - print("Failed to determine module name from get_included_files()\n"); - exit(1); - } - - self::$_extension = new ReflectionExtension($module_name); + return self::$_extension; } static function werror($v) { @@ -92,7 +93,7 @@ class check { if (! is_array($classes)) $classes=array($classes); $message=array(); $missing=array(); - $extra = array_flip(array_filter(self::$_extension->getClassNames(), + $extra = array_flip(array_filter(self::get_extension()->getClassNames(), function ($e) { return !preg_match('/^SWIG\\\\/', $e); })); foreach($classes as $class) { if (! class_exists($class)) $missing[]=$class; @@ -109,7 +110,7 @@ class check { if (! is_array($functions)) $functions=array($functions); $message=array(); $missing=array(); - $extra = self::$_extension->getFunctions(); + $extra = self::get_extension()->getFunctions(); foreach ($functions as $func) { if (! function_exists($func)) $missing[]=$func; else unset($extra[$func]); @@ -127,7 +128,7 @@ class check { if (! is_array($globals)) $globals=array($globals); $message=array(); $missing=array(); - $extra = self::$_extension->getFunctions(); + $extra = self::get_extension()->getFunctions(); foreach ($globals as $glob) { if (! function_exists($glob . "_get") && ! function_exists($glob . "_set")) $missing[]=$glob; else { @@ -149,7 +150,7 @@ class check { if (! is_array($constants)) $constants=array($constants); $message=array(); $missing=array(); - $extra = self::$_extension->getConstants(); + $extra = self::get_extension()->getConstants(); unset($extra['swig_runtime_data_type_pointer']); foreach($constants as $constant) { if (! defined($constant)) $missing[]=$constant; @@ -213,5 +214,3 @@ class check { # print $_SERVER[argv][0]." ok\n"; } } - -check::init(); diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index 538b7e165..d3ad0d26a 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -193,7 +193,7 @@ SWIG_ConvertPtrAndOwn(zval *z, void **ptr, swig_type_info *ty, int flags, swig_o /* They don't care about the target type, so just pass on the pointer! */ *ptr = value->ptr; } else { - swig_cast_info *tc = SWIG_TypeCheckStruct(value->type, ty); + swig_cast_info *tc = SWIG_TypeCheck(value->type->name, ty); if (tc) { int newmemory = 0; *ptr = SWIG_TypeCast(tc, value->ptr, &newmemory); diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index a2e741215..fd53d41f7 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1836,13 +1836,18 @@ public: base_class = NewString("Exception"); } - if (Equal(base_class, "Exception")) { + if (!base_class) { + Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", class_name); + } else if (Equal(base_class, "Exception")) { Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, zend_ce_exception);\n", class_name); } else if (is_class_wrapped(base_class)) { Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, SWIG_Php_ce_%s);\n", class_name, base_class); Setattr(php_parent_class, class_name, base_class); } else { - Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", class_name); + Printf(s_oinit, " {\n"); + Printf(s_oinit, " swig_type_info *type_info = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, \"_p_%s\");\n", base_class); + Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, (zend_class_entry*)(type_info ? type_info->clientdata : NULL));\n", class_name); + Printf(s_oinit, " }\n"); } if (Getattr(n, "abstracts") && !GetFlag(n, "feature:notabstract")) { From 01627edaff3630886ea4d2a365d210a2dd31f1a6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 18 Oct 2022 08:05:49 +0100 Subject: [PATCH 109/217] Remove C++11 from li_std_vector_vector testcase --- Examples/test-suite/li_std_vector_vector.i | 30 +++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/Examples/test-suite/li_std_vector_vector.i b/Examples/test-suite/li_std_vector_vector.i index fbffc8d81..940f56a51 100644 --- a/Examples/test-suite/li_std_vector_vector.i +++ b/Examples/test-suite/li_std_vector_vector.i @@ -12,37 +12,55 @@ namespace std { %inline %{ std::vector make_vector_int() { - std::vector v = {"1", "2", "3", "4", "5"}; + std::string x[5] = {"1", "2", "3", "4", "5"}; + std::vector v; + for (size_t i = 0; i < 5; ++i) + v.push_back(x[i]); return v; } std::vector > make_vector_vector_int() { + int x[5] = {1, 2, 3, 4, 5}; std::vector > vv; - std::vector v = {1, 2, 3, 4, 5}; + std::vector v; + for (size_t i = 0; i < 5; ++i) + v.push_back(x[i]); vv.push_back(v); return vv; } std::vector make_vector_bool() { - std::vector v = {true, false, false, false, true}; + bool x[5] = {true, false, false, false, true}; + std::vector v; + for (size_t i = 0; i < 5; ++i) + v.push_back(x[i]); return v; } std::vector > make_vector_vector_bool() { + bool x[5] = {false, true, true, true, false}; std::vector > vv; - std::vector v = {false, true, true, true, false}; + std::vector v; + for (size_t i = 0; i < 5; ++i) + v.push_back(x[i]); vv.push_back(v); return vv; } std::vector make_vector_string() { - std::vector v = {"aa", "bb", "cc", "dd", "ee"}; + std::string x[5] = {"aa", "bb", "cc", "dd", "ee"}; + std::vector v; + for (size_t i = 0; i < 5; ++i) + v.push_back(x[i]); return v; } std::vector > make_vector_vector_string() { + std::string x[5] = {"1", "2", "3", "4", "5"}; std::vector > vv; - std::vector v = {"1", "2", "3", "4", "5"}; + std::vector v; + for (size_t i = 0; i < 5; ++i) + v.push_back(x[i]); vv.push_back(v); return vv; } From 76b700d2e0e41c8a42aa0ee476ceea2d0527ea13 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 19 Oct 2022 07:35:31 +1300 Subject: [PATCH 110/217] CHANGES: Add blank line before 4.0.0 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 8f3cb9e26..7ea3450fb 100644 --- a/CHANGES +++ b/CHANGES @@ -289,6 +289,7 @@ Version 4.0.1 (21 Aug 2019) 2019-05-22: ferdynator [PHP] #1528 Don't add a closing '?>' PHP tag to generated files. PSR-2 says it MUST be omitted for files containing only PHP. + Version 4.0.0 (27 Apr 2019) =========================== From ea514c39615f616ced604ecbef4b8f42aee8148e Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 19 Oct 2022 07:35:53 +1300 Subject: [PATCH 111/217] [js] Add mod_runme.js See #2126 --- Examples/test-suite/javascript/mod_runme.js | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Examples/test-suite/javascript/mod_runme.js diff --git a/Examples/test-suite/javascript/mod_runme.js b/Examples/test-suite/javascript/mod_runme.js new file mode 100644 index 000000000..e317b061d --- /dev/null +++ b/Examples/test-suite/javascript/mod_runme.js @@ -0,0 +1,6 @@ +var mod_a = require("mod_a"); +var mod_b = require("mod_b"); + +c = mod_b.C(); +d = mod_b.D(); +d.DoSomething(c); From 867e49d7c50aded9afdd36223f05b84645636f15 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 19 Oct 2022 07:42:11 +1300 Subject: [PATCH 112/217] [Ocaml] Add mod_runme.ml See #2126 --- Examples/test-suite/ocaml/mod_runme.ml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Examples/test-suite/ocaml/mod_runme.ml diff --git a/Examples/test-suite/ocaml/mod_runme.ml b/Examples/test-suite/ocaml/mod_runme.ml new file mode 100644 index 000000000..8adb50b6f --- /dev/null +++ b/Examples/test-suite/ocaml/mod_runme.ml @@ -0,0 +1,7 @@ +open Swig +open Mod_a +open Mod_b + +let c = new_C '() +let d = new_D '() +let _ = d -> "DoSomething" (c) From a5bc48afeac0b33631b7aeb544e6a23d99b54bf8 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 19 Oct 2022 07:29:06 +1300 Subject: [PATCH 113/217] [Lua] Fix type resolution between SWIG-wrapped modules See #2126 --- CHANGES.current | 4 ++++ Examples/test-suite/lua/mod_runme.lua | 12 ++++++++++++ Lib/lua/luarun.swg | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 Examples/test-suite/lua/mod_runme.lua diff --git a/CHANGES.current b/CHANGES.current index 0a23158a2..ffebbac46 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-19: olly + [Lua] #2126 Fix type resolution between multiple SWIG-wrapped + modules. + 2022-10-17: wsfulton [R] #2385 Add support for std::vector>. diff --git a/Examples/test-suite/lua/mod_runme.lua b/Examples/test-suite/lua/mod_runme.lua new file mode 100644 index 000000000..444a61b20 --- /dev/null +++ b/Examples/test-suite/lua/mod_runme.lua @@ -0,0 +1,12 @@ +require("import") -- the import fn +import("mod_a") -- import lib +import("mod_b") -- import lib + +-- catch "undefined" global variables +local env = _ENV -- Lua 5.2 +if not env then env = getfenv () end -- Lua 5.1 +setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end}) + +c = mod_b.C() +d = mod_b.D() +d:DoSomething(c) diff --git a/Lib/lua/luarun.swg b/Lib/lua/luarun.swg index 909a5229c..f47fd4fac 100644 --- a/Lib/lua/luarun.swg +++ b/Lib/lua/luarun.swg @@ -1789,7 +1789,7 @@ SWIGRUNTIME int SWIG_Lua_ConvertPtr(lua_State *L,int index,void **ptr,swig_type } else { - cast=SWIG_TypeCheckStruct(usr->type,type); /* performs normal type checking */ + cast=SWIG_TypeCheck(usr->type->name,type); /* performs normal type checking */ if (cast) { int newmemory = 0; From f40658c2d04feeb3803cf0f3d34d915163b39b10 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 19 Oct 2022 16:52:02 +1300 Subject: [PATCH 114/217] [python] Avoid undefined behaviour Cast a parameter type explicitly rather than implicitly by casting the function pointer type, as the latter is undefined behaviour. Caught by ubsan. --- Lib/python/pyrun.swg | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 9b6dd28ee..6b119be1c 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -240,7 +240,7 @@ typedef struct swig_varlinkobject { } swig_varlinkobject; SWIGINTERN PyObject * -swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { +swig_varlink_repr(PyObject *SWIGUNUSEDPARM(v)) { #if PY_VERSION_HEX >= 0x03000000 return PyUnicode_InternFromString(""); #else @@ -249,7 +249,8 @@ swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { } SWIGINTERN PyObject * -swig_varlink_str(swig_varlinkobject *v) { +swig_varlink_str(PyObject *o) { + swig_varlinkobject *v = (swig_varlinkobject *) o; #if PY_VERSION_HEX >= 0x03000000 PyObject *str = PyUnicode_InternFromString("("); PyObject *tail; @@ -287,7 +288,8 @@ swig_varlink_str(swig_varlinkobject *v) { } SWIGINTERN void -swig_varlink_dealloc(swig_varlinkobject *v) { +swig_varlink_dealloc(PyObject *o) { + swig_varlinkobject *v = (swig_varlinkobject *) o; swig_globalvar *var = v->vars; while (var) { swig_globalvar *n = var->next; @@ -298,7 +300,8 @@ swig_varlink_dealloc(swig_varlinkobject *v) { } SWIGINTERN PyObject * -swig_varlink_getattr(swig_varlinkobject *v, char *n) { +swig_varlink_getattr(PyObject *o, char *n) { + swig_varlinkobject *v = (swig_varlinkobject *) o; PyObject *res = NULL; swig_globalvar *var = v->vars; while (var) { @@ -315,7 +318,8 @@ swig_varlink_getattr(swig_varlinkobject *v, char *n) { } SWIGINTERN int -swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { +swig_varlink_setattr(PyObject *o, char *n, PyObject *p) { + swig_varlinkobject *v = (swig_varlinkobject *) o; int res = 1; swig_globalvar *var = v->vars; while (var) { From cfd2557cdaf6205219036585d9cacfbbe0ccead0 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 20 Oct 2022 11:42:27 +1300 Subject: [PATCH 115/217] Revert "[js] Add mod_runme.js" This reverts commit ea514c39615f616ced604ecbef4b8f42aee8148e. The new runme.js isn't used for node because it fails to run multicpptest testcases, but was failing for jsc in CI. The first problem is the new file is missing `new` where the two objects are created, but fixing that reveals that this testcase is currently broken for Javascript so just revert for now. --- Examples/test-suite/javascript/mod_runme.js | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 Examples/test-suite/javascript/mod_runme.js diff --git a/Examples/test-suite/javascript/mod_runme.js b/Examples/test-suite/javascript/mod_runme.js deleted file mode 100644 index e317b061d..000000000 --- a/Examples/test-suite/javascript/mod_runme.js +++ /dev/null @@ -1,6 +0,0 @@ -var mod_a = require("mod_a"); -var mod_b = require("mod_b"); - -c = mod_b.C(); -d = mod_b.D(); -d.DoSomething(c); From 0d523d337d3dc64ea3c64e0c8b5025ae4cc16fab Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Fri, 21 Oct 2022 09:02:31 +0200 Subject: [PATCH 116/217] Fix -Wunused-variable warning --- Source/Modules/interface.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Modules/interface.cxx b/Source/Modules/interface.cxx index 5a9242399..83a5e5f8a 100644 --- a/Source/Modules/interface.cxx +++ b/Source/Modules/interface.cxx @@ -183,6 +183,7 @@ void Swig_interface_propagate_methods(Node *n) { if (Strcmp(symname, "$ignore") != 0) { Symtab *oldscope = Swig_symbol_setscope(Getattr(n, "symtab")); Node *on = Swig_symbol_add(symname, cn); + (void)on; assert(on == cn); // Features from the copied base class method are already present, now add in features specific to the added method in the derived class From 2f3fb6a52f59feb7b895c9ad22df781a50873dbf Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Fri, 21 Oct 2022 09:00:15 +0200 Subject: [PATCH 117/217] CMake: Avoid including parser.c twice Closes #2409 --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a8862f63..7303f4cff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,6 +127,7 @@ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/swigwarn.swg DESTINATION ${SWIG_LIB}) # --------- file (GLOB DOH_SOURCES ${SWIG_SOURCE_DIR}/DOH/*.c) file (GLOB CPARSE_SOURCES ${SWIG_SOURCE_DIR}/CParse/*.c) +list (REMOVE_ITEM CPARSE_SOURCES ${SWIG_SOURCE_DIR}/CParse/parser.c) list (APPEND CPARSE_SOURCES) file (GLOB PREPROCESSOR_SOURCES ${SWIG_SOURCE_DIR}/Preprocessor/*.c) file (GLOB CORE_SOURCES ${SWIG_SOURCE_DIR}/Swig/*.c) From 1d73341aa424ebcf39caab86defff5ea8f0ee5ac Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 24 Oct 2022 08:41:42 +0100 Subject: [PATCH 118/217] Polymorphism in R wrappers fixed for C++ structs --- CHANGES.current | 4 +++ .../test-suite/go/typedef_inherit_runme.go | 5 ++++ .../javascript/typedef_inherit_runme.js | 4 +++ .../test-suite/ocaml/typedef_inherit_runme.ml | 3 +- .../test-suite/octave/typedef_inherit_runme.m | 5 ++++ .../python/typedef_inherit_runme.py | 4 +++ Examples/test-suite/r/typedef_inherit_runme.R | 29 +++++++++++++++++++ .../test-suite/ruby/typedef_inherit_runme.rb | 6 ++++ Examples/test-suite/typedef_inherit.i | 10 +++++-- Source/Modules/r.cxx | 6 ++-- 10 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 Examples/test-suite/r/typedef_inherit_runme.R diff --git a/CHANGES.current b/CHANGES.current index ffebbac46..e5971db72 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-24: wsfulton + [R] Polymorphism in the wrappers was only working for C++ classes, + now this works for C++ structs too. + 2022-10-19: olly [Lua] #2126 Fix type resolution between multiple SWIG-wrapped modules. diff --git a/Examples/test-suite/go/typedef_inherit_runme.go b/Examples/test-suite/go/typedef_inherit_runme.go index f2dbb3263..eef3ef47a 100644 --- a/Examples/test-suite/go/typedef_inherit_runme.go +++ b/Examples/test-suite/go/typedef_inherit_runme.go @@ -28,4 +28,9 @@ func main() { if x != "Grok::blah" { panic(x) } + + x = d.Far() + if x != "Spam::far" { + panic(x) + } } diff --git a/Examples/test-suite/javascript/typedef_inherit_runme.js b/Examples/test-suite/javascript/typedef_inherit_runme.js index 7590e1e6e..1ebb128da 100644 --- a/Examples/test-suite/javascript/typedef_inherit_runme.js +++ b/Examples/test-suite/javascript/typedef_inherit_runme.js @@ -21,3 +21,7 @@ if (x != "Spam::blah") x = typedef_inherit.do_blah2(d); if (x != "Grok::blah") print ("Whoa! Bad return" + x); + +x = d.far(); +if (x != "Spam::far") + print ("Whoa! Bad return" + x); diff --git a/Examples/test-suite/ocaml/typedef_inherit_runme.ml b/Examples/test-suite/ocaml/typedef_inherit_runme.ml index 6352fd4ad..a5feb7c3f 100644 --- a/Examples/test-suite/ocaml/typedef_inherit_runme.ml +++ b/Examples/test-suite/ocaml/typedef_inherit_runme.ml @@ -7,5 +7,6 @@ let _ = assert (_do_blah (b) as string = "Bar::blah"); let c = new_Spam '() and d = new_Grok '() in assert (_do_blah2 (c) as string = "Spam::blah"); - assert (_do_blah2 (d) as string = "Grok::blah") + assert (_do_blah2 (d) as string = "Grok::blah"); + assert (d -> far() as string = "Spam::far") ;; diff --git a/Examples/test-suite/octave/typedef_inherit_runme.m b/Examples/test-suite/octave/typedef_inherit_runme.m index fbe5436d1..b562e3125 100644 --- a/Examples/test-suite/octave/typedef_inherit_runme.m +++ b/Examples/test-suite/octave/typedef_inherit_runme.m @@ -30,3 +30,8 @@ x = typedef_inherit.do_blah2(d); if (!strcmp(x,"Grok::blah")) error("Whoa! Bad return", x) endif + +x = d.far(); +if (!strcmp(x,"Spam::far")) + error("Whoa! Bad return", x) +endif diff --git a/Examples/test-suite/python/typedef_inherit_runme.py b/Examples/test-suite/python/typedef_inherit_runme.py index 3c552ec65..020e4cc5e 100644 --- a/Examples/test-suite/python/typedef_inherit_runme.py +++ b/Examples/test-suite/python/typedef_inherit_runme.py @@ -21,3 +21,7 @@ if x != "Spam::blah": x = typedef_inherit.do_blah2(d) if x != "Grok::blah": raise RuntimeError("Whoa! Bad return {}".format(x)) + +x = d.far() +if x != "Spam::far": + raise RuntimeError("Whoa! Bad return {}".format(x)) diff --git a/Examples/test-suite/r/typedef_inherit_runme.R b/Examples/test-suite/r/typedef_inherit_runme.R new file mode 100644 index 000000000..3589f93b9 --- /dev/null +++ b/Examples/test-suite/r/typedef_inherit_runme.R @@ -0,0 +1,29 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + +dyn.load(paste("typedef_inherit", .Platform$dynlib.ext, sep="")) +source("typedef_inherit.R") +cacheMetaData(1) + + +a <- Foo() +b <- Bar() + +x <- do_blah(a) +unittest(x, "Foo::blah") + +x <- do_blah(b) +unittest(x, "Bar::blah") + +c <- Spam() +d <- Grok() + +x <- do_blah2(c) +unittest(x, "Spam::blah") + +x <- do_blah2(d) +unittest(x, "Grok::blah") + +unittest(d$far(), "Spam::far") + +q(save="no") diff --git a/Examples/test-suite/ruby/typedef_inherit_runme.rb b/Examples/test-suite/ruby/typedef_inherit_runme.rb index 029b80c70..10f155b3b 100644 --- a/Examples/test-suite/ruby/typedef_inherit_runme.rb +++ b/Examples/test-suite/ruby/typedef_inherit_runme.rb @@ -36,3 +36,9 @@ x = Typedef_inherit.do_blah2(d) if x != "Grok::blah" puts "Whoa! Bad return #{x}" end + +x = d.far +if x != "Spam::far" + puts "Whoa! Bad return #{x}" +end + diff --git a/Examples/test-suite/typedef_inherit.i b/Examples/test-suite/typedef_inherit.i index 48821a146..54968b81b 100644 --- a/Examples/test-suite/typedef_inherit.i +++ b/Examples/test-suite/typedef_inherit.i @@ -30,9 +30,13 @@ typedef struct spam { { } - virtual char *blah() { - return (char *) "Spam::blah"; - } + virtual char *blah() { + return (char *) "Spam::blah"; + } + + const char *far() { + return "Spam::far"; + } } Spam; struct Grok : public Spam { diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 526d959f4..2256610d5 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -215,8 +215,7 @@ public: int typedefHandler(Node *n); - static List *Swig_overload_rank(Node *n, - bool script_lang_wrapping); + static List *Swig_overload_rank(Node *n, bool script_lang_wrapping); int memberfunctionHandler(Node *n) { if (debugMode) @@ -2295,7 +2294,6 @@ int R::outputRegistrationRoutines(File *out) { void R::registerClass(Node *n) { String *name = Getattr(n, "name"); - String *kind = Getattr(n, "kind"); if (debugMode) Swig_print_node(n); @@ -2304,7 +2302,7 @@ void R::registerClass(Node *n) { Setattr(SClassDefs, sname, sname); String *base; - if(Strcmp(kind, "class") == 0) { + if (CPlusPlus && (Strcmp(nodeType(n), "class") == 0)) { base = NewString(""); List *l = Getattr(n, "bases"); if(Len(l)) { From 6370fab025605ccf09e2d14e220a2cb02476427d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 24 Oct 2022 16:21:29 +0100 Subject: [PATCH 119/217] R - fix $typemap() for R specific typemaps Add support for special variable replacement in the $typemap() special variable macro for R specific typemaps (rtype, rtypecheck, scoercein, scoereout). --- CHANGES.current | 5 +++++ Source/Modules/r.cxx | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index e5971db72..2ad66dd59 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-24: wsfulton + [R] Add support for special variable replacement in the $typemap() + special variable macro for R specific typemaps (rtype, rtypecheck, + scoercein, scoereout). + 2022-10-24: wsfulton [R] Polymorphism in the wrappers was only working for C++ classes, now this works for C++ structs too. diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 2256610d5..c51198fed 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -242,8 +242,8 @@ public: return status; } - // Not used: String *runtimeCode(); + void replaceSpecialVariables(String *method, String *tm, Parm *parm); protected: int addRegistrationRoutine(String *rname, int nargs); @@ -2666,6 +2666,16 @@ String * R::runtimeCode() { return s; } +/*---------------------------------------------------------------------- + * replaceSpecialVariables() + *--------------------------------------------------------------------*/ + +void R::replaceSpecialVariables(String *method, String *tm, Parm *parm) { + (void)method; + SwigType *type = Getattr(parm, "type"); + replaceRClass(tm, type); +} + /* ----------------------------------------------------------------------- * Called when SWIG wants to initialize this From a71bb2bc6e9fb09de47d6ba88a02fc54d1ef3e65 Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Sat, 1 Oct 2022 19:18:08 +0200 Subject: [PATCH 120/217] fix naming of RClass when template of a shared_ptr --- Source/Modules/r.cxx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index c51198fed..581a9bee1 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -2092,9 +2092,21 @@ int R::functionWrapper(Node *n) { Node * parent = Getattr(n, "parentNode"); String * smartname = Getattr(parent, "feature:smartptr"); if (smartname) { - smartname = getRClassName(smartname, 1, 1); - Replaceall(tm, "$R_class", smartname); - Delete(smartname); + String * classtypeobj = NewString(Getattr(parent, "classtypeobj")); // this is the correct name, e.g. ClassName(int) + String * classtype = NewString(Getattr(parent, "classtype")); // this is the "wrong" name e.g. ClassName + + // we replace inside smartname ClassName with ClassName + String * smartname_fixed = NewString(smartname); + Replaceall(classtype, " ", ""); // classtype actually has spaces inside so we remove them + Replaceall(smartname_fixed, classtype, classtypeobj); + + String * smartname_fixed_rclass = getRClassName(smartname_fixed, 1, 1); + Replaceall(tm, "$R_class", smartname_fixed_rclass); + + Delete(classtypeobj); + Delete(classtype); + Delete(smartname_fixed); + Delete(smartname_fixed_rclass); } } if (debugMode) { From b15e058a27a3eda6d65585d930852421bdbeff21 Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Sun, 2 Oct 2022 19:44:49 +0200 Subject: [PATCH 121/217] typo in comment --- Source/Modules/r.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 581a9bee1..3ea48ea7b 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -2095,7 +2095,7 @@ int R::functionWrapper(Node *n) { String * classtypeobj = NewString(Getattr(parent, "classtypeobj")); // this is the correct name, e.g. ClassName(int) String * classtype = NewString(Getattr(parent, "classtype")); // this is the "wrong" name e.g. ClassName - // we replace inside smartname ClassName with ClassName + // we replace inside smartname ClassName with ClassName(int) String * smartname_fixed = NewString(smartname); Replaceall(classtype, " ", ""); // classtype actually has spaces inside so we remove them Replaceall(smartname_fixed, classtype, classtypeobj); From ba96783d1164011d7c7d88380236747273333cb9 Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Fri, 7 Oct 2022 14:18:35 +0200 Subject: [PATCH 122/217] enable li_boost_shared_ptr in r-test-suite --- Examples/test-suite/li_boost_shared_ptr.i | 3 +- Examples/test-suite/r/Makefile.in | 3 +- .../test-suite/r/li_boost_shared_ptr_runme.R | 676 ++++++++++++++++++ Examples/test-suite/r/unittest.R | 1 + 4 files changed, 681 insertions(+), 2 deletions(-) create mode 100644 Examples/test-suite/r/li_boost_shared_ptr_runme.R diff --git a/Examples/test-suite/li_boost_shared_ptr.i b/Examples/test-suite/li_boost_shared_ptr.i index 001eacb78..48d5fc2f1 100644 --- a/Examples/test-suite/li_boost_shared_ptr.i +++ b/Examples/test-suite/li_boost_shared_ptr.i @@ -44,7 +44,7 @@ # define SWIG_SHARED_PTR_NAMESPACE SwigBoost #endif -#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGD) || defined(SWIGOCTAVE) || defined(SWIGRUBY) +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGD) || defined(SWIGOCTAVE) || defined(SWIGRUBY) || defined(SWIGR) #define SHARED_PTR_WRAPPERS_IMPLEMENTED #endif @@ -268,6 +268,7 @@ long use_count(const SwigBoost::shared_ptr& sptr) { long use_count(const SwigBoost::shared_ptr& sptr) { return sptr.use_count(); } + const SwigBoost::shared_ptr& ref_1() { static SwigBoost::shared_ptr sptr; return sptr; diff --git a/Examples/test-suite/r/Makefile.in b/Examples/test-suite/r/Makefile.in index 78cc4bb53..9d3e9e706 100644 --- a/Examples/test-suite/r/Makefile.in +++ b/Examples/test-suite/r/Makefile.in @@ -25,7 +25,8 @@ CPP_TEST_CASES += \ r_overload_array \ r_sexp \ r_overload_comma \ - r_use_isnull + r_use_isnull \ + li_boost_shared_ptr # These tests are failing because enums currently cannot handle # arithmetic expressions diff --git a/Examples/test-suite/r/li_boost_shared_ptr_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_runme.R new file mode 100644 index 000000000..cdee3b9ad --- /dev/null +++ b/Examples/test-suite/r/li_boost_shared_ptr_runme.R @@ -0,0 +1,676 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) +#source("unittest.R") + +dyn.load(paste("li_boost_shared_ptr", .Platform$dynlib.ext, sep="")) +source("li_boost_shared_ptr.R") +cacheMetaData(1) + +# simple shared_ptr usage - created in C++ + +invisible(debug_shared(TRUE)) +unittest(debug_shared(), TRUE) + + +# Expect 1 instance - the one global variable (GlobalValue) +unittest(Klass_getTotal_count(), 1) + +# Change loop count to run for a long time to monitor memory +unittest(shared_ptr_wrapper_count(), NOT_COUNTING()) + + +# +# test suite to be run in a loop +# + +testSuite_verifyCount <- function(expected, k) { + got = use_count(k) + unittest(expected, got); +} + +testSuite <- function() { + + # simple shared_ptr usage - created in C++ + { + k = Klass("me oh my") + val = k$getValue() + unittest("me oh my", val) + testSuite_verifyCount(1, k) + } + + # simple shared_ptr usage - not created in C++ + { + k = factorycreate() + val = k$getValue() + unittest("factorycreate", val) + testSuite_verifyCount(1, k) + } + + # pass by shared_ptr + { + k = Klass("me oh my") + kret = smartpointertest(k) + val = kret$getValue() + unittest("me oh my smartpointertest", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } + + # pass by shared_ptr pointer + { + k = Klass("me oh my") + kret = smartpointerpointertest(k) + val = kret$getValue() + unittest("me oh my smartpointerpointertest", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } + + # pass by shared_ptr reference + { + k = Klass("me oh my") + kret = smartpointerreftest(k) + val = kret$getValue() + unittest("me oh my smartpointerreftest", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } + + if (FALSE) { + # pass by shared_ptr pointer reference + k = Klass("me oh my") + kret = smartpointerpointerreftest(k) # undefined class _p_p_SwigBoost__shared_ptrT_Space__Klass_t + val = kret$getValue() + unittest("me oh my smartpointerpointerreftest", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } + + if (FALSE) { + # pass by shared_ptr pointer reference + k = Klass("me oh my"); + kret = smartpointerpointerreftest(k); # undefined class _p_p_SwigBoost__shared_ptrT_Space__Klass_t + val = kret$getValue() + unittest("me oh my smartpointerpointerreftest", val); + testSuite_verifyCount(2, k); + testSuite_verifyCount(2, kret); + } + + # const pass by shared_ptr + { + k = Klass("me oh my"); + kret = constsmartpointertest(k); + val = Klass_getValue(kret) # kret$getValue(); - method not defined + unittest("me oh my", val); + testSuite_verifyCount(2, k); + # testSuite_verifyCount(2, kret); # -> use_count not defined on _p_SwigBoost__shared_ptrT_Space__Klass_const_t + } + + # pass by value + { + k = Klass("me oh my"); + kret = valuetest(k); + val = kret$getValue(); + unittest("me oh my valuetest", val); + testSuite_verifyCount(1, k); + # testSuite_verifyCount(1, kret); # -> use_count not defined on _p_Space__Klass + } + + # pass by pointer + { + k = Klass("me oh my"); + kret = pointertest(k); + val = kret$getValue(); + unittest("me oh my pointertest", val); + testSuite_verifyCount(1, k); + # testSuite_verifyCount(1, kret); # -> use_count not defined on _p_Space__Klass + } + + # pass by reference + { + k = Klass("me oh my"); + kret = reftest(k); + val = kret$getValue(); + unittest("me oh my reftest", val); + testSuite_verifyCount(1, k); + #testSuite_verifyCount(1, kret); # -> use_count not defined on _p_Space__Klass + } + + # pass by pointer reference + if (FALSE) { + k = Klass("me oh my"); + kret = pointerreftest(k); # -> class not defined _p_p_Space__Klass + val = kret$getValue(); + unittest("me oh my pointerreftest", val); + testSuite_verifyCount(1, k); + testSuite_verifyCount(1, kret); + } + + # null tests + { + k = NULL + + if (!is.null(smartpointertest(k))) { + stop("return was not null"); + } + + if (!is.null(smartpointerpointertest(k))) { + stop("return was not null"); + } + + if (!is.null(smartpointerreftest(k))) { + stop("return was not null"); + } + + if (!is.null(smartpointerpointerreftest(k))) { + stop("return was not null"); + } + + if (nullsmartpointerpointertest(k) != "null pointer") { + stop("not null smartpointer pointer"); + } + + bNotCatched = F + try({ + valuetest(k); + bNotCatched = T + }, silent = T) + if (bNotCatched) { + stop("Failed to catch null pointer"); + } + + if (!is.null(pointertest(k))) { + stop("return was not null"); + } + + bNotCatched = F + try({ + reftest(k); + bNotCatched = T + }, silent = T) + if (bNotCatched) { + stop("Failed to catch null pointer"); + } + } + + # $owner + { + k = pointerownertest(); + val = k$getValue(); + unittest("pointerownertest", val); + # testSuite_verifyCount(1, k); # -> use_count not defined for _p_Space__Klass + } + + { + k = smartpointerpointerownertest(); + val = k$getValue(); + unittest("smartpointerpointerownertest", val); + testSuite_verifyCount(1, k); + } + + # + # ###################### Derived classes ###################### + # + + # derived pass by shared_ptr + { + k = KlassDerived("me oh my"); + kret = derivedsmartptrtest(k); + val = kret$getValue(); + unittest("me oh my derivedsmartptrtest-Derived", val); + testSuite_verifyCount(2, k); + testSuite_verifyCount(2, kret); + # testSuite_verifyCount(4, k); # includes two extra references for upcasts + # testSuite_verifyCount(4, kret); + } + + # derived pass by shared_ptr pointer + { + k = KlassDerived("me oh my"); + kret = derivedsmartptrpointertest(k); + val = kret$getValue(); + unittest("me oh my derivedsmartptrpointertest-Derived", val); + testSuite_verifyCount(2, k); + testSuite_verifyCount(2, kret); + # testSuite_verifyCount(4, k); # includes two extra references for upcasts in the proxy classes + # testSuite_verifyCount(4, kret); + } + + # derived pass by shared_ptr ref + { + k = KlassDerived("me oh my"); + kret = derivedsmartptrreftest(k); + val = kret$getValue(); + unittest("me oh my derivedsmartptrreftest-Derived", val); + testSuite_verifyCount(2, k); + testSuite_verifyCount(2, kret); + #testSuite_verifyCount(4, k); # includes two extra references for upcasts in the proxy classes + #testSuite_verifyCount(4, kret); + } + + # derived pass by shared_ptr pointer ref + if (FALSE) { + k = KlassDerived("me oh my"); + kret = derivedsmartptrpointerreftest(k); # undefined class _p_p_SwigBoost__shared_ptrT_Space__KlassDerived_t + val = kret$getValue(); + unittest("me oh my derivedsmartptrpointerreftest-Derived", val); + testSuite_verifyCount(4, k); # includes two extra references for upcasts in the proxy classes + testSuite_verifyCount(4, kret); + } + + # derived pass by pointer + { + k = KlassDerived("me oh my"); + kret = derivedpointertest(k); + val = kret$getValue(); + unittest("me oh my derivedpointertest-Derived", val); + testSuite_verifyCount(1, k); + # testSuite_verifyCount(1, kret); -> use_count not defined for _p_Space__KlassDerived + + # testSuite_verifyCount(2, k); # includes an extra reference for the upcast in the proxy class + # testSuite_verifyCount(2, kret); + } + + # derived pass by ref + { + k = KlassDerived("me oh my"); + kret = derivedreftest(k); + val = kret$getValue(); + unittest("me oh my derivedreftest-Derived", val); + testSuite_verifyCount(1, k); + #testSuite_verifyCount(1, kret); --> use_count not defined for _p_Space__KlassDerived + + #testSuite_verifyCount(2, k); # includes an extra reference for the upcast in the proxy class + #testSuite_verifyCount(2, kret); + } + + + # + # ###################### Derived and base class mixed ###################### + # + + # pass by shared_ptr (mixed) + { + k = KlassDerived("me oh my"); + kret = smartpointertest(k); + val = kret$getValue(); + unittest("me oh my smartpointertest-Derived", val); + testSuite_verifyCount(3, k); # an extra reference for the upcast in the proxy class + testSuite_verifyCount(3, kret); + } + + # pass by shared_ptr pointer (mixed) + { + k = KlassDerived("me oh my"); + kret = smartpointerpointertest(k); + val = kret$getValue(); + unittest("me oh my smartpointerpointertest-Derived", val); + testSuite_verifyCount(3, k); # an extra reference for the upcast in the proxy class + testSuite_verifyCount(3, kret); + } + + # pass by shared_ptr reference (mixed) + { + k = KlassDerived("me oh my"); + kret = smartpointerreftest(k); + val = kret$getValue(); + unittest("me oh my smartpointerreftest-Derived", val); + testSuite_verifyCount(3, k); # an extra reference for the upcast in the proxy class + testSuite_verifyCount(3, kret); + } + + # pass by shared_ptr pointer reference (mixed) + if (FALSE) { + k = KlassDerived("me oh my"); + kret = smartpointerpointerreftest(k); # -> undefined _p_p_SwigBoost__shared_ptrT_Space__Klass_t + val = kret$getValue(); + unittest("me oh my smartpointerpointerreftest-Derived", val); + testSuite_verifyCount(3, k); # an extra reference for the upcast in the proxy class + testSuite_verifyCount(3, kret); + } + + # pass by value (mixed) + { + k = KlassDerived("me oh my"); + kret = valuetest(k); + val = kret$getValue(); + unittest("me oh my valuetest", val); # note slicing + testSuite_verifyCount(2, k); # an extra reference for the upcast in the proxy class + # testSuite_verifyCount(1, kret); # -> use count undefined for _p_Space__Klass + } + + # pass by pointer (mixed) + { + k = KlassDerived("me oh my"); + kret = pointertest(k); + val = kret$getValue(); + unittest("me oh my pointertest-Derived", val); + testSuite_verifyCount(2, k); # an extra reference for the upcast in the proxy class + # testSuite_verifyCount(1, kret); # -> use count undefined for _p_Space__Klass + } + + # pass by ref (mixed) + { + k = KlassDerived("me oh my"); + kret = reftest(k); + val = kret$getValue(); + unittest("me oh my reftest-Derived", val); + testSuite_verifyCount(2, k); # an extra reference for the upcast in the proxy class + # testSuite_verifyCount(1, kret); # -> use count undefined for _p_Space__Klass + } + + # 3rd derived class + { + k = Klass3rdDerived("me oh my"); + val = k$getValue(); + unittest("me oh my-3rdDerived", val); + testSuite_verifyCount(1, k); + #testSuite_verifyCount(3, k); # 3 classes in inheritance chain == 3 swigCPtr values + + val = test3rdupcast(k); + unittest("me oh my-3rdDerived", val); + testSuite_verifyCount(2, k); + #testSuite_verifyCount(3, k); + } + + + # + # ################ Member variables #################### + # + + # smart pointer by value + { + m = MemberVariables(); + k = Klass("smart member value"); + MemberVariables_SmartMemberValue_set(self = m, s_SmartMemberValue = k) + + val = k$getValue(); + unittest("smart member value", val); + testSuite_verifyCount(2, k); + + kmember = MemberVariables_SmartMemberPointer_get(self = m) + val = kmember$getValue(); + unittest("smart member value", val); + testSuite_verifyCount(3, kmember); + testSuite_verifyCount(3, k); + + delete_MemberVariables(m) + testSuite_verifyCount(2, kmember); # these should be -1 wrt to the previous test ? + testSuite_verifyCount(2, k); + } + + # smart pointer by pointer + { + m = MemberVariables(); + k = Klass("smart member pointer"); + MemberVariables_SmartMemberPointer_set(self = m , s_SmartMemberPointer = k); + val = k$getValue(); + unittest("smart member pointer", val); + testSuite_verifyCount(1, k); + + kmember = MemberVariables_SmartMemberPointer_get(self = m) + val = kmember$getValue(); + unittest("smart member pointer", val); + testSuite_verifyCount(2, kmember); + testSuite_verifyCount(2, k); + + delete_MemberVariables(m); + testSuite_verifyCount(2, kmember); + testSuite_verifyCount(2, k); + } + + # smart pointer by reference + { + m = MemberVariables(); + k = Klass("smart member reference"); + MemberVariables_SmartMemberReference_set(self = m , s_SmartMemberReference = k); # m$setSmartMemberReference(k); + val = k$getValue(); + unittest("smart member reference", val); + testSuite_verifyCount(2, k); + + kmember = MemberVariables_SmartMemberPointer_get(self = m) + val = kmember$getValue(); + unittest("smart member reference", val); + testSuite_verifyCount(3, kmember); + testSuite_verifyCount(3, k); + + # The C++ reference refers to SmartMemberValue... + kmemberVal = MemberVariables_SmartMemberReference_get(self = m) + val = kmember$getValue(); + unittest("smart member reference", val); + testSuite_verifyCount(4, kmemberVal); + testSuite_verifyCount(4, kmember); + testSuite_verifyCount(4, k); + + delete_MemberVariables(m); + testSuite_verifyCount(3, kmemberVal); # should be one less than the previous one + testSuite_verifyCount(3, kmember); + testSuite_verifyCount(3, k); + } + + # plain by value + { + m = MemberVariables(); + k = Klass("plain member value"); + MemberVariables_MemberValue_set(self = m, s_MemberValue = k); # m$setMemberValue(k); + val = k$getValue(); + unittest("plain member value", val); + testSuite_verifyCount(1, k); + + kmember = MemberVariables_MemberValue_get(m); # m$getMemberValue(); + val = kmember$getValue(); + unittest("plain member value", val); + # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, k); + + delete_MemberVariables(m); # m.delete(); + # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, k); + } + + # plain by pointer + { + m = MemberVariables(); + k = Klass("plain member pointer"); + MemberVariables_MemberPointer_set(self = m, s_MemberPointer = k); # m$setMemberPointer(k); + val = k$getValue(); + unittest("plain member pointer", val); + testSuite_verifyCount(1, k); + + kmember = MemberVariables_MemberPointer_get(self = m); # m$getMemberPointer(); + val = kmember$getValue(); + unittest("plain member pointer", val); + # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, k); + + delete_MemberVariables(m); # m.delete(); + # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, k); + } + + # plain by reference + { + m = MemberVariables(); + k = Klass("plain member reference"); + MemberVariables_MemberReference_set(self = m, s_MemberReference = k); # m$setMemberReference(k); + val = k$getValue(); + unittest("plain member reference", val); + testSuite_verifyCount(1, k); + + kmember = MemberVariables_MemberReference_get(self = m); #m$getMemberReference(); + val = kmember$getValue(); + unittest("plain member reference", val); + # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, k); + + delete_MemberVariables(m); # m.delete(); + # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, k); + } + + # null member variables + { + m = MemberVariables(); + + # shared_ptr by value + k = MemberVariables_SmartMemberValue_get(self = m); # k = m$getSmartMemberValue(); + if (!is.null(k)) + stop("expected null"); + + MemberVariables_SmartMemberValue_set(self = m, s_SmartMemberValue = NULL); #m$setSmartMemberValue(null); + k = MemberVariables_SmartMemberValue_get(self = m); #m$getSmartMemberValue(); + if (!is.null(k)) + stop("expected null"); + #testSuite_verifyCount(0, k); + + # plain by value + bNotCatched = F + try({ + MemberVariables_MemberValue_set(self = m, s_MemberValue = NULL) + bNotCatched = T + }, silent = T) + if (bNotCatched) { + stop("Failed to catch null pointer") + } + + } + + + # + # ################ Global variables #################### + # + + # smart pointer + { + kglobal = GlobalSmartValue_get(); + if (!is.null(kglobal)) + stop("expected null"); + + k = Klass("smart global value"); + GlobalSmartValue_set(k); + testSuite_verifyCount(2, k); + + kglobal = GlobalSmartValue_get(); + val = kglobal$getValue(); + unittest("smart global value", val); + testSuite_verifyCount(3, kglobal); + testSuite_verifyCount(3, k); + unittest("smart global value", GlobalSmartValue_get()$getValue()); + + GlobalSmartValue_set(NULL); + } + + # plain value + { + k = Klass("global value"); + GlobalValue_set(k); + testSuite_verifyCount(1, k); + + kglobal = GlobalValue_get(); + val = kglobal$getValue(); + unittest("global value", val); + # testSuite_verifyCount(1, kglobal); # -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, k); + unittest("global value", GlobalValue_get()$getValue()); + + bNotCatched = F + try({ + GlobalValue_set(NULL) + bNotCatched = T + }, silent = T) + if (bNotCatched) { + stop("Failed to catch null pointer") + } + } + + # plain pointer + { + kglobal = GlobalPointer_get(); + if (!is.null(kglobal)) + stop("expected null"); + + k = Klass("global pointer"); + GlobalPointer_set(k); + testSuite_verifyCount(1, k); + + kglobal = GlobalPointer_get(); + val = kglobal$getValue(); + unittest("global pointer", val); + # testSuite_verifyCount(1, kglobal); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, k); + GlobalPointer_set(NULL); + } + + # plain reference + { + k = Klass("global reference"); + GlobalReference_set(k); + testSuite_verifyCount(1, k); + + kglobal = GlobalReference_get(); + val = kglobal$getValue(); + unittest("global reference", val); + # testSuite_verifyCount(1, kglobal); # -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, k); + + bNotCatched = F + try({ + GlobalReference_set(NULL) + bNotCatched = T + }, silent = T) + if (bNotCatched) { + stop("Failed to catch null pointer") + } + } + + + + + + + # + # ###################### Templates ###################### + # + { + pid = PairIntDouble(10, 20.2); + if (BaseIntDouble_baseVal1_get(pid) != 20 || BaseIntDouble_baseVal2_get(pid) != 40.4) + stop("Base values wrong"); + if (PairIntDouble_val1_get(pid) != 10 || PairIntDouble_val2_get(pid) != 20.2) + stop("Derived Values wrong"); + } + +} + + +# actually do the tests +for (i in 1:10) { + print(paste("Start Loop: ", i)) + testSuite() + print(paste("End Loop: ", i)) +} + + +# wait for the GC to collect unused objects + +for (i in 1:10) { + invisible(gc(verbose = F, full = T)) + + if (Klass_getTotal_count() == 1) { + break + } + + print(paste("Still waiting for GC to collect ", Klass_getTotal_count()-1, " objects, ", i)) + Sys.sleep(1) +} + +# Expect +unittest(shared_ptr_wrapper_count(), NOT_COUNTING()) + +# Expect 1 instance - the one global variable (GlobalValue) +# -> documented bug - gc does not work on some objects - https://www.swig.org/Doc4.0/SWIGDocumentation.html#R_nn2 +if (FALSE) { + unittest(Klass_getTotal_count(), 1) +} + + +q(save="no") diff --git a/Examples/test-suite/r/unittest.R b/Examples/test-suite/r/unittest.R index 481be8ecc..7f56a579f 100644 --- a/Examples/test-suite/r/unittest.R +++ b/Examples/test-suite/r/unittest.R @@ -3,6 +3,7 @@ unittest <- function (x,y) { print("PASS") } else { print("FAIL") + print(paste(x, " != ", y)) stop("Test failed") } } From b885c22f1110b4d41d296ef593c4233f54d955ca Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Sat, 8 Oct 2022 16:19:02 +0200 Subject: [PATCH 123/217] fixes from code review --- Examples/test-suite/r/Makefile.in | 3 +-- Source/Modules/r.cxx | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/r/Makefile.in b/Examples/test-suite/r/Makefile.in index 9d3e9e706..78cc4bb53 100644 --- a/Examples/test-suite/r/Makefile.in +++ b/Examples/test-suite/r/Makefile.in @@ -25,8 +25,7 @@ CPP_TEST_CASES += \ r_overload_array \ r_sexp \ r_overload_comma \ - r_use_isnull \ - li_boost_shared_ptr + r_use_isnull # These tests are failing because enums currently cannot handle # arithmetic expressions diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 3ea48ea7b..18a9aa56d 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -2092,7 +2092,7 @@ int R::functionWrapper(Node *n) { Node * parent = Getattr(n, "parentNode"); String * smartname = Getattr(parent, "feature:smartptr"); if (smartname) { - String * classtypeobj = NewString(Getattr(parent, "classtypeobj")); // this is the correct name, e.g. ClassName(int) + String * classtypeobj = Getattr(parent, "classtypeobj"); // this is the correct name, e.g. ClassName(int) String * classtype = NewString(Getattr(parent, "classtype")); // this is the "wrong" name e.g. ClassName // we replace inside smartname ClassName with ClassName(int) @@ -2103,7 +2103,6 @@ int R::functionWrapper(Node *n) { String * smartname_fixed_rclass = getRClassName(smartname_fixed, 1, 1); Replaceall(tm, "$R_class", smartname_fixed_rclass); - Delete(classtypeobj); Delete(classtype); Delete(smartname_fixed); Delete(smartname_fixed_rclass); From 0d0e369aaff8e7e3311453c533425dab704fc69a Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Tue, 11 Oct 2022 20:30:12 +0200 Subject: [PATCH 124/217] switched implementation reference from java to python --- .../test-suite/r/li_boost_shared_ptr_runme.R | 228 +++++++++--------- 1 file changed, 114 insertions(+), 114 deletions(-) diff --git a/Examples/test-suite/r/li_boost_shared_ptr_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_runme.R index cdee3b9ad..6df8984fc 100644 --- a/Examples/test-suite/r/li_boost_shared_ptr_runme.R +++ b/Examples/test-suite/r/li_boost_shared_ptr_runme.R @@ -30,6 +30,10 @@ testSuite_verifyCount <- function(expected, k) { testSuite <- function() { + # + # Reference Implementation is li_boost_shared_ptr_runme.py + # + # simple shared_ptr usage - created in C++ { k = Klass("me oh my") @@ -106,6 +110,26 @@ testSuite <- function() { # testSuite_verifyCount(2, kret); # -> use_count not defined on _p_SwigBoost__shared_ptrT_Space__Klass_const_t } + # const pass by shared_ptr pointer + { + k = Klass("me oh my") + kret = constsmartpointerpointertest(k) + val = Klass_getValue(kret) + unittest("me oh my", val) + testSuite_verifyCount(2, k) + # testSuite_verifyCount(2, kret) # -> use_count not defined on _p_SwigBoost__shared_ptrT_Space__Klass_const_t + } + + # const pass by shared_ptr reference + { + k = Klass("me oh my") + kret = constsmartpointerreftest(k) + val = Klass_getValue(kret) + unittest("me oh my", val) + testSuite_verifyCount(2, k) + # testSuite_verifyCount(2, kret) # -> use_count not defined for _p_SwigBoost__shared_ptrT_Space__Klass_const_t + } + # pass by value { k = Klass("me oh my"); @@ -191,6 +215,23 @@ testSuite <- function() { if (bNotCatched) { stop("Failed to catch null pointer"); } + + # test null pointers emitted from C++ + + k = sp_pointer_null() + if (!is.null(k)) { + stop("return was not null") + } + + k = null_sp_pointer() + if (!is.null(k)) { + stop("return was not null") + } + + k = sp_value_null() + if (!is.null(k)) { + stop("return was not null") + } } # $owner @@ -209,10 +250,10 @@ testSuite <- function() { } # - # ###################### Derived classes ###################### + # ###################### Derived and base class mixed ###################### # - # derived pass by shared_ptr + # pass by shared_ptr (mixed) { k = KlassDerived("me oh my"); kret = derivedsmartptrtest(k); @@ -220,11 +261,9 @@ testSuite <- function() { unittest("me oh my derivedsmartptrtest-Derived", val); testSuite_verifyCount(2, k); testSuite_verifyCount(2, kret); - # testSuite_verifyCount(4, k); # includes two extra references for upcasts - # testSuite_verifyCount(4, kret); } - # derived pass by shared_ptr pointer + # pass by shared_ptr pointer (mixed) { k = KlassDerived("me oh my"); kret = derivedsmartptrpointertest(k); @@ -232,11 +271,9 @@ testSuite <- function() { unittest("me oh my derivedsmartptrpointertest-Derived", val); testSuite_verifyCount(2, k); testSuite_verifyCount(2, kret); - # testSuite_verifyCount(4, k); # includes two extra references for upcasts in the proxy classes - # testSuite_verifyCount(4, kret); } - # derived pass by shared_ptr ref + # pass by shared_ptr ref (mixed) { k = KlassDerived("me oh my"); kret = derivedsmartptrreftest(k); @@ -244,21 +281,32 @@ testSuite <- function() { unittest("me oh my derivedsmartptrreftest-Derived", val); testSuite_verifyCount(2, k); testSuite_verifyCount(2, kret); - #testSuite_verifyCount(4, k); # includes two extra references for upcasts in the proxy classes - #testSuite_verifyCount(4, kret); } - # derived pass by shared_ptr pointer ref + # pass by shared_ptr pointer reference (mixed) if (FALSE) { k = KlassDerived("me oh my"); - kret = derivedsmartptrpointerreftest(k); # undefined class _p_p_SwigBoost__shared_ptrT_Space__KlassDerived_t + kret = smartpointerpointerreftest(k); # undefined class _p_p_SwigBoost__shared_ptrT_Space__Klass_t val = kret$getValue(); unittest("me oh my derivedsmartptrpointerreftest-Derived", val); - testSuite_verifyCount(4, k); # includes two extra references for upcasts in the proxy classes - testSuite_verifyCount(4, kret); + testSuite_verifyCount(2, k); # includes two extra references for upcasts in the proxy classes + testSuite_verifyCount(2, kret); } - # derived pass by pointer + # pass by value (mixed) + { + k = KlassDerived("me oh my") + kret = valuetest(k) + val = kret$getValue() + unittest("me oh my valuetest", val) # note slicing + testSuite_verifyCount(2, k) + # testSuite_verifyCount(2, kret) --> use count not defined for _p_Space__Klass + + # testSuite_verifyCount(1, k) # this is the python expected reference counting + # testSuite_verifyCount(1, kret) + } + + # pass by pointer (mixed) { k = KlassDerived("me oh my"); kret = derivedpointertest(k); @@ -266,87 +314,6 @@ testSuite <- function() { unittest("me oh my derivedpointertest-Derived", val); testSuite_verifyCount(1, k); # testSuite_verifyCount(1, kret); -> use_count not defined for _p_Space__KlassDerived - - # testSuite_verifyCount(2, k); # includes an extra reference for the upcast in the proxy class - # testSuite_verifyCount(2, kret); - } - - # derived pass by ref - { - k = KlassDerived("me oh my"); - kret = derivedreftest(k); - val = kret$getValue(); - unittest("me oh my derivedreftest-Derived", val); - testSuite_verifyCount(1, k); - #testSuite_verifyCount(1, kret); --> use_count not defined for _p_Space__KlassDerived - - #testSuite_verifyCount(2, k); # includes an extra reference for the upcast in the proxy class - #testSuite_verifyCount(2, kret); - } - - - # - # ###################### Derived and base class mixed ###################### - # - - # pass by shared_ptr (mixed) - { - k = KlassDerived("me oh my"); - kret = smartpointertest(k); - val = kret$getValue(); - unittest("me oh my smartpointertest-Derived", val); - testSuite_verifyCount(3, k); # an extra reference for the upcast in the proxy class - testSuite_verifyCount(3, kret); - } - - # pass by shared_ptr pointer (mixed) - { - k = KlassDerived("me oh my"); - kret = smartpointerpointertest(k); - val = kret$getValue(); - unittest("me oh my smartpointerpointertest-Derived", val); - testSuite_verifyCount(3, k); # an extra reference for the upcast in the proxy class - testSuite_verifyCount(3, kret); - } - - # pass by shared_ptr reference (mixed) - { - k = KlassDerived("me oh my"); - kret = smartpointerreftest(k); - val = kret$getValue(); - unittest("me oh my smartpointerreftest-Derived", val); - testSuite_verifyCount(3, k); # an extra reference for the upcast in the proxy class - testSuite_verifyCount(3, kret); - } - - # pass by shared_ptr pointer reference (mixed) - if (FALSE) { - k = KlassDerived("me oh my"); - kret = smartpointerpointerreftest(k); # -> undefined _p_p_SwigBoost__shared_ptrT_Space__Klass_t - val = kret$getValue(); - unittest("me oh my smartpointerpointerreftest-Derived", val); - testSuite_verifyCount(3, k); # an extra reference for the upcast in the proxy class - testSuite_verifyCount(3, kret); - } - - # pass by value (mixed) - { - k = KlassDerived("me oh my"); - kret = valuetest(k); - val = kret$getValue(); - unittest("me oh my valuetest", val); # note slicing - testSuite_verifyCount(2, k); # an extra reference for the upcast in the proxy class - # testSuite_verifyCount(1, kret); # -> use count undefined for _p_Space__Klass - } - - # pass by pointer (mixed) - { - k = KlassDerived("me oh my"); - kret = pointertest(k); - val = kret$getValue(); - unittest("me oh my pointertest-Derived", val); - testSuite_verifyCount(2, k); # an extra reference for the upcast in the proxy class - # testSuite_verifyCount(1, kret); # -> use count undefined for _p_Space__Klass } # pass by ref (mixed) @@ -355,25 +322,62 @@ testSuite <- function() { kret = reftest(k); val = kret$getValue(); unittest("me oh my reftest-Derived", val); - testSuite_verifyCount(2, k); # an extra reference for the upcast in the proxy class - # testSuite_verifyCount(1, kret); # -> use count undefined for _p_Space__Klass + testSuite_verifyCount(2, k); + #testSuite_verifyCount(2, kret); --> use_count not defined for _p_Space__KlassDerived + + #testSuite_verifyCount(1, k); # --> this is the python expected counting + #testSuite_verifyCount(1, kret); + } + + # + # ################# Overloading tests ################## + # + + # Base class + { + k = Klass("me oh my"); + + unittest(overload_rawbyval(k), "rawbyval") + unittest(overload_rawbyref(k), "rawbyref") + unittest(overload_rawbyptr(k), "rawbyptr") + # unittest(overload_rawbyptrref(k), "rawbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__Klass_t + + unittest(overload_smartbyval(k), "smartbyval") + unittest(overload_smartbyref(k), "smartbyref") + unittest(overload_smartbyptr(k), "smartbyptr") + # unittest(overload_smartbyptrref(k), "smartbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__Klass_t + } + + # Derived class + { + k = KlassDerived("me oh my") + + unittest(overload_rawbyval(k), "rawbyval") + unittest(overload_rawbyref(k), "rawbyref") + unittest(overload_rawbyptr(k), "rawbyptr") + # unittest(overload_rawbyptrref(k), "rawbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__KlassDerived_t + + unittest(overload_smartbyval(k), "smartbyval") + unittest(overload_smartbyref(k), "smartbyref") + unittest(overload_smartbyptr(k), "smartbyptr") + # unittest(overload_smartbyptrref(k), "smartbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__KlassDerived_t } # 3rd derived class { - k = Klass3rdDerived("me oh my"); - val = k$getValue(); - unittest("me oh my-3rdDerived", val); - testSuite_verifyCount(1, k); - #testSuite_verifyCount(3, k); # 3 classes in inheritance chain == 3 swigCPtr values + k = Klass3rdDerived("me oh my") - val = test3rdupcast(k); - unittest("me oh my-3rdDerived", val); - testSuite_verifyCount(2, k); - #testSuite_verifyCount(3, k); + unittest(overload_rawbyval(k), "rawbyval") + unittest(overload_rawbyref(k), "rawbyref") + unittest(overload_rawbyptr(k), "rawbyptr") + # unittest(overload_rawbyptrref(k), "rawbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__Klass3rdDerived_t + + unittest(overload_smartbyval(k), "smartbyval") + unittest(overload_smartbyref(k), "smartbyref") + unittest(overload_smartbyptr(k), "smartbyptr") + # unittest(overload_smartbyptrref(k), "smartbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__Klass3rdDerived_t } - # # ################ Member variables #################### # @@ -395,7 +399,7 @@ testSuite <- function() { testSuite_verifyCount(3, k); delete_MemberVariables(m) - testSuite_verifyCount(2, kmember); # these should be -1 wrt to the previous test ? + testSuite_verifyCount(2, kmember); testSuite_verifyCount(2, k); } @@ -443,7 +447,7 @@ testSuite <- function() { testSuite_verifyCount(4, k); delete_MemberVariables(m); - testSuite_verifyCount(3, kmemberVal); # should be one less than the previous one + testSuite_verifyCount(3, kmemberVal); testSuite_verifyCount(3, kmember); testSuite_verifyCount(3, k); } @@ -624,10 +628,6 @@ testSuite <- function() { } - - - - # # ###################### Templates ###################### # From deb86641653aef6a283ee468f41256862401f7eb Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Fri, 14 Oct 2022 20:53:53 +0200 Subject: [PATCH 125/217] enable test for pointerreftest fixed by 752b7e8 --- Examples/test-suite/r/li_boost_shared_ptr_runme.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/r/li_boost_shared_ptr_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_runme.R index 6df8984fc..059adf1da 100644 --- a/Examples/test-suite/r/li_boost_shared_ptr_runme.R +++ b/Examples/test-suite/r/li_boost_shared_ptr_runme.R @@ -161,13 +161,13 @@ testSuite <- function() { } # pass by pointer reference - if (FALSE) { + { k = Klass("me oh my"); kret = pointerreftest(k); # -> class not defined _p_p_Space__Klass val = kret$getValue(); unittest("me oh my pointerreftest", val); testSuite_verifyCount(1, k); - testSuite_verifyCount(1, kret); + # testSuite_verifyCount(1, kret); # -> use_count not defined on _p_Space__Klass } # null tests From 0fec14ba34c6fdfcf369ee5fe7a364937ad22866 Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Sun, 16 Oct 2022 20:49:00 +0200 Subject: [PATCH 126/217] align implementation of smartname to r class name --- Source/Modules/r.cxx | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 18a9aa56d..3d9cab0d4 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -2091,21 +2091,16 @@ int R::functionWrapper(Node *n) { if (constructor) { Node * parent = Getattr(n, "parentNode"); String * smartname = Getattr(parent, "feature:smartptr"); - if (smartname) { - String * classtypeobj = Getattr(parent, "classtypeobj"); // this is the correct name, e.g. ClassName(int) - String * classtype = NewString(Getattr(parent, "classtype")); // this is the "wrong" name e.g. ClassName - - // we replace inside smartname ClassName with ClassName(int) - String * smartname_fixed = NewString(smartname); - Replaceall(classtype, " ", ""); // classtype actually has spaces inside so we remove them - Replaceall(smartname_fixed, classtype, classtypeobj); - - String * smartname_fixed_rclass = getRClassName(smartname_fixed, 1, 1); - Replaceall(tm, "$R_class", smartname_fixed_rclass); - - Delete(classtype); - Delete(smartname_fixed); - Delete(smartname_fixed_rclass); + if (smartname) { // SmartName handling - has to be aligned to the other implementation in this file + SwigType *spt = Swig_cparse_type(smartname); + String *smart = SwigType_typedef_resolve_all(spt); + String *smart_rname = SwigType_manglestr(smart); + String *smart_rname_p = NewStringf("_p%s", smart_rname); + Replaceall(tm, "$R_class", smart_rname_p); + Delete(spt); + Delete(smart); + Delete(smart_rname); + Delete(smart_rname_p); } } if (debugMode) { @@ -2334,7 +2329,7 @@ void R::registerClass(Node *n) { Printf(s_classes, "setClass('%s', contains = %s)\n", sname, base); Delete(base); String *smartptr = Getattr(n, "feature:smartptr"); - if (smartptr) { + if (smartptr) {// SmartName handling - has to be aligned to the other implementation in this file List *l = Getattr(n, "bases"); SwigType *spt = Swig_cparse_type(smartptr); String *smart = SwigType_typedef_resolve_all(spt); From 4a8f7a9c46a3fda13266a350bc05baabcb90f93e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 24 Oct 2022 18:43:31 +0100 Subject: [PATCH 127/217] Visual C++ warning fixes --- Source/Modules/php.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index fd53d41f7..c8cc9212b 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -386,7 +386,7 @@ public: Setmark(item, 1); char *colon_ptr = Strchr(key, ':'); assert(colon_ptr); - int colon = colon_ptr - Char(key); + int colon = (int)(colon_ptr - Char(key)); if (colon > 0 && Strcmp(colon_ptr + 1, "__construct") != 0) { // See if there's a parent class which implements this method, and if so // emit its arginfo and then merge its PHPTypes into ours as we need to @@ -959,7 +959,7 @@ public: } } - phptypes->adjust(emit_num_required(l), Equal(fname, "__construct")); + phptypes->adjust(emit_num_required(l), Equal(fname, "__construct") ? true : false); String *arginfo_id = phptypes->get_arginfo_id(); String *s = cs_entry; From 6c4dcbb8fe62cd8802bb683eb9fc14b32e8459c3 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 24 Oct 2022 08:38:17 +0100 Subject: [PATCH 128/217] R shared_ptr fixes Fix problems in shared_ptr wrappers where the class names were not consistent when using the shared_ptr template or the actual underlying type. Move $R_class substitution to typemaps. Issue #2386 --- CHANGES.current | 5 ++ .../test-suite/r/li_boost_shared_ptr_runme.R | 66 +++++++++---------- Lib/r/boost_shared_ptr.i | 19 ++++++ Source/Modules/r.cxx | 40 ----------- 4 files changed, 57 insertions(+), 73 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 2ad66dd59..c82d1221b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-10-24: wsfulton, AndLLA + [R] #2386 Fix problems in shared_ptr wrappers where the class names + were not consistent when using the shared_ptr template or the actual + underlying type. + 2022-10-24: wsfulton [R] Add support for special variable replacement in the $typemap() special variable macro for R specific typemaps (rtype, rtypecheck, diff --git a/Examples/test-suite/r/li_boost_shared_ptr_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_runme.R index 059adf1da..d1e343cb3 100644 --- a/Examples/test-suite/r/li_boost_shared_ptr_runme.R +++ b/Examples/test-suite/r/li_boost_shared_ptr_runme.R @@ -83,7 +83,7 @@ testSuite <- function() { if (FALSE) { # pass by shared_ptr pointer reference k = Klass("me oh my") - kret = smartpointerpointerreftest(k) # undefined class _p_p_SwigBoost__shared_ptrT_Space__Klass_t + kret = smartpointerpointerreftest(k) val = kret$getValue() unittest("me oh my smartpointerpointerreftest", val) testSuite_verifyCount(2, k) @@ -93,7 +93,7 @@ testSuite <- function() { if (FALSE) { # pass by shared_ptr pointer reference k = Klass("me oh my"); - kret = smartpointerpointerreftest(k); # undefined class _p_p_SwigBoost__shared_ptrT_Space__Klass_t + kret = smartpointerpointerreftest(k); val = kret$getValue() unittest("me oh my smartpointerpointerreftest", val); testSuite_verifyCount(2, k); @@ -104,10 +104,10 @@ testSuite <- function() { { k = Klass("me oh my"); kret = constsmartpointertest(k); - val = Klass_getValue(kret) # kret$getValue(); - method not defined + val = Klass_getValue(kret); unittest("me oh my", val); testSuite_verifyCount(2, k); - # testSuite_verifyCount(2, kret); # -> use_count not defined on _p_SwigBoost__shared_ptrT_Space__Klass_const_t + testSuite_verifyCount(2, kret); } # const pass by shared_ptr pointer @@ -117,7 +117,7 @@ testSuite <- function() { val = Klass_getValue(kret) unittest("me oh my", val) testSuite_verifyCount(2, k) - # testSuite_verifyCount(2, kret) # -> use_count not defined on _p_SwigBoost__shared_ptrT_Space__Klass_const_t + testSuite_verifyCount(2, kret) } # const pass by shared_ptr reference @@ -127,7 +127,7 @@ testSuite <- function() { val = Klass_getValue(kret) unittest("me oh my", val) testSuite_verifyCount(2, k) - # testSuite_verifyCount(2, kret) # -> use_count not defined for _p_SwigBoost__shared_ptrT_Space__Klass_const_t + testSuite_verifyCount(2, kret) } # pass by value @@ -137,7 +137,7 @@ testSuite <- function() { val = kret$getValue(); unittest("me oh my valuetest", val); testSuite_verifyCount(1, k); - # testSuite_verifyCount(1, kret); # -> use_count not defined on _p_Space__Klass + testSuite_verifyCount(1, kret); } # pass by pointer @@ -147,7 +147,7 @@ testSuite <- function() { val = kret$getValue(); unittest("me oh my pointertest", val); testSuite_verifyCount(1, k); - # testSuite_verifyCount(1, kret); # -> use_count not defined on _p_Space__Klass + testSuite_verifyCount(1, kret); } # pass by reference @@ -157,17 +157,17 @@ testSuite <- function() { val = kret$getValue(); unittest("me oh my reftest", val); testSuite_verifyCount(1, k); - #testSuite_verifyCount(1, kret); # -> use_count not defined on _p_Space__Klass + testSuite_verifyCount(1, kret); } # pass by pointer reference { k = Klass("me oh my"); - kret = pointerreftest(k); # -> class not defined _p_p_Space__Klass + kret = pointerreftest(k); val = kret$getValue(); unittest("me oh my pointerreftest", val); testSuite_verifyCount(1, k); - # testSuite_verifyCount(1, kret); # -> use_count not defined on _p_Space__Klass + testSuite_verifyCount(1, kret); } # null tests @@ -239,7 +239,7 @@ testSuite <- function() { k = pointerownertest(); val = k$getValue(); unittest("pointerownertest", val); - # testSuite_verifyCount(1, k); # -> use_count not defined for _p_Space__Klass + testSuite_verifyCount(1, k); } { @@ -286,7 +286,7 @@ testSuite <- function() { # pass by shared_ptr pointer reference (mixed) if (FALSE) { k = KlassDerived("me oh my"); - kret = smartpointerpointerreftest(k); # undefined class _p_p_SwigBoost__shared_ptrT_Space__Klass_t + kret = smartpointerpointerreftest(k); val = kret$getValue(); unittest("me oh my derivedsmartptrpointerreftest-Derived", val); testSuite_verifyCount(2, k); # includes two extra references for upcasts in the proxy classes @@ -313,7 +313,7 @@ testSuite <- function() { val = kret$getValue(); unittest("me oh my derivedpointertest-Derived", val); testSuite_verifyCount(1, k); - # testSuite_verifyCount(1, kret); -> use_count not defined for _p_Space__KlassDerived + testSuite_verifyCount(1, kret); } # pass by ref (mixed) @@ -340,12 +340,12 @@ testSuite <- function() { unittest(overload_rawbyval(k), "rawbyval") unittest(overload_rawbyref(k), "rawbyref") unittest(overload_rawbyptr(k), "rawbyptr") - # unittest(overload_rawbyptrref(k), "rawbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__Klass_t + unittest(overload_rawbyptrref(k), "rawbyptrref") unittest(overload_smartbyval(k), "smartbyval") unittest(overload_smartbyref(k), "smartbyref") unittest(overload_smartbyptr(k), "smartbyptr") - # unittest(overload_smartbyptrref(k), "smartbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__Klass_t + unittest(overload_smartbyptrref(k), "smartbyptrref") } # Derived class @@ -355,12 +355,12 @@ testSuite <- function() { unittest(overload_rawbyval(k), "rawbyval") unittest(overload_rawbyref(k), "rawbyref") unittest(overload_rawbyptr(k), "rawbyptr") - # unittest(overload_rawbyptrref(k), "rawbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__KlassDerived_t + unittest(overload_rawbyptrref(k), "rawbyptrref") unittest(overload_smartbyval(k), "smartbyval") unittest(overload_smartbyref(k), "smartbyref") unittest(overload_smartbyptr(k), "smartbyptr") - # unittest(overload_smartbyptrref(k), "smartbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__KlassDerived_t + unittest(overload_smartbyptrref(k), "smartbyptrref") } # 3rd derived class @@ -370,12 +370,12 @@ testSuite <- function() { unittest(overload_rawbyval(k), "rawbyval") unittest(overload_rawbyref(k), "rawbyref") unittest(overload_rawbyptr(k), "rawbyptr") - # unittest(overload_rawbyptrref(k), "rawbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__Klass3rdDerived_t + unittest(overload_rawbyptrref(k), "rawbyptrref") unittest(overload_smartbyval(k), "smartbyval") unittest(overload_smartbyref(k), "smartbyref") unittest(overload_smartbyptr(k), "smartbyptr") - # unittest(overload_smartbyptrref(k), "smartbyptrref") --> undefined for _p_SwigBoost__shared_ptrT_Space__Klass3rdDerived_t + unittest(overload_smartbyptrref(k), "smartbyptrref") } # @@ -573,7 +573,7 @@ testSuite <- function() { kglobal = GlobalValue_get(); val = kglobal$getValue(); unittest("global value", val); - # testSuite_verifyCount(1, kglobal); # -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, kglobal); testSuite_verifyCount(1, k); unittest("global value", GlobalValue_get()$getValue()); @@ -600,7 +600,7 @@ testSuite <- function() { kglobal = GlobalPointer_get(); val = kglobal$getValue(); unittest("global pointer", val); - # testSuite_verifyCount(1, kglobal); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, kglobal); testSuite_verifyCount(1, k); GlobalPointer_set(NULL); } @@ -614,7 +614,7 @@ testSuite <- function() { kglobal = GlobalReference_get(); val = kglobal$getValue(); unittest("global reference", val); - # testSuite_verifyCount(1, kglobal); # -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, kglobal); testSuite_verifyCount(1, k); bNotCatched = F @@ -652,16 +652,16 @@ for (i in 1:10) { # wait for the GC to collect unused objects -for (i in 1:10) { - invisible(gc(verbose = F, full = T)) - - if (Klass_getTotal_count() == 1) { - break - } - - print(paste("Still waiting for GC to collect ", Klass_getTotal_count()-1, " objects, ", i)) - Sys.sleep(1) -} +#for (i in 1:10) { +# invisible(gc(verbose = F, full = T)) +# +# if (Klass_getTotal_count() == 1) { +# break +# } +# +# print(paste("Still waiting for GC to collect ", Klass_getTotal_count()-1, " objects, ", i)) +# Sys.sleep(1) +#} # Expect unittest(shared_ptr_wrapper_count(), NOT_COUNTING()) diff --git a/Lib/r/boost_shared_ptr.i b/Lib/r/boost_shared_ptr.i index 87c89b5f9..13f041fbb 100644 --- a/Lib/r/boost_shared_ptr.i +++ b/Lib/r/boost_shared_ptr.i @@ -394,6 +394,25 @@ #error "typemaps for $1_type not available" %} +%typemap(rtype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "$typemap(rtype, TYPE)" + +%typemap(scoercein) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + %{ if (inherits($input, "ExternalReference")) $input = slot($input,"ref"); %} + +%typemap(scoerceout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + %{ $result <- if (is.null($result)) $result + else new("$typemap(rtype, TYPE)", ref=$result); %} + %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 3d9cab0d4..e1fd422dd 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -2088,21 +2088,6 @@ int R::functionWrapper(Node *n) { /*If the user gave us something to convert the result in */ if ((tm = Swig_typemap_lookup("scoerceout", n, Swig_cresult_name(), sfun))) { Replaceall(tm,"$result","ans"); - if (constructor) { - Node * parent = Getattr(n, "parentNode"); - String * smartname = Getattr(parent, "feature:smartptr"); - if (smartname) { // SmartName handling - has to be aligned to the other implementation in this file - SwigType *spt = Swig_cparse_type(smartname); - String *smart = SwigType_typedef_resolve_all(spt); - String *smart_rname = SwigType_manglestr(smart); - String *smart_rname_p = NewStringf("_p%s", smart_rname); - Replaceall(tm, "$R_class", smart_rname_p); - Delete(spt); - Delete(smart); - Delete(smart_rname); - Delete(smart_rname_p); - } - } if (debugMode) { Printf(stdout, "Calling replace B: %s, %s, %s\n", Getattr(n, "type"), Getattr(n, "sym:name"), getNSpace()); } @@ -2328,31 +2313,6 @@ void R::registerClass(Node *n) { Printf(s_classes, "setClass('%s', contains = %s)\n", sname, base); Delete(base); - String *smartptr = Getattr(n, "feature:smartptr"); - if (smartptr) {// SmartName handling - has to be aligned to the other implementation in this file - List *l = Getattr(n, "bases"); - SwigType *spt = Swig_cparse_type(smartptr); - String *smart = SwigType_typedef_resolve_all(spt); - String *smart_rname = SwigType_manglestr(smart); - Printf(s_classes, "setClass('_p%s', contains = c('%s'", smart_rname, sname); - Delete(spt); - Delete(smart); - Delete(smart_rname); - for(int i = 0; i < Len(l); i++) { - Node * b = Getitem(l, i); - smartptr = Getattr(b, "feature:smartptr"); - if (smartptr) { - spt = Swig_cparse_type(smartptr); - smart = SwigType_typedef_resolve_all(spt); - smart_rname = SwigType_manglestr(smart); - Printf(s_classes, ", '_p%s'", smart_rname); - Delete(spt); - Delete(smart); - Delete(smart_rname); - } - } - Printf(s_classes, "))\n"); - } } } From d238d109c95f2245f2f68b53d054bd28d7e95fb0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 24 Oct 2022 19:35:04 +0100 Subject: [PATCH 129/217] Whitespace cleanup in R testcase --- .../test-suite/r/li_boost_shared_ptr_runme.R | 128 +++++++++--------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/Examples/test-suite/r/li_boost_shared_ptr_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_runme.R index d1e343cb3..ecdc7f1ab 100644 --- a/Examples/test-suite/r/li_boost_shared_ptr_runme.R +++ b/Examples/test-suite/r/li_boost_shared_ptr_runme.R @@ -24,8 +24,8 @@ unittest(shared_ptr_wrapper_count(), NOT_COUNTING()) # testSuite_verifyCount <- function(expected, k) { - got = use_count(k) - unittest(expected, got); + got = use_count(k) + unittest(expected, got); } testSuite <- function() { @@ -34,7 +34,7 @@ testSuite <- function() { # Reference Implementation is li_boost_shared_ptr_runme.py # - # simple shared_ptr usage - created in C++ + # simple shared_ptr usage - created in C++ { k = Klass("me oh my") val = k$getValue() @@ -42,73 +42,73 @@ testSuite <- function() { testSuite_verifyCount(1, k) } - # simple shared_ptr usage - not created in C++ - { - k = factorycreate() - val = k$getValue() - unittest("factorycreate", val) - testSuite_verifyCount(1, k) - } + # simple shared_ptr usage - not created in C++ + { + k = factorycreate() + val = k$getValue() + unittest("factorycreate", val) + testSuite_verifyCount(1, k) + } - # pass by shared_ptr - { - k = Klass("me oh my") - kret = smartpointertest(k) - val = kret$getValue() - unittest("me oh my smartpointertest", val) - testSuite_verifyCount(2, k) - testSuite_verifyCount(2, kret) - } + # pass by shared_ptr + { + k = Klass("me oh my") + kret = smartpointertest(k) + val = kret$getValue() + unittest("me oh my smartpointertest", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } - # pass by shared_ptr pointer - { - k = Klass("me oh my") - kret = smartpointerpointertest(k) - val = kret$getValue() - unittest("me oh my smartpointerpointertest", val) - testSuite_verifyCount(2, k) - testSuite_verifyCount(2, kret) - } + # pass by shared_ptr pointer + { + k = Klass("me oh my") + kret = smartpointerpointertest(k) + val = kret$getValue() + unittest("me oh my smartpointerpointertest", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } - # pass by shared_ptr reference - { - k = Klass("me oh my") - kret = smartpointerreftest(k) - val = kret$getValue() - unittest("me oh my smartpointerreftest", val) - testSuite_verifyCount(2, k) - testSuite_verifyCount(2, kret) - } + # pass by shared_ptr reference + { + k = Klass("me oh my") + kret = smartpointerreftest(k) + val = kret$getValue() + unittest("me oh my smartpointerreftest", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } - if (FALSE) { - # pass by shared_ptr pointer reference - k = Klass("me oh my") - kret = smartpointerpointerreftest(k) - val = kret$getValue() - unittest("me oh my smartpointerpointerreftest", val) - testSuite_verifyCount(2, k) - testSuite_verifyCount(2, kret) - } + if (FALSE) { + # pass by shared_ptr pointer reference + k = Klass("me oh my") + kret = smartpointerpointerreftest(k) + val = kret$getValue() + unittest("me oh my smartpointerpointerreftest", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } - if (FALSE) { - # pass by shared_ptr pointer reference - k = Klass("me oh my"); - kret = smartpointerpointerreftest(k); - val = kret$getValue() - unittest("me oh my smartpointerpointerreftest", val); - testSuite_verifyCount(2, k); - testSuite_verifyCount(2, kret); - } + if (FALSE) { + # pass by shared_ptr pointer reference + k = Klass("me oh my"); + kret = smartpointerpointerreftest(k); + val = kret$getValue() + unittest("me oh my smartpointerpointerreftest", val); + testSuite_verifyCount(2, k); + testSuite_verifyCount(2, kret); + } - # const pass by shared_ptr - { - k = Klass("me oh my"); - kret = constsmartpointertest(k); - val = Klass_getValue(kret); - unittest("me oh my", val); - testSuite_verifyCount(2, k); - testSuite_verifyCount(2, kret); - } + # const pass by shared_ptr + { + k = Klass("me oh my"); + kret = constsmartpointertest(k); + val = Klass_getValue(kret); + unittest("me oh my", val); + testSuite_verifyCount(2, k); + testSuite_verifyCount(2, kret); + } # const pass by shared_ptr pointer { From c9dcd0ee78e710b783096b5b02c14580a919e92d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 24 Oct 2022 19:47:03 +0100 Subject: [PATCH 130/217] Add SWIG-4.1.0 release date --- ANNOUNCE | 2 +- CHANGES.current | 2 +- Doc/Manual/Sections.html | 2 +- README | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index 90ac94f52..1ca7d72c5 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,4 +1,4 @@ -*** ANNOUNCE: SWIG 4.1.0 (in progress) *** +*** ANNOUNCE: SWIG 4.1.0 (24 Oct 2022) *** https://www.swig.org diff --git a/CHANGES.current b/CHANGES.current index c82d1221b..4bf04e4c9 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -4,7 +4,7 @@ See the RELEASENOTES file for a summary of changes in each release. Issue # numbers mentioned below can be found on Github. For more details, add the issue number to the end of the URL: https://github.com/swig/swig/issues/ -Version 4.1.0 (in progress) +Version 4.1.0 (24 Oct 2022) =========================== 2022-10-24: wsfulton, AndLLA diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html index 2a0d023a2..d06bb7120 100644 --- a/Doc/Manual/Sections.html +++ b/Doc/Manual/Sections.html @@ -8,7 +8,7 @@

      SWIG-4.1 Documentation

      -Last update : SWIG-4.1.0 (in progress) +Last update : SWIG-4.1.0 (24 Oct 2022)

      Sections

      diff --git a/README b/README index ff28090fb..c5317fee7 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ SWIG (Simplified Wrapper and Interface Generator) -Version: 4.1.0 (in progress) +Version: 4.1.0 (24 Oct 2022) Tagline: SWIG is a compiler that integrates C and C++ with languages including Perl, Python, Tcl, Ruby, PHP, Java, C#, D, Go, Lua, From 899c9b819e0d30b3c7235b776ac0802c5325b2a4 Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Mon, 24 Oct 2022 10:54:47 -0700 Subject: [PATCH 131/217] Modify some CHANGES entries that weren't written by me [skip ci] --- CHANGES | 6 +++--- CHANGES.current | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 7ea3450fb..fb5d8b55e 100644 --- a/CHANGES +++ b/CHANGES @@ -27,7 +27,7 @@ Version 4.0.2 (8 Jun 2020) [D] #1593 Replace broken imports when using newer versions of D. 2020-05-29: ZackerySpytz - [Python] #1716 Performance improvements converting strings when using Python >= 3.3. + [Python] #1716 Performance improvements when converting strings when using Python >= 3.3. 2020-05-28: ZackerySpytz #1776 Quite dramatically decrease run times when generating very large interface files by changing @@ -74,8 +74,8 @@ Version 4.0.2 (8 Jun 2020) [Ruby] #1651 Add std::auto_ptr<> typemaps. 2020-01-31: ZackerySpytz - [Python] #1700 More robust error checking for failures in calls to Python C API: - PyBytes_AsStringAndSize() and PyString_AsStringAndSize(). + [Python] #1700 The Python C API functions PyBytes_AsStringAndSize() and + PyString_AsStringAndSize() are now checked for failure. 2020-01-31: vadz [Python] #1710 Fix crash parsing empty docstrings. diff --git a/CHANGES.current b/CHANGES.current index 4bf04e4c9..549a05c1e 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1275,5 +1275,5 @@ Version 4.1.0 (24 Oct 2022) #1843 [Python] Compilation error fix in SwigPyBuiltin_SetMetaType when using PyPy. 2020-06-14: ZackerySpytz - #1642 #1809 Fix virtual comparison operators in director classes - remove incorrect - space in the function name, for example, operator= = is now operator==. + #1642 #1809 Fix virtual comparison operators in director classes by removing an + incorrect space in the function name (for example, operator= = is now operator==). From 76f004766d245d3a0a22ccd1102e0e61e45f582d Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Mon, 24 Oct 2022 21:43:34 +0200 Subject: [PATCH 132/217] enable tests working after master merge --- .../test-suite/r/li_boost_shared_ptr_runme.R | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Examples/test-suite/r/li_boost_shared_ptr_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_runme.R index ecdc7f1ab..d35919902 100644 --- a/Examples/test-suite/r/li_boost_shared_ptr_runme.R +++ b/Examples/test-suite/r/li_boost_shared_ptr_runme.R @@ -80,7 +80,7 @@ testSuite <- function() { testSuite_verifyCount(2, kret) } - if (FALSE) { + { # pass by shared_ptr pointer reference k = Klass("me oh my") kret = smartpointerpointerreftest(k) @@ -90,7 +90,7 @@ testSuite <- function() { testSuite_verifyCount(2, kret) } - if (FALSE) { + { # pass by shared_ptr pointer reference k = Klass("me oh my"); kret = smartpointerpointerreftest(k); @@ -288,7 +288,7 @@ testSuite <- function() { k = KlassDerived("me oh my"); kret = smartpointerpointerreftest(k); val = kret$getValue(); - unittest("me oh my derivedsmartptrpointerreftest-Derived", val); + unittest("me oh my derivedsmartptrpointerreftest-Derived", val); # fails "me oh my derivedsmartptrpointerreftest-Derived != me oh my smartpointerpointerreftest-Derived" testSuite_verifyCount(2, k); # includes two extra references for upcasts in the proxy classes testSuite_verifyCount(2, kret); } @@ -300,9 +300,10 @@ testSuite <- function() { val = kret$getValue() unittest("me oh my valuetest", val) # note slicing testSuite_verifyCount(2, k) - # testSuite_verifyCount(2, kret) --> use count not defined for _p_Space__Klass + testSuite_verifyCount(1, kret) - # testSuite_verifyCount(1, k) # this is the python expected reference counting + # --> these are the python expected counting + # testSuite_verifyCount(1, k) # testSuite_verifyCount(1, kret) } @@ -323,9 +324,10 @@ testSuite <- function() { val = kret$getValue(); unittest("me oh my reftest-Derived", val); testSuite_verifyCount(2, k); - #testSuite_verifyCount(2, kret); --> use_count not defined for _p_Space__KlassDerived + testSuite_verifyCount(1, kret); - #testSuite_verifyCount(1, k); # --> this is the python expected counting + # --> these are the python expected counting + #testSuite_verifyCount(1, k); #testSuite_verifyCount(1, kret); } @@ -464,11 +466,11 @@ testSuite <- function() { kmember = MemberVariables_MemberValue_get(m); # m$getMemberValue(); val = kmember$getValue(); unittest("plain member value", val); - # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); delete_MemberVariables(m); # m.delete(); - # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); } @@ -484,11 +486,11 @@ testSuite <- function() { kmember = MemberVariables_MemberPointer_get(self = m); # m$getMemberPointer(); val = kmember$getValue(); unittest("plain member pointer", val); - # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); delete_MemberVariables(m); # m.delete(); - # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); } @@ -504,11 +506,11 @@ testSuite <- function() { kmember = MemberVariables_MemberReference_get(self = m); #m$getMemberReference(); val = kmember$getValue(); unittest("plain member reference", val); - # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, kmember); # -> use_count undefined for _p_Space__Klass testSuite_verifyCount(1, k); delete_MemberVariables(m); # m.delete(); - # testSuite_verifyCount(1, kmember); -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, kmember); #-> use_count undefined for _p_Space__Klass testSuite_verifyCount(1, k); } @@ -525,7 +527,7 @@ testSuite <- function() { k = MemberVariables_SmartMemberValue_get(self = m); #m$getSmartMemberValue(); if (!is.null(k)) stop("expected null"); - #testSuite_verifyCount(0, k); + #testSuite_verifyCount(0, k); # this does not work for nulls # plain by value bNotCatched = F From 1e99e4fe37c0f2334b6de1c6bc3fcd3188bc2c92 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 24 Oct 2022 22:44:31 +0100 Subject: [PATCH 133/217] R shared_ptr testing Enable more tests. Use preferred member variable access. --- .../test-suite/r/li_boost_shared_ptr_runme.R | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/Examples/test-suite/r/li_boost_shared_ptr_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_runme.R index d35919902..73765b3e3 100644 --- a/Examples/test-suite/r/li_boost_shared_ptr_runme.R +++ b/Examples/test-suite/r/li_boost_shared_ptr_runme.R @@ -284,13 +284,13 @@ testSuite <- function() { } # pass by shared_ptr pointer reference (mixed) - if (FALSE) { + { k = KlassDerived("me oh my"); kret = smartpointerpointerreftest(k); val = kret$getValue(); - unittest("me oh my derivedsmartptrpointerreftest-Derived", val); # fails "me oh my derivedsmartptrpointerreftest-Derived != me oh my smartpointerpointerreftest-Derived" - testSuite_verifyCount(2, k); # includes two extra references for upcasts in the proxy classes - testSuite_verifyCount(2, kret); + unittest("me oh my smartpointerpointerreftest-Derived", val); + #testSuite_verifyCount(2, k); # includes two extra references for upcasts in the proxy classes + #testSuite_verifyCount(2, kret); } # pass by value (mixed) @@ -388,13 +388,13 @@ testSuite <- function() { { m = MemberVariables(); k = Klass("smart member value"); - MemberVariables_SmartMemberValue_set(self = m, s_SmartMemberValue = k) + m$SmartMemberValue = k; val = k$getValue(); unittest("smart member value", val); testSuite_verifyCount(2, k); - kmember = MemberVariables_SmartMemberPointer_get(self = m) + kmember = m$SmartMemberPointer; val = kmember$getValue(); unittest("smart member value", val); testSuite_verifyCount(3, kmember); @@ -409,12 +409,12 @@ testSuite <- function() { { m = MemberVariables(); k = Klass("smart member pointer"); - MemberVariables_SmartMemberPointer_set(self = m , s_SmartMemberPointer = k); + m$SmartMemberPointer = k; val = k$getValue(); unittest("smart member pointer", val); testSuite_verifyCount(1, k); - kmember = MemberVariables_SmartMemberPointer_get(self = m) + kmember = m$SmartMemberPointer; val = kmember$getValue(); unittest("smart member pointer", val); testSuite_verifyCount(2, kmember); @@ -429,19 +429,19 @@ testSuite <- function() { { m = MemberVariables(); k = Klass("smart member reference"); - MemberVariables_SmartMemberReference_set(self = m , s_SmartMemberReference = k); # m$setSmartMemberReference(k); + m$SmartMemberReference = k; val = k$getValue(); unittest("smart member reference", val); testSuite_verifyCount(2, k); - kmember = MemberVariables_SmartMemberPointer_get(self = m) + kmember = m$SmartMemberPointer; val = kmember$getValue(); unittest("smart member reference", val); testSuite_verifyCount(3, kmember); testSuite_verifyCount(3, k); # The C++ reference refers to SmartMemberValue... - kmemberVal = MemberVariables_SmartMemberReference_get(self = m) + kmemberVal = m$SmartMemberReference; val = kmember$getValue(); unittest("smart member reference", val); testSuite_verifyCount(4, kmemberVal); @@ -458,12 +458,12 @@ testSuite <- function() { { m = MemberVariables(); k = Klass("plain member value"); - MemberVariables_MemberValue_set(self = m, s_MemberValue = k); # m$setMemberValue(k); + m$MemberValue = k; val = k$getValue(); unittest("plain member value", val); testSuite_verifyCount(1, k); - kmember = MemberVariables_MemberValue_get(m); # m$getMemberValue(); + kmember = m$MemberValue; val = kmember$getValue(); unittest("plain member value", val); testSuite_verifyCount(1, kmember); @@ -478,12 +478,12 @@ testSuite <- function() { { m = MemberVariables(); k = Klass("plain member pointer"); - MemberVariables_MemberPointer_set(self = m, s_MemberPointer = k); # m$setMemberPointer(k); + m$MemberPointer = k; val = k$getValue(); unittest("plain member pointer", val); testSuite_verifyCount(1, k); - kmember = MemberVariables_MemberPointer_get(self = m); # m$getMemberPointer(); + kmember = m$MemberPointer; val = kmember$getValue(); unittest("plain member pointer", val); testSuite_verifyCount(1, kmember); @@ -498,19 +498,19 @@ testSuite <- function() { { m = MemberVariables(); k = Klass("plain member reference"); - MemberVariables_MemberReference_set(self = m, s_MemberReference = k); # m$setMemberReference(k); + m$MemberReference = k; val = k$getValue(); unittest("plain member reference", val); testSuite_verifyCount(1, k); - kmember = MemberVariables_MemberReference_get(self = m); #m$getMemberReference(); + kmember = m$MemberReference; val = kmember$getValue(); unittest("plain member reference", val); - testSuite_verifyCount(1, kmember); # -> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); delete_MemberVariables(m); # m.delete(); - testSuite_verifyCount(1, kmember); #-> use_count undefined for _p_Space__Klass + testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); } @@ -519,12 +519,12 @@ testSuite <- function() { m = MemberVariables(); # shared_ptr by value - k = MemberVariables_SmartMemberValue_get(self = m); # k = m$getSmartMemberValue(); + k = m$SmartMemberValue; if (!is.null(k)) stop("expected null"); - MemberVariables_SmartMemberValue_set(self = m, s_SmartMemberValue = NULL); #m$setSmartMemberValue(null); - k = MemberVariables_SmartMemberValue_get(self = m); #m$getSmartMemberValue(); + m$SmartMemberValue = NULL; + k = m$SmartMemberValue; if (!is.null(k)) stop("expected null"); #testSuite_verifyCount(0, k); # this does not work for nulls @@ -532,13 +532,12 @@ testSuite <- function() { # plain by value bNotCatched = F try({ - MemberVariables_MemberValue_set(self = m, s_MemberValue = NULL) + m$MemberValue = NULL bNotCatched = T }, silent = T) if (bNotCatched) { stop("Failed to catch null pointer") } - } From 96f2235d6de942f87cfc49ff9962a54b58dd99d5 Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Wed, 26 Oct 2022 09:25:04 +0200 Subject: [PATCH 134/217] CMake: Fix -swiglib on win32 - swig library files must be installed relatively to the exe into PREFIX/bin/Lib - unset SWIG_LIB_WIN_UNIX else swiglib returns a list of 2 paths which break cmake detection (and consistent to the provided windows binaries) --- CMakeLists.txt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7303f4cff..6298b62d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,8 +20,11 @@ endif () set (SWIG_ROOT ${PROJECT_SOURCE_DIR}) -set (SWIG_LIB share/swig/${SWIG_VERSION}) - +if (WIN32) + set (SWIG_LIB bin/Lib) +else () + set (SWIG_LIB share/swig/${SWIG_VERSION}) +endif () # Project wide configuration variables # ------------------------------------ @@ -80,10 +83,10 @@ if (WITH_PCRE) include_directories (${PCRE2_INCLUDE_DIRS}) endif() -if (WIN32) - file (TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/${SWIG_LIB} SWIG_LIB_WIN_UNIX) - string (REGEX REPLACE "\\\\" "\\\\\\\\" SWIG_LIB_WIN_UNIX "${SWIG_LIB_WIN_UNIX}") -endif () +#if (WIN32) +# file (TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/${SWIG_LIB} SWIG_LIB_WIN_UNIX) +# string (REGEX REPLACE "\\\\" "\\\\\\\\" SWIG_LIB_WIN_UNIX "${SWIG_LIB_WIN_UNIX}") +#endif () configure_file (${SWIG_ROOT}/Tools/cmake/swigconfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/Source/Include/swigconfig.h) From 62e27bb61680482ec9a1a0a27f7bb29946c9472e Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 30 Oct 2022 22:48:14 +0200 Subject: [PATCH 135/217] build: harden nuget.yml permissions Signed-off-by: Alex --- .github/workflows/nuget.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 7b8174a1e..40ab4244c 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -13,6 +13,9 @@ on: - 'Doc/**' - 'appveyor.yml' +permissions: + contents: read # to fetch code (actions/checkout) + jobs: build: From df716b8f00fd4c6c980b91569ab7612015509c01 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 31 Oct 2022 12:59:22 +1300 Subject: [PATCH 136/217] Document that -php7 is for PHP 7 *or later* This was already in the manual, but not in -help output. Fixes #2420 --- Source/Modules/swigmain.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx index ad24d0fee..d553fe893 100644 --- a/Source/Modules/swigmain.cxx +++ b/Source/Modules/swigmain.cxx @@ -70,7 +70,7 @@ static TargetLanguageModule modules[] = { {"-perl5", swig_perl5, "Perl 5", Supported}, {"-php", swig_php, NULL, Supported}, {"-php5", NULL, "PHP 5", Disabled}, - {"-php7", swig_php, "PHP 7", Supported}, + {"-php7", swig_php, "PHP 7 or later", Supported}, {"-pike", NULL, "Pike", Disabled}, {"-python", swig_python, "Python", Supported}, {"-r", swig_r, "R (aka GNU S)", Supported}, From 1f40d38e56c79d5ba7b2442033297c8095e0cbe8 Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Sat, 29 Oct 2022 11:19:18 -0600 Subject: [PATCH 137/217] Use more portable PyUnicode_AsUTF8* methods. This supports the use of Py_LIMITED_API and also uses PyUnicode_AsUTF8AndSize if Py_LIMITED_API is set to 3.10 or newer. --- Lib/python/pyhead.swg | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Lib/python/pyhead.swg b/Lib/python/pyhead.swg index 6f37160bb..a5f804a7b 100644 --- a/Lib/python/pyhead.swg +++ b/Lib/python/pyhead.swg @@ -34,7 +34,14 @@ SWIGINTERN char* SWIG_Python_str_AsChar(PyObject *str) { #if PY_VERSION_HEX >= 0x03030000 - return (char *)PyUnicode_AsUTF8(str); +# if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000 + return (char*)PyUnicode_AsUTF8AndSize(str, NULL); +# else + PyObject* bytes = PyUnicode_AsUTF8String(str); + char* chars = PyBytes_AsString(bytes); + Py_DECREF(bytes); + return chars; +# endif #else return PyString_AsString(str); #endif From fe2d781b422372994491d414ae64a4ea24703d8c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 4 Nov 2022 20:09:13 +0000 Subject: [PATCH 138/217] Bump version to 4.2.0 and migrate CHANGES to CHANGES.current --- ANNOUNCE | 8 +- CHANGES | 1274 ++++++++++++++++++++++++++++++++++++++ CHANGES.current | 1272 +------------------------------------ Doc/Manual/Sections.html | 6 +- README | 2 - configure.ac | 2 +- 6 files changed, 1283 insertions(+), 1281 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index 1ca7d72c5..73ddb2b77 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,8 +1,8 @@ -*** ANNOUNCE: SWIG 4.1.0 (24 Oct 2022) *** +*** ANNOUNCE: SWIG 4.2.0 (in progress) *** https://www.swig.org -We're pleased to announce SWIG-4.1.0, the latest SWIG release. +We're pleased to announce SWIG-4.2.0, the latest SWIG release. What is SWIG? ============= @@ -25,11 +25,11 @@ Availability ============ The release is available for download on Sourceforge at - https://prdownloads.sourceforge.net/swig/swig-4.1.0.tar.gz + https://prdownloads.sourceforge.net/swig/swig-4.2.0.tar.gz A Windows version is also available at - https://prdownloads.sourceforge.net/swig/swigwin-4.1.0.zip + https://prdownloads.sourceforge.net/swig/swigwin-4.2.0.zip Please report problems with this release to the swig-devel mailing list, details at https://www.swig.org/mail.html. diff --git a/CHANGES b/CHANGES index fb5d8b55e..9001d0181 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,1280 @@ See the RELEASENOTES file for a summary of changes in each release. Issue # numbers mentioned below can be found on Github. For more details, add the issue number to the end of the URL: https://github.com/swig/swig/issues/ +Version 4.1.0 (24 Oct 2022) +=========================== + +2022-10-24: wsfulton, AndLLA + [R] #2386 Fix problems in shared_ptr wrappers where the class names + were not consistent when using the shared_ptr template or the actual + underlying type. + +2022-10-24: wsfulton + [R] Add support for special variable replacement in the $typemap() + special variable macro for R specific typemaps (rtype, rtypecheck, + scoercein, scoereout). + +2022-10-24: wsfulton + [R] Polymorphism in the wrappers was only working for C++ classes, + now this works for C++ structs too. + +2022-10-19: olly + [Lua] #2126 Fix type resolution between multiple SWIG-wrapped + modules. + +2022-10-17: wsfulton + [R] #2385 Add support for std::vector>. + +2022-10-14: murillo128 + [Javascript] #2109 Tweak unsigned long and unsigned long long typemaps + to create a v8::Number instead of v8::Integer if the value exceeds + the size of v8::Integer. Note that the v8::Number value will be + imprecise if the value is > MAX_SAFE_INTEGER. + +2022-10-14: olly + [R] Arrange that destructors of local C++ objects in the wrapper + function get run on SWIG_fail (which calls Rf_error() which calls + longjmp()). + +2022-10-14: olly + [Lua] Arrange that destructors of local C++ objects in the wrapper + function get run on SWIG_fail (which calls lua_error() which calls + longjmp()). + +2022-10-13: wsfulton + [R] Add missing SWIGTYPE *const& typemaps for supporting pointers + by const reference. + +2022-10-10: wsfulton + #2160 Fix compile error when using templates with more than one template + parameter and used as an input parameter in a virtual method in a + director class (problem affecting most of the scripting languages). + +2022-10-10: treitmayr, wsfulton + [Python, Ruby] #1811 #1823 Fix invalid code generated in some cases when + returning a pointer or reference to a director-enabled class instance. + This previously only worked in very simple cases, now return types are + resolved to fix. A bug in template instantiations using pointers also + works now. + +2022-10-06: wsfulton + [CFFI] #1966 #2200 Remove code for Common Lisp CFFI. We dropped support + for it in SWIG 4.0.0 by disabling it as the first stage. This is the + final stage for complete removal as there has been no meaningful + progress to revive it to the status of experimental language. + +2022-10-06: olly + [Python] #2390 Remove deprecated and apparently useless defarg.swg + + The only documentation is in the file itself and describes a Python + wrapper around the C function defined here, but digging though the + git history this Python wrapper doesn't seem to have ever actually + been generated by SWIG. + + This file was also marked as deprecated in 2005. + +2022-10-06: wsfulton + [Java] #2048 Fix quoting for doxygen \image command to quote the output + file name generated into the html src attribute. + +2022-10-05: benjamin-sch + [Python] added an interpreter counter to fix deinitialization + issues if multiple subinterpreters are used + +2022-10-05: olly, wsfulton + #672 Add support for parsing C++11 final classes such as: + + class X final {}; + + This no longer gives a syntax error. + +2022-10-05: wsfulton + [OCaml] Fix %rename for enum items. Previously the rename had no effect. + +2022-10-05: olly + #1465 Report errors in preprocessor expressions by default + + Until now SWIG quietly ignored such errors unless -Wextra (or -Wall + which implies -Wextra) was passed, but this is unhelpful as it tends + to hide genuine problems. To illustrate this point, enabling this + warning by default revealed a typo in the preproc_defined.i + testcase in SWIG's own testsuite. + + If you really don't want to see this warning, you can suppress it + with command line option -w202 or by using this in your interface + file: + + %warnfilter(SWIGWARN_PP_EVALUATION); + + Both will work with older versions of SWIG too. + +2022-10-04: olly + #1050 Consistently define SWIG_VERSION both at SWIG-time and in + the generated wrapper. Best practice remains to check at SWIG-time + where possible because that results in smaller generated wrapper + sources. + + SWIGGO and SWIGJAVASCRIPT are now defined in the generated wrappers + to match behaviour for all other target languages. + + The undocumented SWIGVERSION macro is no longer defined. + +2022-09-29: olly + #2303 SWIG's internal hash tables now use a better hash function. + + The old hash function only considerd the last five characters + plus the least significant bit of the last-but-sixth character, + which as you might guess generated a lot of many-way collisions. + + This change seems to give about a 4% reduction in wallclock time + for processing li_std_list_wrap.i from the testsuite for Python. + The hash collision rate for this example drops from 39% to 0! + +2022-09-29: wsfulton + #2303 Type tables are now output in a fixed order whereas previously + the order may change with any minor input code change. This shouldn't + affect users except SWIG_TypePrettyName may output a different C/C++ + typedef to a type - it's used mostly for showing errors when the type + passed to a function is wrong. + +2022-09-29: olly + [PHP] Dynamic class properties are no longer supported by default. + + Historically PHP has supported dynamic class properties and SWIG + has implemented them too (because we implement the magic __get(), + __set() and __isset() methods we need to include explicit + handling). + + PHP 8.2 deprecates dynamic class properties - initially they'll + warn, and apparently they'll not work by default in PHP 9.0: + https://wiki.php.net/rfc/deprecate_dynamic_properties + + In PHP code dynamic properties can be enabled for a class by + marking that class with the attribute `#[AllowDynamicProperties]`. + + To follow this PHP change, in SWIG you now need to specify + `%feature("php:allowdynamicproperties", 1) Foo;` (or + `%feature("php:allowdynamicproperties", 1)` to enable it for + all wrapped classes). Unknown features are ignored, so you can add + it unconditionally and it'll work with older SWIG too. + + *** POTENTIAL INCOMPATIBILITY *** + +2022-09-19: wsfulton + #1484 Fixes for class inheritance with the same name in different namespaces + such as: + + namespace A { class Bar {}; } + namespace B { template class Bar : public A::Bar {}; } + +2022-09-19: wsfulton + #2316 Remove swig.spec file and srcrpm makefile target. These are very out of date + and don't seem to be used by RPM based Linux distributions which have their + own version of swig.spec. + +2022-09-17: wsfulton + [Go, Guile, Racket, Scilab] Add throws typemaps for std::string so that thrown + string exception messages can be seen. + +2022-09-17: wsfulton + [Racket] Add throws typemaps for char * so that thrown string exception + messages can be seen from Racket. + +2022-09-17: wsfulton + [Javascript, Octave, R] Improve exceptions for %catches and exception + specifications for native types. String exception messages are shown as + the exception message instead of just the type of the exception. + +2022-09-17: wsfulton + Add missing typecheck typemaps for std::auto_ptr and std::unique_ptr to + fix overloading when using these types. + +2022-09-17: wsfulton + [Guile] Add error checking to SWIGTYPE and SWIGTYPE & in typemaps to prevent + seg faults when passing #nil to these parameter types. + +2022-09-16: wsfulton + #999 Provide SWIGTYPE MOVE typemaps in swigmove.i for implementing full + move semantics when passing parameters by value. + +2022-08-31: wsfulton + #999 Improve move semantics when using rvalue references. + The SWIGTYPE && input typemaps now assume the object has been moved. + + These typemaps have been changed assuming that after the function call, + the rvalue reference parameter has been moved. The parameter's proxy class + that owns the C++ object thus has the underlying pointer set to null + so that the (moved from, but still valid) C++ object cannot be used again + and the object is additionally deleted. + + *** POTENTIAL INCOMPATIBILITY *** + +2022-08-28: wsfulton + [Octave] SWIG now marshals a C/C++ NULL pointer into the null matrix, []. + SWIG has always marshalled the null matrix into a NULL pointer; this remains + and now we have consistency in representing a NULL pointer. + +2022-08-26: wsfulton + [Racket] SWIG now marshals a C/C++ NULL pointer into a null value by calling + scheme_make_null(), so that scheme's null? is true for a NULL C/C++ pointer value. + +2022-08-18: wsfulton + [Racket] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + +2022-08-13: wsfulton + [Guile] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + +2022-08-11: wsfulton + [Lua] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + +2022-08-05: wsfulton + [D] Fix occasional undefined behaviour with inheritance hierarchies, particularly + when using virtual inheritance as the pointers weren't correctly upcast from derived + class to base class when stored in the base's proxy class. + +2022-08-05: wsfulton + [D] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + +2022-08-03: wsfulton + [Javascript] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + +2022-08-02: wsfulton + [Octave] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + +2022-08-01: wsfulton + [Python] Add initialisers for additional members in PyHeapTypeObject + (builtin mode) for Python-3.11 - _ht_tpname, _spec_cache. + +2022-07-30: wsfulton + C++20 has deprecated std::basic_string<>::reserve() and the C++11 method + std::basic_string<>::shrink_to_fit() is a replacement that can be used. + std_string.i and std_wstring.i provided wrappers for reserve with the following + template instantiations: + + %template(string) std::basic_string; + %template(wstring) std::basic_string; + + The reserve method is no longer wrapped, however the shrink_to_fit() method + can be used as an alternative from the target language (the generated wrappers + call reserve() instead if C++<=20). + + Note that std::basic_string<>::reserve(size_t n) is still wrapped unchanged. + + *** POTENTIAL INCOMPATIBILITY *** + +2022-07-30: wsfulton + [Tcl] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + +2022-07-27: ZackerySpytz, olly + #1678 Support parsing C++20 templated lambdas. + +2022-07-27: ZackerySpytz, olly + #1622 Add support for the C++20 spaceship operator (<=>). + +2022-07-26: olly + [Tcl] https://sourceforge.net/p/swig/bugs/977/ + Fix handling of long long on 32-bit platforms. This fix raises + SWIG's minimum supported Tcl version to 8.4.0 (which was released + just under 20 years ago). + +2022-07-26: olly + Fix incorrect operator precedence in preprocessor expressions. + +2022-07-25: olly + Support for C++14 binary integer literals in preprocessor expressions. + +2022-07-20: wsfulton + [C#, Java] Ensure the order of interfaces generated in proxy interfaces for the + %interface family of macros is the same as that parsed from the bases in C++. + +2022-07-20: jicks, Ingener74, olly + #422 [Python] Fix mishandling of a Python class inheriting from + multiple SWIG-wrapped director classes. + +2022-07-19: wsfulton + #692 [C#, Java, Perl, Python, Ruby] std::unique_ptr and std::auto_ptr typemaps + provided for inputs types in std_unique_ptr.i and std_auto_ptr.i. + + Now these smart pointers can be used as input parameters to functions. A proxy + class instance transfers memory ownership of the underlying C++ object from the + proxy class to a smart pointer instance passed to the wrapped function. + +2022-07-19: jschueller + [Python] #2314 Drop support for Python 3.2. + +2022-07-19: olly + Remove remaining support code for classic macos, which has not been + supported by Apple for over 20 years now. + +2022-07-12: wsfulton + #999 Performance optimisation for parameters passed by value that are C++11 movable. + The C++ wrappers create a temporary variable for a parameter to be passed to a + function. This is initially default constructed and then copy assigned from the + instance being passed in from the target language. This is unchanged, however, + when the temporary variable is passed to the wrapped function, it is now done using + std::move. If the type is move constructible, the move constructor will be used + instead of the copy constructor. + +2022-07-12: wsfulton + [Perl] Add std::auto_ptr support in std_auto_ptr.i library file. + +2022-07-12: erezgeva + [Perl] Add std::unique_ptr support in std_unique_ptr.i library file. + +2022-07-07: jmarrec + #1158 #2286 Add basic support for C++11 attributes. These are now + crudely ignored by SWIG's parser's tokeniser, which is better that + failing with a parse error. + +2022-07-05: ianlancetaylor + [Go] #2245 Handle NULL pointers for string* conversions. + Rearrange generation of director methods and rename + receiver argument from p to swig_p. + +2022-07-03: wsfulton + #999 Performance optimisation for directors for classes passed by value. The directorin + typemaps in the director methods now use std::move on the input parameter when + copying the object from the stack to the heap prior to the callback into the target + language, thereby taking advantage of move semantics if available. + +2022-07-02: wsfulton + #1722 [C#, Java, Python, Ruby] Add std::unique_ptr support. Ported from std::auto_ptr. + Use the %unique_ptr(T) macro as follows for usage std::unique_ptr. For example, for + a class called Klass: + + %include "std_unique_ptr.i" + %unique_ptr(Klass) + + Support is currently limited to only returning a std::unique_ptr from a function. + +2022-06-29: wsfulton + #999 #1044 Enhance SWIGTYPE "out" typemaps to use std::move when copying + objects, thereby making use of move semantics when wrapping a function returning + by value if the returned type supports move semantics. + + Wrapping functions that return move only types 'by value' now work out the box + without having to provide custom typemaps. + + The implementation removed all casts in the "out" typemaps to allow the compiler to + appropriately choose calling a move constructor, where possible, otherwise a copy + constructor. The implementation also required modifying SwigValueWrapper to + change a cast operator from: + + SwigValueWrapper::operator T&() const; + + to + + #if __cplusplus >=201103L + SwigValueWrapper::operator T&&() const; + #else + SwigValueWrapper::operator T&() const; + #endif + + This is not backwards compatible for C++11 and later when using the valuewrapper feature + if a cast is explicitly being made in user supplied "out" typemaps. Suggested change + in custom "out" typemaps for C++11 and later code: + + 1. Try remove the cast altogether to let the compiler use an appropriate implicit cast. + 2. Change the cast, for example, from static_cast to static_cast, using the + __cplusplus macro if all versions of C++ need to be supported. + + *** POTENTIAL INCOMPATIBILITY *** + +2022-06-15: wsfulton + #2039 Add move assignment operator to SwigValueWrapper used by the + valuewrapper feature. + +2022-06-04: sethrj + Enhance $typemap to support typemap attributes. + + $typemap(method:attribute, typepattern) + + For example: + + %typemap(cstype, out="object") XClass "XClass" + %typemap(cscode) BarClass %{ + $typemap(cstype:out, XClass) bar() { + return null; + } + + which expands to + + object bar() { + return null; + } + +2022-05-30: wsfulton + [C#, D] Add new special variable expansion: $imfuncname. + Expands to the function name called in the intermediary class. + +2022-05-30: LindleyF + [Java] #2042 Add new special variable expansion: $imfuncname. + Expands to the function name called in the intermediary class. + +2022-05-28: jkuebart + [Java] On some versions of Android, specifically Android 6, + detaching the current thread from the JVM after every invocation + causes a memory leak. + + Offer SWIG_JAVA_DETACH_ON_THREAD_END to configure a behaviour + where the JVM is only detached in the thread destructor. + + See https://developer.android.com/training/articles/perf-jni#threads. + +2022-05-27: xypron + [Python] #2277 Define PY_SSIZE_T_CLEAN macro before #include "Python.h" as + recommended in Python 3.7 and later. + + To avoid this macro definition, add the following to your interface file so + that SWIG_NO_PY_SSIZE_T_CLEAN is defined at the beginning of the C++ wrappers: + + %begin %{ + #define SWIG_NO_PY_SSIZE_T_CLEAN + %} + +2022-05-26: rokups + [C#] #1323 Modify SwigDerivedClassHasMethod for a more efficient director + implementation when calling virtual methods that are not overridden. + +2022-05-15: erezgeva, eiselekd + [Lua, Perl, Octave, PHP, Tcl] #2275 #2276 #2283 Add argcargv.i library containing + (int ARGC, char **ARGV) multi-argument typemaps. + + Document this library in Typemaps.html. + +2022-05-07: KrisThielemans + [Python] Fix "too many initializers for 'PyHeapTypeObject'" errors + using PyPy 3.8 and later. + +2022-05-04: wsfulton + [C#] Add C# wchar_t * director typemaps + +2022-04-20: cminyard + Fix an issue where newlines were not properly generated + for godirectorin typemaps. If you have a virtual function + not assigned to zero, in some cases it won't generate a + newline and you will see errors: + example.go:1508:3: expected ';', found swig_r + when compiling the go code. + + Also add an example of using goin and godirectorin and add + a test for this situation. + +2022-04-29: jason-daly, JerryJoyce, wsfulton + [C#] #1233 Add wchar_t * and std::wstring Unicode string support on Linux. + +2022-04-11: robinst + #2257 Fix new Ruby 3.2 warning "undefining the allocator of T_DATA + class swig_runtime_data". + +2022-04-07: olly + #1750 SWIG now recognises and ignores Doxygen group commands `@{` and `@}`. + +2022-04-06: wsfulton + ./configure now enables C++11 and later C++ standards testing by default (when + running: 'make check'). + + The options to control this testing are the same: + + ./configure --enable-cpp11-testing + ./configure --disable-cpp11-testing + + But the former is now the default and the latter can be used to turn off C++11 and + later C++ standards testing. + +2022-04-06: wsfulton + [Python] #1635 The "autodoc" feature no longer overrides Doxygen comments + in the generated docstring. + + If a "docstring" feature is present it will still override a Doxygen comment. + If the "autodoc" feature is also present, the combined "autodoc" and "docstring" + will override the Doxygen comment. If no "docstring" is present then the + "autodoc" feature will not be generated when there is a Doxygen comment. + + This way the "autodoc" feature can be specified and used to provide documentation + for 'missing' Doxygen comments. + + *** POTENTIAL INCOMPATIBILITY *** + +2022-04-01: olly + Remove undocumented and non-functional -browse command line option. + +2022-03-26: eltoder + [Python] #1684 Use different capsule names with and without -builtin + + Types generated with and without -builtin are not compatible. Mixing + them in a common type list leads to crashes. Avoid this by using + different capsule names: "type_pointer_capsule" without -builtin and + "type_pointer_capsule_builtin" with. + +2022-03-25: wsfulton + The debug command line options that display parse tree nodes + (-debug-module, -debug-top, -debug-symtabs) now display previously hidden + linked list pointers which are useful for debugging parse trees. + + Added new command line option -debug-quiet. This suppresses the display + of most linked list pointers and symbol table pointers in the parse tree nodes. + + The keys in the parse tree node are now shown in alphabetical order. + +2022-03-24: wsfulton + #2244 Fix using declaration in derived class bugs when all the base + class's overloaded methods were overridden in the derived class - + fixes "multiply defined" errors. + +2022-03-23: wsfulton + [Python] #1779 The -py3 option is deprecated and now has no effect on the + code generated. Use of this option results in a deprecated warning. + The related SWIGPYTHON_PY3 macro that this option defined is no longer generated. + + Note that %pythonnondynamic feature generates a metaclass that works on both + Python 2 and Python 3. + +2022-03-21: wsfulton + [Python] #1779 pyabc.i for abstract base classes now supports versions of + Python prior to 3.3 by using the collection module for these older versions. + Python-3.3 and later continue to use the collections.abc module. + The -py3 option no longer has any effect on the %pythonabc feature. + +2022-03-21: jschueller, jim-easterbrook, wsfulton + [Python] #2137 C++ static member functions no longer generate a "flattened" + name in the Python module. For example: + + s = example.Spam() + s.foo() # Spam::foo() via an instance + example.Spam.foo() # Spam::foo() using class method + example.Spam_foo() # Spam::foo() "flattened" name + + The "flattened" name is no longer generated, but can be generated + by using the new -flatstaticmethod option. + + *** POTENTIAL INCOMPATIBILITY *** + +2022-03-18: ianlancetaylor + [Go] #337 Implement %extend base methods in child classes. + +2022-03-17: olly + [Python] #1779 SWIG's Python test-suite and examples are now + run with Python 3 by default. To run them with Python 2, set + PY2 to a non-empty value, e.g.: + + make check-python-test-suite PY2=1 + +2022-03-16: olly + [Go] #683 -intgosize is now optional - if not specified the + generated C/C++ wrapper code will use ptrdiff_t for intgo and + size_t for uintgo. + +2022-03-15: ianlancetaylor + [Go] Add typemaps for std::string*. + +2022-03-15: ianlancetaylor + [Go] Don't convert arrays to pointers if there is a "gotype" + typemap entry. + +2022-03-15: ianlancetaylor + [Go] Add documentation note about Go and C++ exceptions. + +2022-03-12: wsfulton + #1524 %interface family of macros no longer contain the getter/setter + methods for wrapping variables. The interface only contains + virtual and non-virtual instance methods, that is, no static methods. + Enums are also no longer added to the interface (affects Java only where + they were missing from the proxy class, C# never had them in the interface). + + *** POTENTIAL INCOMPATIBILITY *** + +2022-03-12: wsfulton + #1277 Fixes for the family of %interface macros, %interface, + %interface_impl and %interface_custom fixes for overloaded methods + in an inheritance chain. + + When C++ methods are not able to be overloaded in a derived class, + such as when they differ by just const, or the target language + parameters types are identical even when the C++ parameter types + are different, SWIG will ignore one of the overloaded methods with + a warning. A %ignore is required to explicitly ignore one of the + overloaded methods to avoid the warning message. Methods added + in the derived classes due to one of the %interface macros are now + similarly ignored/not added to the derived class. + + The methods added to the derived classes can now also be modified + via %feature and %rename. + +2022-03-08: ianlancetaylor + [Go] Treat a nil argument as a NULL pointer. + +2022-03-08: ianlancetaylor + [Go] Add documentation notes about thread local storage. + +2022-03-08: olly + #1006 SWIG now copes with an interface filename specified on the + command line which contains a closing parenthesis `)`, and more + generally with attributes to `%include` and `%import` which + are quoted and contain parentheses. + +2022-03-07: Omar Medina + [Tcl] https://sourceforge.net/p/swig/bugs/1290/ + Fix SWIG_AsWCharPtrAndSize() to actually assign to result + variable. It looks like SWIG/Tcl wide character handling is + currently fundamentally broken except on systems which use wide + characters as the system encoding, but this should fix wrapping + functions which take a wide string as a parameter on Microsoft + Windows. + +2022-03-07: olly + [Javascript] #682 Fix handling of functions which take void*. + +2022-03-06: olly + SWIG should now reliably exit with status 0 if the run was + successful and status 1 if there was an error (or a warning and + -Werror was in effect). + + Previously in some situations SWIG would try to exit with the + status set to the number of errors encountered, but that's + problematic - for example if there were 256 errors this would + result in exit status 0 on most platforms. Also some error + statuses have special meanings e.g. those defined by . + Also SWIG/Javascript tried to exit with status -1 in a few places + (which typically results in exit status 255). + +2022-03-05: wsfulton + #1441 Fix using declaration in derived class incorrectly introducing a method + from a base class when the using declaration is declared before the method + declaration. Problem occurred when within a namespace and the parameter types + in the method signatures were not fully qualified. +2022-03-05: ianlancetaylor + [Go] Treat non-const references as pointers. + +2022-03-05: ianlancetaylor + In SWIG Go testsuite, fail test if "go build" fails. + +2022-03-03: olly + #1901 #2223 SWIG should now always exit cleanly if memory + allocation fails, including removing any output files created + during the current run. + + Previously most places in the code didn't check for a NULL return + from malloc()/realloc()/calloc() at all, typically resulting in + undefined behaviour; some places used assert() to check for a NULL + return (which is a misuse of assert() and such checks disappear if + built with NDEBUG defined leaving us back with undefined + behaviour). + +2022-03-03: olly + #891 Report errors for typemap attributes without a value + (previously SWIG segfaulted) and for typemap types with a value + (previously the value was quietly ignored). + + The old way of specifying a language name in the typemap attributes + is no longer supported (it has been deprecated for 16 years). + +2022-03-02: geographika, wsfulton + [Python] #1951 Add Python variable annotations support. + + Both function annotations and variable annotations are turned on using the + "python:annotations" feature. Example: + + %feature("python:annotations", "c"); + + struct V { + float val; + }; + + The generated code contains a variable annotation containing the C float type: + + class V(object): + val: "float" = property(_example.V_val_get, _example.V_val_set) + ... + + Python 3.5 and earlier do not support variable annotations, so variable + annotations can be turned off with a "python:annotations:novar" feature flag. + Example turning on function annotations but not variable annotations globally: + + %feature("python:annotations", "c"); + %feature("python:annotations:novar"); + + or via the command line: + + -features python:annotations=c,python:annotations:novar + + *** POTENTIAL INCOMPATIBILITY *** + +2022-02-27: wsfulton + [Python] #735 #1561 Function annotations containing C/C++ types are no longer + generated when using the -py3 option. Function annotations support has been + moved to a feature to provide finer grained control. It can be turned on + globally by adding: + + %feature("python:annotations", "c"); + + or by using the command line argument: + + -features python:annotations=c + + Also see entry dated 2022-03-02, regarding variable annotations. + + *** POTENTIAL INCOMPATIBILITY *** + +2022-02-26: wsfulton + #655 #1840 Add new warning WARN_LANG_USING_NAME_DIFFERENT to warn when a + method introduced by a using declaration in a derived class cannot + be used due to a conflict in names. + +2022-02-24: olly + #1465 An invalid preprocessor expression is reported as a pair of + warnings with the second giving a more detailed message from the + expression evaluator. Previously SWIG prefixed the second message + with "Error:" - that was confusing as it's actually only a warning + by default so we've now dropped this prefix. + + Before: + + x.i:1: Warning 202: Could not evaluate expression '1.2' + x.i:1: Warning 202: Error: 'Floating point constant in preprocessor expression' + + Now: + + x.i:1: Warning 202: Could not evaluate expression '1.2' + x.i:1: Warning 202: Floating point constant in preprocessor expression + +2022-02-23: olly + #1384 Fix a preprocessor expression evaluation bug. A + subexpression in parentheses lost its string/int type flag and + instead used whatever type was left in the stack entry from + previous use. In practice we mostly got away with this because + most preprocessor expressions are integer, but it could have + resulted in a preprocessor expression incorrectly evaluating as + zero. If -Wextra was in use you got a warning: + + Warning 202: Error: 'Can't mix strings and integers in expression' + +2022-02-21: davidcl + [Scilab] Improve 5.5.2, 6.0.0 and 6.1.0 support. + + For Scilab 5, long names are reduced to small names preserving the + class prefix and accessor suffix (get or set). + + For Scilab 6, long names with the class prefix and accessor suffix + should be used on the user code. + + The `-targetversion` option has been removed as the generated code + now detects the Scilab version in loader.sce or builder.sce. + + *** POTENTIAL INCOMPATIBILITY *** + +2022-02-20: wsfulton + Fix %warnfilter warning suppress for warning 315 SWIGWARN_PARSE_USING_UNDEF. + +2022-02-17: olly + [PHP] https://sourceforge.net/p/swig/bugs/1211/ + Fix to call cleanup code in exception situations and not to invoke + the freearg typemap twice in certain situations. + +2022-02-15: olly + #300 #368 Improve parser handling of % followed immediately by + an identifier. If it's not a recognised directive the scanner + now emits MODULO and then rescans what follows, and if the parser + then gives a syntax error we report it as an unknown directive. + This means that `a%b` is now allowed in an expression, and that + things like `%std::vector` now give an error rather + than being quietly ignored. + +2022-02-11: adr26 + [Python] #2154 Fix memory leak. + + SWIG python objects were being freed after the corresponding SWIG + module information was destroyed in Python 3, causing leaks when as + a result the object destructor could not be invoked. To prevent this + misordering, SWIG python objects now obtain a reference to the + Python capsule wrapping the module information, so that the module + information is correctly destroyed after all SWIG python objects + have been freed (and corresponding destructors invoked). + +2022-02-10: olly + [Tcl] https://sourceforge.net/p/swig/bugs/1207/ + https://sourceforge.net/p/swig/bugs/1213/ + + Fix Tcl generic input typemap for std::vector. + +2022-02-07: sethrj + #2196 Add alternative syntax for specifying fragments in typemaps. + + New syntax: + %typemap("in", fragment="frag1", fragment="frag2", fragment="frag3") {...} + which is equivalent to: + %typemap(in, fragment="frag1,frag2,frag3") {...} + + +2022-02-07: olly + #1806 Remove support for the "command" encoder, which was mostly + intended for use in `%rename` - most uses can be achieved using + the "regex" encoder, so we recommend using that instead. + + The "command" encoder suffers from a number of issues - as the + documentation for it admitted, "[it] is extremely slow compared to + all the other [encoders] as it involves spawning a separate process + and using it for many declarations is not recommended" and that it + "should generally be avoided because of performance + considerations". + + But it's also not portable. The design assumes that `/bin/sh` + supports `<<<` but that's a bash-specific feature so it doesn't + work on platforms where `/bin/sh` is not bash - it fails on + Debian, Ubuntu and probably some other Linux distros, plus most + non-Linux platforms. Microsoft Windows doesn't even have a + /bin/sh as standard. + + Finally, no escaping of the passed string is done, so it has + potential security issues (though at least with %rename the input + is limited to valid C/C++ symbol names). + +2022-02-06: olly + #2193 -DFOO on the SWIG command line now sets FOO to 1 for + consistency with C/C++ compiler preprocessors. Previously + SWIG set FOO to an empty value. + + Existing invocations of SWIG with `-DFOO` where the empty value + matters can be updated to `-DFOO=` which should work with both + old and new releases of SWIG. + + *** POTENTIAL INCOMPATIBILITY *** + +2022-02-06: sethrj + #2194 Classes that are non-assignable due to const data or const + reference members are now automatically detected. + +2022-02-04: friedrichatgc + [Octave] #1672 Fix for isobject for Octave 4.4 - 6.0. + +2022-02-03: olly + [C#] #283 #998 Fix memory leak in directorin typemap for + std::string. + +2022-02-03: olly + [Python] #967 Make `self` parameter available to user typemaps. + +2022-02-03: teythoon + [Python] #801 Fix -Wunused-parameter warnings with builtin, + +2022-02-03: teythoon + #801 Fix -Wstrict-prototypes warnings in generated pointer + functions. + +2022-02-03: olly + #660 https://sourceforge.net/p/swig/bugs/1081/ + Default parameter values containing method calls are now parsed and + handled - e.g. `x->foo(3,4)` and `y.z()`. + +2022-02-02: olly + [Ruby] https://sourceforge.net/p/swig/bugs/1136/ Fix remove of prefix + from method name to only remove it at the start. + +2022-02-01: olly + #231 Handle returning an object by reference in a C++ trailing + return type. + +2022-02-01: davidcl + [Scilab] #745 use SWIG__Init() as a C module init function. + +2022-02-01: olly + [OCaml] #2083 Fix to work when CAML_SAFE_STRING is on, which it is + by default in recent Ocaml releases. + +2022-01-31: mreeez + https://sourceforge.net/p/swig/bugs/1147/ + Fix copyToR() generated for a struct in a namespace. + +2022-01-29: fschlimb + #655 Better handling of using declarations. + +2022-01-29: dontpanic92 + [Go] #676 Fix code generated for a C++ class with a non-capitalised + name. + +2022-01-26: trex58 + #1919 #1921 #1923 Various fixes for AIX portability. + +2022-01-26: olly + #1935 Don't crash on an unclosed HTML tag in a doxygen comment + when -doxygen is specified. + +2022-01-25: olly + Constant expressions now support member access with `.` such as + `foo.bar`. Previous this only worked in a case like `x->foo.bar`. + +2022-01-25: olly + #2091 Support most cases of `sizeof` applied to an expression + in constant expressions. Previously there was only support for + `sizeof()` and expressions which syntactically look like a + type (such as `sizeof(foo)`). + +2022-01-25: olly + #80 #635 https://sourceforge.net/p/swig/bugs/1139/ + Add support for parsing common cases of `<` and `>` comparisons + in constant expressions. Adding full support for these seems hard + to do without introducing conflicts into the parser grammar, but in + fact all reported cases have had parentheses around the comparison + and we can support that with a few restrictions on the left side of + `<`. + +2022-01-25: wsfulton + New warning 327 for extern templates, eg: + + extern template class std::vector; + extern template void Func(); + + results in warning + + example.i:3: Warning 327: Extern template ignored. + example.i:4: Warning 327: Extern template ignored. + + Extern template classes previously resulted in warning 320. + +2022-01-24: romintomasetti + #2131 #2157 C++11 extern function template parsing error fix. + +2022-01-21: wsfulton + #2120 #2138 Replace legacy PCRE dependency with PCRE2. + This requires changes for building SWIG from source. See updated + html documentation in Preface.html and Windows.html. Updated + instructions are also shown when running ./configure if PCRE2 is not + found. Note that debian based systems can install PCRE2 using: + + apt install libpcre2-dev + + Note that https://github.com/swig/swig/wiki/Getting-Started also has + updated information for building from source. + +2022-01-19: olly + [PHP] #2027 Automatically generate PHP type declarations for PHP 8. + The generate code still compiles for PHP 7.x, but without type + declarations since PHP 7.x has much more limited type declaration + support. + +2022-01-18: olly + [Perl] #1629 Perl 5.8.0 is now the oldest version we aim to support. + +2022-01-14: wsfulton + [Python] Fix %callback and specifying the callback function as a + static member function using Python staticmethod syntax, such as + Klass.memberfunction instead of Klass_memberfunction when using + -builtin and -fastproxy. + +2022-01-11: wsfulton + [Python] Accept keyword arguments accessing static member functions when + using -builtin and kwargs feature and Python class staticmethod syntax. + The missing keyword argument support was only when using the + class staticmethod syntax, such as Klass.memberfunction, and not when + using the flat static method syntax, such as Klass_memberfunction. + +2022-01-04: juierror + [Go] #2045 Add support for std::array in std_array.i. + +2021-12-18: olly + [PHP] Add PHP keyword 'readonly' (added in 8.1) to the list SWIG + knows to automatically rename. This keyword is special in that PHP + allows it to be used as a function (or method) name. + +2021-12-07: vstinner + [Python] #2116 Python 3.11 support: use Py_SET_TYPE() + +2021-12-05: rwf1 + [Octave] #2020 #1893 Add support for Octave 6 up to and including 6.4. + Also add support for compiling with -Bsymbolic which is used by default + by mkoctfile. + +2021-12-02: jsenn + [Python] #2102 Fixed crashes when using embedded Python interpreters. + +2021-11-12: wsfulton + [Javascript] v8 and node only. Fix mismatched new char[] and free() + when wrapping C code char arrays. Now calloc is now used instead of + new char[] in SWIG_AsCharPtrAndSize. + +2021-10-03: ajrh1 + [Perl] #2074: Avoid -Wmisleading-indentation in generated code + when using gcc11. + +2021-10-03: jschueller + [CMake] #2065: Add option to enable or disable PCRE support. + +2021-09-16: ianlancetaylor + [Go] Improved _cgo_panic implementation. + +2021-09-16: ianlancetaylor + [Go] Don't use crosscall2 for panicking. Instead rely on documented + and exported interfaces. + +2021-09-14: ianlancetaylor + [Go] Remove -no-cgo option (long unsupported in Go) + +2021-05-04: olly + [PHP] #2014 Throw PHP exceptions instead of using PHP errors + + PHP exceptions can be caught and handled if desired, but if they + aren't caught then PHP exits in much the same way as it does for a + PHP error. + + In particular this means parameter type errors and some other cases + in SWIG-generated wrappers now throw a PHP exception, which matches + how PHP's native parameter handling deals with similar situations. + + `SWIG_ErrorCode()`, `SWIG_ErrorMsg()`, `SWIG_FAIL()` and `goto thrown;` + are no longer supported (these are really all internal implementation + details and none are documented aside from brief mentions in CHANGES + for the first three). I wasn't able to find any uses in user interface + files at least in FOSS code via code search tools. + + If you are using these: + + Use `SWIG_PHP_Error(code,msg);` instead of `SWIG_ErrorCode(code); + SWIG_ErrorMsg(msg);` (which will throw a PHP exception in SWIG >= 4.1 + and do the same as the individual calls in older SWIG). + + `SWIG_FAIL();` and `goto thrown;` can typically be replaced with + `SWIG_fail;`. This will probably also work with older SWIG, but + please test with your wrappers if this is important to you. + + *** POTENTIAL INCOMPATIBILITY *** + +2021-05-17: adr26 + [Python] #1985 Fix memory leaks: + + 1. Python object references were being incorrectly retained by + SwigPyClientData, causing swig_varlink_dealloc() never to run / free + memory. SwigPyClientData_New() / SwigPyClientData_Del() were updated + to fix the object reference counting, causing swig_varlink_dealloc() + to run and the memory swig_varlink owns to be freed. + + 2. SwigPyClientData itself was not freed by SwigPyClientData_Del(), + causing another heap leak. The required free() was added to + SwigPyClientData_Del() + + 3. Fix reference counting/leak of python cached type query + + 4. Fix reference counting/leak of SwigPyObject dict (-builtin) + + 5. Python object reference counting fixes for out-of-memory + scenarios were added to: SWIG_Python_RaiseOrModifyTypeError(), + SWIG_Python_AppendOutput(), SwigPyClientData_New(), + SwigPyObject_get___dict__() and SwigPyObject_format() + + 6. Add error handling for PyModule_AddObject() to + SWIG_Python_SetModule() (failure could be caused by OOM or a name + clash caused by malicious code) + +2021-05-13: olly + [UFFI] #2009 Remove code for Common Lisp UFFI. We dropped support + for it in SWIG 4.0.0 and nobody has stepped forward to revive it in + over 2 years. + +2021-05-13: olly + [S-EXP] #2009 Remove code for Common Lisp S-Exp. We dropped + support for it in SWIG 4.0.0 and nobody has stepped forward to + revive it in over 2 years. + +2021-05-13: olly + [Pike] #2009 Remove code for Pike. We dropped support for it in + SWIG 4.0.0 and nobody has stepped forward to revive it in over 2 + years. + +2021-05-13: olly + [Modula3] #2009 Remove code for Modula3. We dropped support for it + in SWIG 4.0.0 and nobody has stepped forward to revive it in over 2 + years. + +2021-05-13: olly + [CLISP] #2009 Remove code for GNU Common Lisp. We dropped support + for it in SWIG 4.0.0 and nobody has stepped forward to revive it in + over 2 years. + +2021-05-13: olly + [Chicken] #2009 Remove code for Chicken. We dropped support for it + in SWIG 4.0.0 and nobody has stepped forward to revive it in over 2 + years. + +2021-05-13: olly + [Allegrocl] #2009 Remove code for Allegro Common Lisp. We dropped + support for it in SWIG 4.0.0 and nobody has stepped forward to + revive it in over 2 years. + +2021-05-04: olly + [PHP] #1982 #1457 https://sourceforge.net/p/swig/bugs/1339/ + SWIG now only use PHP's C API to implement its wrappers, and no + longer generates PHP code to define classes. The wrappers should + be almost entirely compatible with those generated before, but + faster and without some previously hard-to-fix bugs. + + The main notable difference is SWIG no longer generates a .php + wrapper at all by default (only if %pragma(php) code=... or + %pragma(php) include=... are specified in the interface file). + This also means you need to load the module via extension=... + in php.ini, rather than letting the dl() in the generated + .php wrapper load it (but dl() has only worked for command-line + PHP for some years now). + + *** POTENTIAL INCOMPATIBILITY *** + +2021-04-30: olly + #1984 Remove support for $source and $target. + These were officially deprecated in 2001, and attempts to use them have + resulted in a warning (including a pointer to what to update them to) + for most if not all of that time. + +2021-04-27: wsfulton + #1987 [Java] Fix %interface family of macros for returning by const + pointer reference. + +2021-04-19: olly + Fix use of uninitialised variable in the generated code for an + empty typecheck typemap, such as the dummy one we include for + std::initializer_list. + +2021-04-12: olly + #1777 [Python] Specifying -py3 now generates a check for Python + version >= 3.0. + +2021-03-26: olly + [PHP] Add PHP keywords 'fn' (added in 7.4) and 'match' (added in + 8.0) to the list SWIG knows to automatically rename. + +2021-03-23: wsfulton + #1942 [Python] Fix compilation error in wrappers when using -builtin + and wrapping varargs in constructors. + +2021-03-22: goto40 + #1977 Fix handling of template template parameters. + +2021-03-21: olly + #1929, #1978 [PHP] Add support for PHP 8. + +2021-03-19: wsfulton + #1610 Remove -ansi from default compilation flags. + +2021-03-19: dot-asm + #1934 [Java] Clean up typemaps for long long arrays. + +2021-03-19: olly + #1527 [PHP] Improve PHP object creation in directorin case. + Reportedly the code we were using in this case gave segfaults in + PHP 7.2 and later - we've been unable to reproduce these, but the + new approach is also simpler and should be bit faster too. + +2021-03-18: olly + #1655 [PHP] Fix char* typecheck typemap to accept PHP Null like the + corresponding in typemap does. + +2021-03-18: olly + #1900, #1905 [PHP] Fix wrapping of overloaded directed methods with + non-void return. + +2021-03-11: murillo128 + #1498 [Javascript] Support type conversion. + +2021-03-06: nshmyrev + #872 [Javascript] Various typemap issues in arrays_javascript.i fixed. + +2021-03-03: vaughamhong + #577 [Javascript] Implemented SetModule/GetModule for JSC to allow type sharing + across modules. + +2021-03-01: xantares, Oliver Buchtala, geographika + #1040 Add support for building SWIG with CMake. See documentation in Windows.html. + +2021-03-01: vadz + #1952 Fix incorrect warning "Unknown Doxygen command: ." + +2021-02-28: p2k + #969 [Javascript] v8/node - prevent crash calling a constructor without new keyword. + +2021-02-28: alecmev + #405 #1121 [Javascript] Fix OUTPUT typemaps on methods that don't return void. + The output value is appended to the return value. + +2021-02-26: murillo128, wsfulton + #1269 [Javascript] Fix handling of large positive unsigned long and + unsigned long long values. + +2021-02-24: tomleavy, yegorich, tungntpham + #1746 [Javascript] Add support for Node v12, v14 and v16. + SWIG support for Node is now for v6 and later only. + +2020-02-09: ZackerySpytz + #1872 Fix typos in attribute2ref macros. + +2020-10-10: wsfulton + [Javascript] Fix so that ccomplex.i interface to file can be used. + +2020-10-10: wsfulton + #252 complex can now be used as a C identifier and doesn't give a syntax error. + +2020-10-10: lpsinger + #1770 Correct C complex support. + _Complex is now parsed as a keyword rather than complex as per the C99 standard. + The complex macro is available in the ccomplex.i library file along with other + complex number handling provided by the complex.h header. + +2020-10-07: ZackerySpytz + [Python] #1812 Fix the error handling for the PyObject_GetBuffer() calls in + pybuffer.i. + +2020-10-07: treitmayr + #1824 Add missing space in director method declaration returning + const pointer. + +2020-10-07: adelva1984 + #1859 Remove all (two) exceptions from SWIG executable. + +2020-09-25: wsfulton + [C#, Java] #1874 Add ability to change the modifiers for the interface + generated when using the %interface macros. + + For C# use the 'csinterfacemodifiers' typemap. + For Java use the 'javainterfacemodifiers' typemap. + + For example: + + %typemap(csinterfacemodifiers) X "internal interface" + +2020-09-24: geefr + [C#] #1868 Fix wchar_t* csvarout typemap for member variable wrappers. + +2020-08-28: wsfulton + [Java] #1862 Fix crashes in swig_connect_director during director class construction + when using the director class from multiple threads - a race condition initialising + block scope static variables. The fix is guaranteed when using C++11, but most + compilers also fix it when using C++03/C++98. + +2020-08-16: wsfulton + [Python] Add missing initializer for member '_heaptypeobject::ht_module' when using + -builtin to complete Python 3.9 support. + +2020-08-16: wsfulton + [Python] Remove PyEval_InitThreads() call for Python 3.7 and later as Python calls + it automatically now. This removes a deprecation warning when using Python 3.9. + +2020-08-15: wsfulton + [Python] All Python examples and tests are written to be Python 2 and Python 3 + compatible, removing the need for 2to3 to run the examples or test-suite. + +2020-08-13: wsfulton + [C#] Add support for void *VOID_INT_PTR for member variables. + +2020-07-29: chrisburr + #1843 [Python] Compilation error fix in SwigPyBuiltin_SetMetaType when using PyPy. + +2020-06-14: ZackerySpytz + #1642 #1809 Fix virtual comparison operators in director classes by removing an + incorrect space in the function name (for example, operator= = is now operator==). + Version 4.0.2 (8 Jun 2020) ========================== diff --git a/CHANGES.current b/CHANGES.current index 549a05c1e..d908e64da 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -4,1276 +4,6 @@ See the RELEASENOTES file for a summary of changes in each release. Issue # numbers mentioned below can be found on Github. For more details, add the issue number to the end of the URL: https://github.com/swig/swig/issues/ -Version 4.1.0 (24 Oct 2022) +Version 4.2.0 (in progress) =========================== -2022-10-24: wsfulton, AndLLA - [R] #2386 Fix problems in shared_ptr wrappers where the class names - were not consistent when using the shared_ptr template or the actual - underlying type. - -2022-10-24: wsfulton - [R] Add support for special variable replacement in the $typemap() - special variable macro for R specific typemaps (rtype, rtypecheck, - scoercein, scoereout). - -2022-10-24: wsfulton - [R] Polymorphism in the wrappers was only working for C++ classes, - now this works for C++ structs too. - -2022-10-19: olly - [Lua] #2126 Fix type resolution between multiple SWIG-wrapped - modules. - -2022-10-17: wsfulton - [R] #2385 Add support for std::vector>. - -2022-10-14: murillo128 - [Javascript] #2109 Tweak unsigned long and unsigned long long typemaps - to create a v8::Number instead of v8::Integer if the value exceeds - the size of v8::Integer. Note that the v8::Number value will be - imprecise if the value is > MAX_SAFE_INTEGER. - -2022-10-14: olly - [R] Arrange that destructors of local C++ objects in the wrapper - function get run on SWIG_fail (which calls Rf_error() which calls - longjmp()). - -2022-10-14: olly - [Lua] Arrange that destructors of local C++ objects in the wrapper - function get run on SWIG_fail (which calls lua_error() which calls - longjmp()). - -2022-10-13: wsfulton - [R] Add missing SWIGTYPE *const& typemaps for supporting pointers - by const reference. - -2022-10-10: wsfulton - #2160 Fix compile error when using templates with more than one template - parameter and used as an input parameter in a virtual method in a - director class (problem affecting most of the scripting languages). - -2022-10-10: treitmayr, wsfulton - [Python, Ruby] #1811 #1823 Fix invalid code generated in some cases when - returning a pointer or reference to a director-enabled class instance. - This previously only worked in very simple cases, now return types are - resolved to fix. A bug in template instantiations using pointers also - works now. - -2022-10-06: wsfulton - [CFFI] #1966 #2200 Remove code for Common Lisp CFFI. We dropped support - for it in SWIG 4.0.0 by disabling it as the first stage. This is the - final stage for complete removal as there has been no meaningful - progress to revive it to the status of experimental language. - -2022-10-06: olly - [Python] #2390 Remove deprecated and apparently useless defarg.swg - - The only documentation is in the file itself and describes a Python - wrapper around the C function defined here, but digging though the - git history this Python wrapper doesn't seem to have ever actually - been generated by SWIG. - - This file was also marked as deprecated in 2005. - -2022-10-06: wsfulton - [Java] #2048 Fix quoting for doxygen \image command to quote the output - file name generated into the html src attribute. - -2022-10-05: benjamin-sch - [Python] added an interpreter counter to fix deinitialization - issues if multiple subinterpreters are used - -2022-10-05: olly, wsfulton - #672 Add support for parsing C++11 final classes such as: - - class X final {}; - - This no longer gives a syntax error. - -2022-10-05: wsfulton - [OCaml] Fix %rename for enum items. Previously the rename had no effect. - -2022-10-05: olly - #1465 Report errors in preprocessor expressions by default - - Until now SWIG quietly ignored such errors unless -Wextra (or -Wall - which implies -Wextra) was passed, but this is unhelpful as it tends - to hide genuine problems. To illustrate this point, enabling this - warning by default revealed a typo in the preproc_defined.i - testcase in SWIG's own testsuite. - - If you really don't want to see this warning, you can suppress it - with command line option -w202 or by using this in your interface - file: - - %warnfilter(SWIGWARN_PP_EVALUATION); - - Both will work with older versions of SWIG too. - -2022-10-04: olly - #1050 Consistently define SWIG_VERSION both at SWIG-time and in - the generated wrapper. Best practice remains to check at SWIG-time - where possible because that results in smaller generated wrapper - sources. - - SWIGGO and SWIGJAVASCRIPT are now defined in the generated wrappers - to match behaviour for all other target languages. - - The undocumented SWIGVERSION macro is no longer defined. - -2022-09-29: olly - #2303 SWIG's internal hash tables now use a better hash function. - - The old hash function only considerd the last five characters - plus the least significant bit of the last-but-sixth character, - which as you might guess generated a lot of many-way collisions. - - This change seems to give about a 4% reduction in wallclock time - for processing li_std_list_wrap.i from the testsuite for Python. - The hash collision rate for this example drops from 39% to 0! - -2022-09-29: wsfulton - #2303 Type tables are now output in a fixed order whereas previously - the order may change with any minor input code change. This shouldn't - affect users except SWIG_TypePrettyName may output a different C/C++ - typedef to a type - it's used mostly for showing errors when the type - passed to a function is wrong. - -2022-09-29: olly - [PHP] Dynamic class properties are no longer supported by default. - - Historically PHP has supported dynamic class properties and SWIG - has implemented them too (because we implement the magic __get(), - __set() and __isset() methods we need to include explicit - handling). - - PHP 8.2 deprecates dynamic class properties - initially they'll - warn, and apparently they'll not work by default in PHP 9.0: - https://wiki.php.net/rfc/deprecate_dynamic_properties - - In PHP code dynamic properties can be enabled for a class by - marking that class with the attribute `#[AllowDynamicProperties]`. - - To follow this PHP change, in SWIG you now need to specify - `%feature("php:allowdynamicproperties", 1) Foo;` (or - `%feature("php:allowdynamicproperties", 1)` to enable it for - all wrapped classes). Unknown features are ignored, so you can add - it unconditionally and it'll work with older SWIG too. - - *** POTENTIAL INCOMPATIBILITY *** - -2022-09-19: wsfulton - #1484 Fixes for class inheritance with the same name in different namespaces - such as: - - namespace A { class Bar {}; } - namespace B { template class Bar : public A::Bar {}; } - -2022-09-19: wsfulton - #2316 Remove swig.spec file and srcrpm makefile target. These are very out of date - and don't seem to be used by RPM based Linux distributions which have their - own version of swig.spec. - -2022-09-17: wsfulton - [Go, Guile, Racket, Scilab] Add throws typemaps for std::string so that thrown - string exception messages can be seen. - -2022-09-17: wsfulton - [Racket] Add throws typemaps for char * so that thrown string exception - messages can be seen from Racket. - -2022-09-17: wsfulton - [Javascript, Octave, R] Improve exceptions for %catches and exception - specifications for native types. String exception messages are shown as - the exception message instead of just the type of the exception. - -2022-09-17: wsfulton - Add missing typecheck typemaps for std::auto_ptr and std::unique_ptr to - fix overloading when using these types. - -2022-09-17: wsfulton - [Guile] Add error checking to SWIGTYPE and SWIGTYPE & in typemaps to prevent - seg faults when passing #nil to these parameter types. - -2022-09-16: wsfulton - #999 Provide SWIGTYPE MOVE typemaps in swigmove.i for implementing full - move semantics when passing parameters by value. - -2022-08-31: wsfulton - #999 Improve move semantics when using rvalue references. - The SWIGTYPE && input typemaps now assume the object has been moved. - - These typemaps have been changed assuming that after the function call, - the rvalue reference parameter has been moved. The parameter's proxy class - that owns the C++ object thus has the underlying pointer set to null - so that the (moved from, but still valid) C++ object cannot be used again - and the object is additionally deleted. - - *** POTENTIAL INCOMPATIBILITY *** - -2022-08-28: wsfulton - [Octave] SWIG now marshals a C/C++ NULL pointer into the null matrix, []. - SWIG has always marshalled the null matrix into a NULL pointer; this remains - and now we have consistency in representing a NULL pointer. - -2022-08-26: wsfulton - [Racket] SWIG now marshals a C/C++ NULL pointer into a null value by calling - scheme_make_null(), so that scheme's null? is true for a NULL C/C++ pointer value. - -2022-08-18: wsfulton - [Racket] Add support for std::unique_ptr in std_unique_ptr.i. - Add support for std::auto_ptr in std_auto_ptr.i. - -2022-08-13: wsfulton - [Guile] Add support for std::unique_ptr in std_unique_ptr.i. - Add support for std::auto_ptr in std_auto_ptr.i. - -2022-08-11: wsfulton - [Lua] Add support for std::unique_ptr in std_unique_ptr.i. - Add support for std::auto_ptr in std_auto_ptr.i. - -2022-08-05: wsfulton - [D] Fix occasional undefined behaviour with inheritance hierarchies, particularly - when using virtual inheritance as the pointers weren't correctly upcast from derived - class to base class when stored in the base's proxy class. - -2022-08-05: wsfulton - [D] Add support for std::unique_ptr in std_unique_ptr.i. - Add support for std::auto_ptr in std_auto_ptr.i. - -2022-08-03: wsfulton - [Javascript] Add support for std::unique_ptr in std_unique_ptr.i. - Add support for std::auto_ptr in std_auto_ptr.i. - -2022-08-02: wsfulton - [Octave] Add support for std::unique_ptr in std_unique_ptr.i. - Add support for std::auto_ptr in std_auto_ptr.i. - -2022-08-01: wsfulton - [Python] Add initialisers for additional members in PyHeapTypeObject - (builtin mode) for Python-3.11 - _ht_tpname, _spec_cache. - -2022-07-30: wsfulton - C++20 has deprecated std::basic_string<>::reserve() and the C++11 method - std::basic_string<>::shrink_to_fit() is a replacement that can be used. - std_string.i and std_wstring.i provided wrappers for reserve with the following - template instantiations: - - %template(string) std::basic_string; - %template(wstring) std::basic_string; - - The reserve method is no longer wrapped, however the shrink_to_fit() method - can be used as an alternative from the target language (the generated wrappers - call reserve() instead if C++<=20). - - Note that std::basic_string<>::reserve(size_t n) is still wrapped unchanged. - - *** POTENTIAL INCOMPATIBILITY *** - -2022-07-30: wsfulton - [Tcl] Add support for std::unique_ptr in std_unique_ptr.i. - Add support for std::auto_ptr in std_auto_ptr.i. - -2022-07-27: ZackerySpytz, olly - #1678 Support parsing C++20 templated lambdas. - -2022-07-27: ZackerySpytz, olly - #1622 Add support for the C++20 spaceship operator (<=>). - -2022-07-26: olly - [Tcl] https://sourceforge.net/p/swig/bugs/977/ - Fix handling of long long on 32-bit platforms. This fix raises - SWIG's minimum supported Tcl version to 8.4.0 (which was released - just under 20 years ago). - -2022-07-26: olly - Fix incorrect operator precedence in preprocessor expressions. - -2022-07-25: olly - Support for C++14 binary integer literals in preprocessor expressions. - -2022-07-20: wsfulton - [C#, Java] Ensure the order of interfaces generated in proxy interfaces for the - %interface family of macros is the same as that parsed from the bases in C++. - -2022-07-20: jicks, Ingener74, olly - #422 [Python] Fix mishandling of a Python class inheriting from - multiple SWIG-wrapped director classes. - -2022-07-19: wsfulton - #692 [C#, Java, Perl, Python, Ruby] std::unique_ptr and std::auto_ptr typemaps - provided for inputs types in std_unique_ptr.i and std_auto_ptr.i. - - Now these smart pointers can be used as input parameters to functions. A proxy - class instance transfers memory ownership of the underlying C++ object from the - proxy class to a smart pointer instance passed to the wrapped function. - -2022-07-19: jschueller - [Python] #2314 Drop support for Python 3.2. - -2022-07-19: olly - Remove remaining support code for classic macos, which has not been - supported by Apple for over 20 years now. - -2022-07-12: wsfulton - #999 Performance optimisation for parameters passed by value that are C++11 movable. - The C++ wrappers create a temporary variable for a parameter to be passed to a - function. This is initially default constructed and then copy assigned from the - instance being passed in from the target language. This is unchanged, however, - when the temporary variable is passed to the wrapped function, it is now done using - std::move. If the type is move constructible, the move constructor will be used - instead of the copy constructor. - -2022-07-12: wsfulton - [Perl] Add std::auto_ptr support in std_auto_ptr.i library file. - -2022-07-12: erezgeva - [Perl] Add std::unique_ptr support in std_unique_ptr.i library file. - -2022-07-07: jmarrec - #1158 #2286 Add basic support for C++11 attributes. These are now - crudely ignored by SWIG's parser's tokeniser, which is better that - failing with a parse error. - -2022-07-05: ianlancetaylor - [Go] #2245 Handle NULL pointers for string* conversions. - Rearrange generation of director methods and rename - receiver argument from p to swig_p. - -2022-07-03: wsfulton - #999 Performance optimisation for directors for classes passed by value. The directorin - typemaps in the director methods now use std::move on the input parameter when - copying the object from the stack to the heap prior to the callback into the target - language, thereby taking advantage of move semantics if available. - -2022-07-02: wsfulton - #1722 [C#, Java, Python, Ruby] Add std::unique_ptr support. Ported from std::auto_ptr. - Use the %unique_ptr(T) macro as follows for usage std::unique_ptr. For example, for - a class called Klass: - - %include "std_unique_ptr.i" - %unique_ptr(Klass) - - Support is currently limited to only returning a std::unique_ptr from a function. - -2022-06-29: wsfulton - #999 #1044 Enhance SWIGTYPE "out" typemaps to use std::move when copying - objects, thereby making use of move semantics when wrapping a function returning - by value if the returned type supports move semantics. - - Wrapping functions that return move only types 'by value' now work out the box - without having to provide custom typemaps. - - The implementation removed all casts in the "out" typemaps to allow the compiler to - appropriately choose calling a move constructor, where possible, otherwise a copy - constructor. The implementation also required modifying SwigValueWrapper to - change a cast operator from: - - SwigValueWrapper::operator T&() const; - - to - - #if __cplusplus >=201103L - SwigValueWrapper::operator T&&() const; - #else - SwigValueWrapper::operator T&() const; - #endif - - This is not backwards compatible for C++11 and later when using the valuewrapper feature - if a cast is explicitly being made in user supplied "out" typemaps. Suggested change - in custom "out" typemaps for C++11 and later code: - - 1. Try remove the cast altogether to let the compiler use an appropriate implicit cast. - 2. Change the cast, for example, from static_cast to static_cast, using the - __cplusplus macro if all versions of C++ need to be supported. - - *** POTENTIAL INCOMPATIBILITY *** - -2022-06-15: wsfulton - #2039 Add move assignment operator to SwigValueWrapper used by the - valuewrapper feature. - -2022-06-04: sethrj - Enhance $typemap to support typemap attributes. - - $typemap(method:attribute, typepattern) - - For example: - - %typemap(cstype, out="object") XClass "XClass" - %typemap(cscode) BarClass %{ - $typemap(cstype:out, XClass) bar() { - return null; - } - - which expands to - - object bar() { - return null; - } - -2022-05-30: wsfulton - [C#, D] Add new special variable expansion: $imfuncname. - Expands to the function name called in the intermediary class. - -2022-05-30: LindleyF - [Java] #2042 Add new special variable expansion: $imfuncname. - Expands to the function name called in the intermediary class. - -2022-05-28: jkuebart - [Java] On some versions of Android, specifically Android 6, - detaching the current thread from the JVM after every invocation - causes a memory leak. - - Offer SWIG_JAVA_DETACH_ON_THREAD_END to configure a behaviour - where the JVM is only detached in the thread destructor. - - See https://developer.android.com/training/articles/perf-jni#threads. - -2022-05-27: xypron - [Python] #2277 Define PY_SSIZE_T_CLEAN macro before #include "Python.h" as - recommended in Python 3.7 and later. - - To avoid this macro definition, add the following to your interface file so - that SWIG_NO_PY_SSIZE_T_CLEAN is defined at the beginning of the C++ wrappers: - - %begin %{ - #define SWIG_NO_PY_SSIZE_T_CLEAN - %} - -2022-05-26: rokups - [C#] #1323 Modify SwigDerivedClassHasMethod for a more efficient director - implementation when calling virtual methods that are not overridden. - -2022-05-15: erezgeva, eiselekd - [Lua, Perl, Octave, PHP, Tcl] #2275 #2276 #2283 Add argcargv.i library containing - (int ARGC, char **ARGV) multi-argument typemaps. - - Document this library in Typemaps.html. - -2022-05-07: KrisThielemans - [Python] Fix "too many initializers for 'PyHeapTypeObject'" errors - using PyPy 3.8 and later. - -2022-05-04: wsfulton - [C#] Add C# wchar_t * director typemaps - -2022-04-20: cminyard - Fix an issue where newlines were not properly generated - for godirectorin typemaps. If you have a virtual function - not assigned to zero, in some cases it won't generate a - newline and you will see errors: - example.go:1508:3: expected ';', found swig_r - when compiling the go code. - - Also add an example of using goin and godirectorin and add - a test for this situation. - -2022-04-29: jason-daly, JerryJoyce, wsfulton - [C#] #1233 Add wchar_t * and std::wstring Unicode string support on Linux. - -2022-04-11: robinst - #2257 Fix new Ruby 3.2 warning "undefining the allocator of T_DATA - class swig_runtime_data". - -2022-04-07: olly - #1750 SWIG now recognises and ignores Doxygen group commands `@{` and `@}`. - -2022-04-06: wsfulton - ./configure now enables C++11 and later C++ standards testing by default (when - running: 'make check'). - - The options to control this testing are the same: - - ./configure --enable-cpp11-testing - ./configure --disable-cpp11-testing - - But the former is now the default and the latter can be used to turn off C++11 and - later C++ standards testing. - -2022-04-06: wsfulton - [Python] #1635 The "autodoc" feature no longer overrides Doxygen comments - in the generated docstring. - - If a "docstring" feature is present it will still override a Doxygen comment. - If the "autodoc" feature is also present, the combined "autodoc" and "docstring" - will override the Doxygen comment. If no "docstring" is present then the - "autodoc" feature will not be generated when there is a Doxygen comment. - - This way the "autodoc" feature can be specified and used to provide documentation - for 'missing' Doxygen comments. - - *** POTENTIAL INCOMPATIBILITY *** - -2022-04-01: olly - Remove undocumented and non-functional -browse command line option. - -2022-03-26: eltoder - [Python] #1684 Use different capsule names with and without -builtin - - Types generated with and without -builtin are not compatible. Mixing - them in a common type list leads to crashes. Avoid this by using - different capsule names: "type_pointer_capsule" without -builtin and - "type_pointer_capsule_builtin" with. - -2022-03-25: wsfulton - The debug command line options that display parse tree nodes - (-debug-module, -debug-top, -debug-symtabs) now display previously hidden - linked list pointers which are useful for debugging parse trees. - - Added new command line option -debug-quiet. This suppresses the display - of most linked list pointers and symbol table pointers in the parse tree nodes. - - The keys in the parse tree node are now shown in alphabetical order. - -2022-03-24: wsfulton - #2244 Fix using declaration in derived class bugs when all the base - class's overloaded methods were overridden in the derived class - - fixes "multiply defined" errors. - -2022-03-23: wsfulton - [Python] #1779 The -py3 option is deprecated and now has no effect on the - code generated. Use of this option results in a deprecated warning. - The related SWIGPYTHON_PY3 macro that this option defined is no longer generated. - - Note that %pythonnondynamic feature generates a metaclass that works on both - Python 2 and Python 3. - -2022-03-21: wsfulton - [Python] #1779 pyabc.i for abstract base classes now supports versions of - Python prior to 3.3 by using the collection module for these older versions. - Python-3.3 and later continue to use the collections.abc module. - The -py3 option no longer has any effect on the %pythonabc feature. - -2022-03-21: jschueller, jim-easterbrook, wsfulton - [Python] #2137 C++ static member functions no longer generate a "flattened" - name in the Python module. For example: - - s = example.Spam() - s.foo() # Spam::foo() via an instance - example.Spam.foo() # Spam::foo() using class method - example.Spam_foo() # Spam::foo() "flattened" name - - The "flattened" name is no longer generated, but can be generated - by using the new -flatstaticmethod option. - - *** POTENTIAL INCOMPATIBILITY *** - -2022-03-18: ianlancetaylor - [Go] #337 Implement %extend base methods in child classes. - -2022-03-17: olly - [Python] #1779 SWIG's Python test-suite and examples are now - run with Python 3 by default. To run them with Python 2, set - PY2 to a non-empty value, e.g.: - - make check-python-test-suite PY2=1 - -2022-03-16: olly - [Go] #683 -intgosize is now optional - if not specified the - generated C/C++ wrapper code will use ptrdiff_t for intgo and - size_t for uintgo. - -2022-03-15: ianlancetaylor - [Go] Add typemaps for std::string*. - -2022-03-15: ianlancetaylor - [Go] Don't convert arrays to pointers if there is a "gotype" - typemap entry. - -2022-03-15: ianlancetaylor - [Go] Add documentation note about Go and C++ exceptions. - -2022-03-12: wsfulton - #1524 %interface family of macros no longer contain the getter/setter - methods for wrapping variables. The interface only contains - virtual and non-virtual instance methods, that is, no static methods. - Enums are also no longer added to the interface (affects Java only where - they were missing from the proxy class, C# never had them in the interface). - - *** POTENTIAL INCOMPATIBILITY *** - -2022-03-12: wsfulton - #1277 Fixes for the family of %interface macros, %interface, - %interface_impl and %interface_custom fixes for overloaded methods - in an inheritance chain. - - When C++ methods are not able to be overloaded in a derived class, - such as when they differ by just const, or the target language - parameters types are identical even when the C++ parameter types - are different, SWIG will ignore one of the overloaded methods with - a warning. A %ignore is required to explicitly ignore one of the - overloaded methods to avoid the warning message. Methods added - in the derived classes due to one of the %interface macros are now - similarly ignored/not added to the derived class. - - The methods added to the derived classes can now also be modified - via %feature and %rename. - -2022-03-08: ianlancetaylor - [Go] Treat a nil argument as a NULL pointer. - -2022-03-08: ianlancetaylor - [Go] Add documentation notes about thread local storage. - -2022-03-08: olly - #1006 SWIG now copes with an interface filename specified on the - command line which contains a closing parenthesis `)`, and more - generally with attributes to `%include` and `%import` which - are quoted and contain parentheses. - -2022-03-07: Omar Medina - [Tcl] https://sourceforge.net/p/swig/bugs/1290/ - Fix SWIG_AsWCharPtrAndSize() to actually assign to result - variable. It looks like SWIG/Tcl wide character handling is - currently fundamentally broken except on systems which use wide - characters as the system encoding, but this should fix wrapping - functions which take a wide string as a parameter on Microsoft - Windows. - -2022-03-07: olly - [Javascript] #682 Fix handling of functions which take void*. - -2022-03-06: olly - SWIG should now reliably exit with status 0 if the run was - successful and status 1 if there was an error (or a warning and - -Werror was in effect). - - Previously in some situations SWIG would try to exit with the - status set to the number of errors encountered, but that's - problematic - for example if there were 256 errors this would - result in exit status 0 on most platforms. Also some error - statuses have special meanings e.g. those defined by . - Also SWIG/Javascript tried to exit with status -1 in a few places - (which typically results in exit status 255). - -2022-03-05: wsfulton - #1441 Fix using declaration in derived class incorrectly introducing a method - from a base class when the using declaration is declared before the method - declaration. Problem occurred when within a namespace and the parameter types - in the method signatures were not fully qualified. -2022-03-05: ianlancetaylor - [Go] Treat non-const references as pointers. - -2022-03-05: ianlancetaylor - In SWIG Go testsuite, fail test if "go build" fails. - -2022-03-03: olly - #1901 #2223 SWIG should now always exit cleanly if memory - allocation fails, including removing any output files created - during the current run. - - Previously most places in the code didn't check for a NULL return - from malloc()/realloc()/calloc() at all, typically resulting in - undefined behaviour; some places used assert() to check for a NULL - return (which is a misuse of assert() and such checks disappear if - built with NDEBUG defined leaving us back with undefined - behaviour). - -2022-03-03: olly - #891 Report errors for typemap attributes without a value - (previously SWIG segfaulted) and for typemap types with a value - (previously the value was quietly ignored). - - The old way of specifying a language name in the typemap attributes - is no longer supported (it has been deprecated for 16 years). - -2022-03-02: geographika, wsfulton - [Python] #1951 Add Python variable annotations support. - - Both function annotations and variable annotations are turned on using the - "python:annotations" feature. Example: - - %feature("python:annotations", "c"); - - struct V { - float val; - }; - - The generated code contains a variable annotation containing the C float type: - - class V(object): - val: "float" = property(_example.V_val_get, _example.V_val_set) - ... - - Python 3.5 and earlier do not support variable annotations, so variable - annotations can be turned off with a "python:annotations:novar" feature flag. - Example turning on function annotations but not variable annotations globally: - - %feature("python:annotations", "c"); - %feature("python:annotations:novar"); - - or via the command line: - - -features python:annotations=c,python:annotations:novar - - *** POTENTIAL INCOMPATIBILITY *** - -2022-02-27: wsfulton - [Python] #735 #1561 Function annotations containing C/C++ types are no longer - generated when using the -py3 option. Function annotations support has been - moved to a feature to provide finer grained control. It can be turned on - globally by adding: - - %feature("python:annotations", "c"); - - or by using the command line argument: - - -features python:annotations=c - - Also see entry dated 2022-03-02, regarding variable annotations. - - *** POTENTIAL INCOMPATIBILITY *** - -2022-02-26: wsfulton - #655 #1840 Add new warning WARN_LANG_USING_NAME_DIFFERENT to warn when a - method introduced by a using declaration in a derived class cannot - be used due to a conflict in names. - -2022-02-24: olly - #1465 An invalid preprocessor expression is reported as a pair of - warnings with the second giving a more detailed message from the - expression evaluator. Previously SWIG prefixed the second message - with "Error:" - that was confusing as it's actually only a warning - by default so we've now dropped this prefix. - - Before: - - x.i:1: Warning 202: Could not evaluate expression '1.2' - x.i:1: Warning 202: Error: 'Floating point constant in preprocessor expression' - - Now: - - x.i:1: Warning 202: Could not evaluate expression '1.2' - x.i:1: Warning 202: Floating point constant in preprocessor expression - -2022-02-23: olly - #1384 Fix a preprocessor expression evaluation bug. A - subexpression in parentheses lost its string/int type flag and - instead used whatever type was left in the stack entry from - previous use. In practice we mostly got away with this because - most preprocessor expressions are integer, but it could have - resulted in a preprocessor expression incorrectly evaluating as - zero. If -Wextra was in use you got a warning: - - Warning 202: Error: 'Can't mix strings and integers in expression' - -2022-02-21: davidcl - [Scilab] Improve 5.5.2, 6.0.0 and 6.1.0 support. - - For Scilab 5, long names are reduced to small names preserving the - class prefix and accessor suffix (get or set). - - For Scilab 6, long names with the class prefix and accessor suffix - should be used on the user code. - - The `-targetversion` option has been removed as the generated code - now detects the Scilab version in loader.sce or builder.sce. - - *** POTENTIAL INCOMPATIBILITY *** - -2022-02-20: wsfulton - Fix %warnfilter warning suppress for warning 315 SWIGWARN_PARSE_USING_UNDEF. - -2022-02-17: olly - [PHP] https://sourceforge.net/p/swig/bugs/1211/ - Fix to call cleanup code in exception situations and not to invoke - the freearg typemap twice in certain situations. - -2022-02-15: olly - #300 #368 Improve parser handling of % followed immediately by - an identifier. If it's not a recognised directive the scanner - now emits MODULO and then rescans what follows, and if the parser - then gives a syntax error we report it as an unknown directive. - This means that `a%b` is now allowed in an expression, and that - things like `%std::vector` now give an error rather - than being quietly ignored. - -2022-02-11: adr26 - [Python] #2154 Fix memory leak. - - SWIG python objects were being freed after the corresponding SWIG - module information was destroyed in Python 3, causing leaks when as - a result the object destructor could not be invoked. To prevent this - misordering, SWIG python objects now obtain a reference to the - Python capsule wrapping the module information, so that the module - information is correctly destroyed after all SWIG python objects - have been freed (and corresponding destructors invoked). - -2022-02-10: olly - [Tcl] https://sourceforge.net/p/swig/bugs/1207/ - https://sourceforge.net/p/swig/bugs/1213/ - - Fix Tcl generic input typemap for std::vector. - -2022-02-07: sethrj - #2196 Add alternative syntax for specifying fragments in typemaps. - - New syntax: - %typemap("in", fragment="frag1", fragment="frag2", fragment="frag3") {...} - which is equivalent to: - %typemap(in, fragment="frag1,frag2,frag3") {...} - - -2022-02-07: olly - #1806 Remove support for the "command" encoder, which was mostly - intended for use in `%rename` - most uses can be achieved using - the "regex" encoder, so we recommend using that instead. - - The "command" encoder suffers from a number of issues - as the - documentation for it admitted, "[it] is extremely slow compared to - all the other [encoders] as it involves spawning a separate process - and using it for many declarations is not recommended" and that it - "should generally be avoided because of performance - considerations". - - But it's also not portable. The design assumes that `/bin/sh` - supports `<<<` but that's a bash-specific feature so it doesn't - work on platforms where `/bin/sh` is not bash - it fails on - Debian, Ubuntu and probably some other Linux distros, plus most - non-Linux platforms. Microsoft Windows doesn't even have a - /bin/sh as standard. - - Finally, no escaping of the passed string is done, so it has - potential security issues (though at least with %rename the input - is limited to valid C/C++ symbol names). - -2022-02-06: olly - #2193 -DFOO on the SWIG command line now sets FOO to 1 for - consistency with C/C++ compiler preprocessors. Previously - SWIG set FOO to an empty value. - - Existing invocations of SWIG with `-DFOO` where the empty value - matters can be updated to `-DFOO=` which should work with both - old and new releases of SWIG. - - *** POTENTIAL INCOMPATIBILITY *** - -2022-02-06: sethrj - #2194 Classes that are non-assignable due to const data or const - reference members are now automatically detected. - -2022-02-04: friedrichatgc - [Octave] #1672 Fix for isobject for Octave 4.4 - 6.0. - -2022-02-03: olly - [C#] #283 #998 Fix memory leak in directorin typemap for - std::string. - -2022-02-03: olly - [Python] #967 Make `self` parameter available to user typemaps. - -2022-02-03: teythoon - [Python] #801 Fix -Wunused-parameter warnings with builtin, - -2022-02-03: teythoon - #801 Fix -Wstrict-prototypes warnings in generated pointer - functions. - -2022-02-03: olly - #660 https://sourceforge.net/p/swig/bugs/1081/ - Default parameter values containing method calls are now parsed and - handled - e.g. `x->foo(3,4)` and `y.z()`. - -2022-02-02: olly - [Ruby] https://sourceforge.net/p/swig/bugs/1136/ Fix remove of prefix - from method name to only remove it at the start. - -2022-02-01: olly - #231 Handle returning an object by reference in a C++ trailing - return type. - -2022-02-01: davidcl - [Scilab] #745 use SWIG__Init() as a C module init function. - -2022-02-01: olly - [OCaml] #2083 Fix to work when CAML_SAFE_STRING is on, which it is - by default in recent Ocaml releases. - -2022-01-31: mreeez - https://sourceforge.net/p/swig/bugs/1147/ - Fix copyToR() generated for a struct in a namespace. - -2022-01-29: fschlimb - #655 Better handling of using declarations. - -2022-01-29: dontpanic92 - [Go] #676 Fix code generated for a C++ class with a non-capitalised - name. - -2022-01-26: trex58 - #1919 #1921 #1923 Various fixes for AIX portability. - -2022-01-26: olly - #1935 Don't crash on an unclosed HTML tag in a doxygen comment - when -doxygen is specified. - -2022-01-25: olly - Constant expressions now support member access with `.` such as - `foo.bar`. Previous this only worked in a case like `x->foo.bar`. - -2022-01-25: olly - #2091 Support most cases of `sizeof` applied to an expression - in constant expressions. Previously there was only support for - `sizeof()` and expressions which syntactically look like a - type (such as `sizeof(foo)`). - -2022-01-25: olly - #80 #635 https://sourceforge.net/p/swig/bugs/1139/ - Add support for parsing common cases of `<` and `>` comparisons - in constant expressions. Adding full support for these seems hard - to do without introducing conflicts into the parser grammar, but in - fact all reported cases have had parentheses around the comparison - and we can support that with a few restrictions on the left side of - `<`. - -2022-01-25: wsfulton - New warning 327 for extern templates, eg: - - extern template class std::vector; - extern template void Func(); - - results in warning - - example.i:3: Warning 327: Extern template ignored. - example.i:4: Warning 327: Extern template ignored. - - Extern template classes previously resulted in warning 320. - -2022-01-24: romintomasetti - #2131 #2157 C++11 extern function template parsing error fix. - -2022-01-21: wsfulton - #2120 #2138 Replace legacy PCRE dependency with PCRE2. - This requires changes for building SWIG from source. See updated - html documentation in Preface.html and Windows.html. Updated - instructions are also shown when running ./configure if PCRE2 is not - found. Note that debian based systems can install PCRE2 using: - - apt install libpcre2-dev - - Note that https://github.com/swig/swig/wiki/Getting-Started also has - updated information for building from source. - -2022-01-19: olly - [PHP] #2027 Automatically generate PHP type declarations for PHP 8. - The generate code still compiles for PHP 7.x, but without type - declarations since PHP 7.x has much more limited type declaration - support. - -2022-01-18: olly - [Perl] #1629 Perl 5.8.0 is now the oldest version we aim to support. - -2022-01-14: wsfulton - [Python] Fix %callback and specifying the callback function as a - static member function using Python staticmethod syntax, such as - Klass.memberfunction instead of Klass_memberfunction when using - -builtin and -fastproxy. - -2022-01-11: wsfulton - [Python] Accept keyword arguments accessing static member functions when - using -builtin and kwargs feature and Python class staticmethod syntax. - The missing keyword argument support was only when using the - class staticmethod syntax, such as Klass.memberfunction, and not when - using the flat static method syntax, such as Klass_memberfunction. - -2022-01-04: juierror - [Go] #2045 Add support for std::array in std_array.i. - -2021-12-18: olly - [PHP] Add PHP keyword 'readonly' (added in 8.1) to the list SWIG - knows to automatically rename. This keyword is special in that PHP - allows it to be used as a function (or method) name. - -2021-12-07: vstinner - [Python] #2116 Python 3.11 support: use Py_SET_TYPE() - -2021-12-05: rwf1 - [Octave] #2020 #1893 Add support for Octave 6 up to and including 6.4. - Also add support for compiling with -Bsymbolic which is used by default - by mkoctfile. - -2021-12-02: jsenn - [Python] #2102 Fixed crashes when using embedded Python interpreters. - -2021-11-12: wsfulton - [Javascript] v8 and node only. Fix mismatched new char[] and free() - when wrapping C code char arrays. Now calloc is now used instead of - new char[] in SWIG_AsCharPtrAndSize. - -2021-10-03: ajrh1 - [Perl] #2074: Avoid -Wmisleading-indentation in generated code - when using gcc11. - -2021-10-03: jschueller - [CMake] #2065: Add option to enable or disable PCRE support. - -2021-09-16: ianlancetaylor - [Go] Improved _cgo_panic implementation. - -2021-09-16: ianlancetaylor - [Go] Don't use crosscall2 for panicking. Instead rely on documented - and exported interfaces. - -2021-09-14: ianlancetaylor - [Go] Remove -no-cgo option (long unsupported in Go) - -2021-05-04: olly - [PHP] #2014 Throw PHP exceptions instead of using PHP errors - - PHP exceptions can be caught and handled if desired, but if they - aren't caught then PHP exits in much the same way as it does for a - PHP error. - - In particular this means parameter type errors and some other cases - in SWIG-generated wrappers now throw a PHP exception, which matches - how PHP's native parameter handling deals with similar situations. - - `SWIG_ErrorCode()`, `SWIG_ErrorMsg()`, `SWIG_FAIL()` and `goto thrown;` - are no longer supported (these are really all internal implementation - details and none are documented aside from brief mentions in CHANGES - for the first three). I wasn't able to find any uses in user interface - files at least in FOSS code via code search tools. - - If you are using these: - - Use `SWIG_PHP_Error(code,msg);` instead of `SWIG_ErrorCode(code); - SWIG_ErrorMsg(msg);` (which will throw a PHP exception in SWIG >= 4.1 - and do the same as the individual calls in older SWIG). - - `SWIG_FAIL();` and `goto thrown;` can typically be replaced with - `SWIG_fail;`. This will probably also work with older SWIG, but - please test with your wrappers if this is important to you. - - *** POTENTIAL INCOMPATIBILITY *** - -2021-05-17: adr26 - [Python] #1985 Fix memory leaks: - - 1. Python object references were being incorrectly retained by - SwigPyClientData, causing swig_varlink_dealloc() never to run / free - memory. SwigPyClientData_New() / SwigPyClientData_Del() were updated - to fix the object reference counting, causing swig_varlink_dealloc() - to run and the memory swig_varlink owns to be freed. - - 2. SwigPyClientData itself was not freed by SwigPyClientData_Del(), - causing another heap leak. The required free() was added to - SwigPyClientData_Del() - - 3. Fix reference counting/leak of python cached type query - - 4. Fix reference counting/leak of SwigPyObject dict (-builtin) - - 5. Python object reference counting fixes for out-of-memory - scenarios were added to: SWIG_Python_RaiseOrModifyTypeError(), - SWIG_Python_AppendOutput(), SwigPyClientData_New(), - SwigPyObject_get___dict__() and SwigPyObject_format() - - 6. Add error handling for PyModule_AddObject() to - SWIG_Python_SetModule() (failure could be caused by OOM or a name - clash caused by malicious code) - -2021-05-13: olly - [UFFI] #2009 Remove code for Common Lisp UFFI. We dropped support - for it in SWIG 4.0.0 and nobody has stepped forward to revive it in - over 2 years. - -2021-05-13: olly - [S-EXP] #2009 Remove code for Common Lisp S-Exp. We dropped - support for it in SWIG 4.0.0 and nobody has stepped forward to - revive it in over 2 years. - -2021-05-13: olly - [Pike] #2009 Remove code for Pike. We dropped support for it in - SWIG 4.0.0 and nobody has stepped forward to revive it in over 2 - years. - -2021-05-13: olly - [Modula3] #2009 Remove code for Modula3. We dropped support for it - in SWIG 4.0.0 and nobody has stepped forward to revive it in over 2 - years. - -2021-05-13: olly - [CLISP] #2009 Remove code for GNU Common Lisp. We dropped support - for it in SWIG 4.0.0 and nobody has stepped forward to revive it in - over 2 years. - -2021-05-13: olly - [Chicken] #2009 Remove code for Chicken. We dropped support for it - in SWIG 4.0.0 and nobody has stepped forward to revive it in over 2 - years. - -2021-05-13: olly - [Allegrocl] #2009 Remove code for Allegro Common Lisp. We dropped - support for it in SWIG 4.0.0 and nobody has stepped forward to - revive it in over 2 years. - -2021-05-04: olly - [PHP] #1982 #1457 https://sourceforge.net/p/swig/bugs/1339/ - SWIG now only use PHP's C API to implement its wrappers, and no - longer generates PHP code to define classes. The wrappers should - be almost entirely compatible with those generated before, but - faster and without some previously hard-to-fix bugs. - - The main notable difference is SWIG no longer generates a .php - wrapper at all by default (only if %pragma(php) code=... or - %pragma(php) include=... are specified in the interface file). - This also means you need to load the module via extension=... - in php.ini, rather than letting the dl() in the generated - .php wrapper load it (but dl() has only worked for command-line - PHP for some years now). - - *** POTENTIAL INCOMPATIBILITY *** - -2021-04-30: olly - #1984 Remove support for $source and $target. - These were officially deprecated in 2001, and attempts to use them have - resulted in a warning (including a pointer to what to update them to) - for most if not all of that time. - -2021-04-27: wsfulton - #1987 [Java] Fix %interface family of macros for returning by const - pointer reference. - -2021-04-19: olly - Fix use of uninitialised variable in the generated code for an - empty typecheck typemap, such as the dummy one we include for - std::initializer_list. - -2021-04-12: olly - #1777 [Python] Specifying -py3 now generates a check for Python - version >= 3.0. - -2021-03-26: olly - [PHP] Add PHP keywords 'fn' (added in 7.4) and 'match' (added in - 8.0) to the list SWIG knows to automatically rename. - -2021-03-23: wsfulton - #1942 [Python] Fix compilation error in wrappers when using -builtin - and wrapping varargs in constructors. - -2021-03-22: goto40 - #1977 Fix handling of template template parameters. - -2021-03-21: olly - #1929, #1978 [PHP] Add support for PHP 8. - -2021-03-19: wsfulton - #1610 Remove -ansi from default compilation flags. - -2021-03-19: dot-asm - #1934 [Java] Clean up typemaps for long long arrays. - -2021-03-19: olly - #1527 [PHP] Improve PHP object creation in directorin case. - Reportedly the code we were using in this case gave segfaults in - PHP 7.2 and later - we've been unable to reproduce these, but the - new approach is also simpler and should be bit faster too. - -2021-03-18: olly - #1655 [PHP] Fix char* typecheck typemap to accept PHP Null like the - corresponding in typemap does. - -2021-03-18: olly - #1900, #1905 [PHP] Fix wrapping of overloaded directed methods with - non-void return. - -2021-03-11: murillo128 - #1498 [Javascript] Support type conversion. - -2021-03-06: nshmyrev - #872 [Javascript] Various typemap issues in arrays_javascript.i fixed. - -2021-03-03: vaughamhong - #577 [Javascript] Implemented SetModule/GetModule for JSC to allow type sharing - across modules. - -2021-03-01: xantares, Oliver Buchtala, geographika - #1040 Add support for building SWIG with CMake. See documentation in Windows.html. - -2021-03-01: vadz - #1952 Fix incorrect warning "Unknown Doxygen command: ." - -2021-02-28: p2k - #969 [Javascript] v8/node - prevent crash calling a constructor without new keyword. - -2021-02-28: alecmev - #405 #1121 [Javascript] Fix OUTPUT typemaps on methods that don't return void. - The output value is appended to the return value. - -2021-02-26: murillo128, wsfulton - #1269 [Javascript] Fix handling of large positive unsigned long and - unsigned long long values. - -2021-02-24: tomleavy, yegorich, tungntpham - #1746 [Javascript] Add support for Node v12, v14 and v16. - SWIG support for Node is now for v6 and later only. - -2020-02-09: ZackerySpytz - #1872 Fix typos in attribute2ref macros. - -2020-10-10: wsfulton - [Javascript] Fix so that ccomplex.i interface to file can be used. - -2020-10-10: wsfulton - #252 complex can now be used as a C identifier and doesn't give a syntax error. - -2020-10-10: lpsinger - #1770 Correct C complex support. - _Complex is now parsed as a keyword rather than complex as per the C99 standard. - The complex macro is available in the ccomplex.i library file along with other - complex number handling provided by the complex.h header. - -2020-10-07: ZackerySpytz - [Python] #1812 Fix the error handling for the PyObject_GetBuffer() calls in - pybuffer.i. - -2020-10-07: treitmayr - #1824 Add missing space in director method declaration returning - const pointer. - -2020-10-07: adelva1984 - #1859 Remove all (two) exceptions from SWIG executable. - -2020-09-25: wsfulton - [C#, Java] #1874 Add ability to change the modifiers for the interface - generated when using the %interface macros. - - For C# use the 'csinterfacemodifiers' typemap. - For Java use the 'javainterfacemodifiers' typemap. - - For example: - - %typemap(csinterfacemodifiers) X "internal interface" - -2020-09-24: geefr - [C#] #1868 Fix wchar_t* csvarout typemap for member variable wrappers. - -2020-08-28: wsfulton - [Java] #1862 Fix crashes in swig_connect_director during director class construction - when using the director class from multiple threads - a race condition initialising - block scope static variables. The fix is guaranteed when using C++11, but most - compilers also fix it when using C++03/C++98. - -2020-08-16: wsfulton - [Python] Add missing initializer for member ‘_heaptypeobject::ht_module’ when using - -builtin to complete Python 3.9 support. - -2020-08-16: wsfulton - [Python] Remove PyEval_InitThreads() call for Python 3.7 and later as Python calls - it automatically now. This removes a deprecation warning when using Python 3.9. - -2020-08-15: wsfulton - [Python] All Python examples and tests are written to be Python 2 and Python 3 - compatible, removing the need for 2to3 to run the examples or test-suite. - -2020-08-13: wsfulton - [C#] Add support for void *VOID_INT_PTR for member variables. - -2020-07-29: chrisburr - #1843 [Python] Compilation error fix in SwigPyBuiltin_SetMetaType when using PyPy. - -2020-06-14: ZackerySpytz - #1642 #1809 Fix virtual comparison operators in director classes by removing an - incorrect space in the function name (for example, operator= = is now operator==). diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html index d06bb7120..4b8577adf 100644 --- a/Doc/Manual/Sections.html +++ b/Doc/Manual/Sections.html @@ -1,14 +1,14 @@ -SWIG-4.1 Documentation +SWIG-4.2 Documentation -

      SWIG-4.1 Documentation

      +

      SWIG-4.2 Documentation

      -Last update : SWIG-4.1.0 (24 Oct 2022) +Last update : SWIG-4.2.0 (in progress)

      Sections

      diff --git a/README b/README index c5317fee7..e499e7605 100644 --- a/README +++ b/README @@ -1,7 +1,5 @@ SWIG (Simplified Wrapper and Interface Generator) -Version: 4.1.0 (24 Oct 2022) - Tagline: SWIG is a compiler that integrates C and C++ with languages including Perl, Python, Tcl, Ruby, PHP, Java, C#, D, Go, Lua, Octave, R, Scheme (Guile, MzScheme/Racket), Scilab, Ocaml. diff --git a/configure.ac b/configure.ac index f88004ab9..4ae334e28 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. dnl The macros which aren't shipped with the autotools are stored in the dnl Tools/config directory in .m4 files. -AC_INIT([swig],[4.1.0],[https://www.swig.org]) +AC_INIT([swig],[4.2.0],[https://www.swig.org]) AC_PREREQ([2.60]) AC_CONFIG_SRCDIR([Source/Swig/swig.h]) From ed09dd948f5a310c586708af360dddcd09cc6ee3 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 25 Oct 2022 19:05:26 +0100 Subject: [PATCH 139/217] cpp11_attribute_specifiers testcase warning suppression --- Examples/test-suite/cpp11_attribute_specifiers.i | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/test-suite/cpp11_attribute_specifiers.i b/Examples/test-suite/cpp11_attribute_specifiers.i index b822d2ae9..f14c87b0d 100644 --- a/Examples/test-suite/cpp11_attribute_specifiers.i +++ b/Examples/test-suite/cpp11_attribute_specifiers.i @@ -19,6 +19,7 @@ #if defined(_MSC_VER) #pragma warning(disable : 4996) // For the deprecated attributes in this testcase +#pragma warning(disable : 5030) // attribute is not recognized ('likely' and 'unlikely') #endif From 24b0e6839113d69a7d60cd30d7b17cbdbd325355 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 26 Oct 2022 19:03:38 +0100 Subject: [PATCH 140/217] li_boost_shared_ptr testcase for R Synchronise test with Python version of testcase --- .../test-suite/r/li_boost_shared_ptr_runme.R | 187 +++++++++++------- 1 file changed, 115 insertions(+), 72 deletions(-) diff --git a/Examples/test-suite/r/li_boost_shared_ptr_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_runme.R index 73765b3e3..607d008c0 100644 --- a/Examples/test-suite/r/li_boost_shared_ptr_runme.R +++ b/Examples/test-suite/r/li_boost_shared_ptr_runme.R @@ -90,16 +90,6 @@ testSuite <- function() { testSuite_verifyCount(2, kret) } - { - # pass by shared_ptr pointer reference - k = Klass("me oh my"); - kret = smartpointerpointerreftest(k); - val = kret$getValue() - unittest("me oh my smartpointerpointerreftest", val); - testSuite_verifyCount(2, k); - testSuite_verifyCount(2, kret); - } - # const pass by shared_ptr { k = Klass("me oh my"); @@ -250,47 +240,110 @@ testSuite <- function() { } # - # ###################### Derived and base class mixed ###################### + # ###################### Derived class ###################### # + # derived pass by shared_ptr + { + k = KlassDerived("me oh my") + kret = derivedsmartptrtest(k) + val = kret$getValue() + unittest("me oh my derivedsmartptrtest-Derived", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } + + # derived pass by shared_ptr pointer + { + k = KlassDerived("me oh my") + kret = derivedsmartptrpointertest(k) + val = kret$getValue() + unittest("me oh my derivedsmartptrpointertest-Derived", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } + + # derived pass by shared_ptr ref + { + k = KlassDerived("me oh my") + kret = derivedsmartptrreftest(k) + val = kret$getValue() + unittest("me oh my derivedsmartptrreftest-Derived", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } + + # derived pass by shared_ptr pointer ref + { + k = KlassDerived("me oh my") + kret = derivedsmartptrpointerreftest(k) + val = kret$getValue() + unittest("me oh my derivedsmartptrpointerreftest-Derived", val) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) + } + + # derived pass by pointer + { + k = KlassDerived("me oh my") + kret = derivedpointertest(k) + val = kret$getValue() + unittest("me oh my derivedpointertest-Derived", val) + testSuite_verifyCount(1, k) + testSuite_verifyCount(1, kret) + } + + # derived pass by ref + { + k = KlassDerived("me oh my") + kret = derivedreftest(k) + val = kret$getValue() + unittest("me oh my derivedreftest-Derived", val) + testSuite_verifyCount(1, k) + testSuite_verifyCount(1, kret) + } + + # + # ###################### Derived and base class mixed ###################### + # # pass by shared_ptr (mixed) { - k = KlassDerived("me oh my"); - kret = derivedsmartptrtest(k); - val = kret$getValue(); - unittest("me oh my derivedsmartptrtest-Derived", val); - testSuite_verifyCount(2, k); - testSuite_verifyCount(2, kret); + k = KlassDerived("me oh my") + kret = smartpointertest(k) + val = kret$getValue() + unittest("me oh my smartpointertest-Derived", val) + #testSuite_verifyCount(2, k) + #testSuite_verifyCount(2, kret) } # pass by shared_ptr pointer (mixed) { - k = KlassDerived("me oh my"); - kret = derivedsmartptrpointertest(k); - val = kret$getValue(); - unittest("me oh my derivedsmartptrpointertest-Derived", val); - testSuite_verifyCount(2, k); - testSuite_verifyCount(2, kret); + k = KlassDerived("me oh my") + kret = smartpointerpointertest(k) + val = kret$getValue() + unittest("me oh my smartpointerpointertest-Derived", val) + #testSuite_verifyCount(2, k) + #testSuite_verifyCount(2, kret) } - # pass by shared_ptr ref (mixed) + # pass by shared_ptr reference (mixed) { - k = KlassDerived("me oh my"); - kret = derivedsmartptrreftest(k); - val = kret$getValue(); - unittest("me oh my derivedsmartptrreftest-Derived", val); - testSuite_verifyCount(2, k); - testSuite_verifyCount(2, kret); + k = KlassDerived("me oh my") + kret = smartpointerreftest(k) + val = kret$getValue() + unittest("me oh my smartpointerreftest-Derived", val) + #testSuite_verifyCount(2, k) + #testSuite_verifyCount(2, kret) } # pass by shared_ptr pointer reference (mixed) { - k = KlassDerived("me oh my"); - kret = smartpointerpointerreftest(k); - val = kret$getValue(); - unittest("me oh my smartpointerpointerreftest-Derived", val); - #testSuite_verifyCount(2, k); # includes two extra references for upcasts in the proxy classes - #testSuite_verifyCount(2, kret); + k = KlassDerived("me oh my") + kret = smartpointerpointerreftest(k) + val = kret$getValue() + unittest("me oh my smartpointerpointerreftest-Derived", val) + #testSuite_verifyCount(2, k) + #testSuite_verifyCount(2, kret) } # pass by value (mixed) @@ -299,38 +352,31 @@ testSuite <- function() { kret = valuetest(k) val = kret$getValue() unittest("me oh my valuetest", val) # note slicing - testSuite_verifyCount(2, k) - testSuite_verifyCount(1, kret) - - # --> these are the python expected counting - # testSuite_verifyCount(1, k) - # testSuite_verifyCount(1, kret) + #testSuite_verifyCount(1, k) + #testSuite_verifyCount(1, kret) } # pass by pointer (mixed) { - k = KlassDerived("me oh my"); - kret = derivedpointertest(k); - val = kret$getValue(); - unittest("me oh my derivedpointertest-Derived", val); - testSuite_verifyCount(1, k); - testSuite_verifyCount(1, kret); + k = KlassDerived("me oh my") + kret = pointertest(k) + val = kret$getValue() + unittest("me oh my pointertest-Derived", val) + #testSuite_verifyCount(1, k) + #testSuite_verifyCount(1, kret) } # pass by ref (mixed) { - k = KlassDerived("me oh my"); - kret = reftest(k); - val = kret$getValue(); - unittest("me oh my reftest-Derived", val); - testSuite_verifyCount(2, k); - testSuite_verifyCount(1, kret); - - # --> these are the python expected counting - #testSuite_verifyCount(1, k); - #testSuite_verifyCount(1, kret); + k = KlassDerived("me oh my") + kret = reftest(k) + val = kret$getValue() + unittest("me oh my reftest-Derived", val) + #testSuite_verifyCount(1, k) + #testSuite_verifyCount(1, kret) } + # # ################# Overloading tests ################## # @@ -369,15 +415,12 @@ testSuite <- function() { { k = Klass3rdDerived("me oh my") - unittest(overload_rawbyval(k), "rawbyval") - unittest(overload_rawbyref(k), "rawbyref") - unittest(overload_rawbyptr(k), "rawbyptr") - unittest(overload_rawbyptrref(k), "rawbyptrref") - - unittest(overload_smartbyval(k), "smartbyval") - unittest(overload_smartbyref(k), "smartbyref") - unittest(overload_smartbyptr(k), "smartbyptr") - unittest(overload_smartbyptrref(k), "smartbyptrref") + val = k$getValue() + unittest("me oh my-3rdDerived", val) + testSuite_verifyCount(1, k) + val = test3rdupcast(k) + unittest("me oh my-3rdDerived", val) +# testSuite_verifyCount(1, k) } # @@ -394,7 +437,7 @@ testSuite <- function() { unittest("smart member value", val); testSuite_verifyCount(2, k); - kmember = m$SmartMemberPointer; + kmember = m$SmartMemberValue; val = kmember$getValue(); unittest("smart member value", val); testSuite_verifyCount(3, kmember); @@ -434,14 +477,14 @@ testSuite <- function() { unittest("smart member reference", val); testSuite_verifyCount(2, k); - kmember = m$SmartMemberPointer; + kmember = m$SmartMemberReference; val = kmember$getValue(); unittest("smart member reference", val); testSuite_verifyCount(3, kmember); testSuite_verifyCount(3, k); # The C++ reference refers to SmartMemberValue... - kmemberVal = m$SmartMemberReference; + kmemberVal = m$SmartMemberValue; val = kmember$getValue(); unittest("smart member reference", val); testSuite_verifyCount(4, kmemberVal); @@ -634,9 +677,9 @@ testSuite <- function() { # { pid = PairIntDouble(10, 20.2); - if (BaseIntDouble_baseVal1_get(pid) != 20 || BaseIntDouble_baseVal2_get(pid) != 40.4) + if (pid$baseVal1 != 20 || pid$baseVal2 != 40.4) stop("Base values wrong"); - if (PairIntDouble_val1_get(pid) != 10 || PairIntDouble_val2_get(pid) != 20.2) + if (pid$val1 != 10 || pid$val2 != 20.2) stop("Derived Values wrong"); } From 9e7610f972f3ba770dae3a99ec7a803171396165 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 26 Oct 2022 22:44:13 +0100 Subject: [PATCH 141/217] Fix memory leak in R shared_ptr wrappers Fix leak when a cast up a class inheritance chain is required. Adds implementation of SWIG_ConvertPtrAndOwn for R. Closes #2386 --- CHANGES.current | 4 +++ .../test-suite/r/li_boost_shared_ptr_runme.R | 32 +++++++++---------- Lib/r/rrun.swg | 18 ++++++++--- Lib/r/std_vector.i | 4 +-- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index d908e64da..8331dfd66 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,3 +7,7 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2022-10-26: wsfulton + [R] #2386 Fix memory leak in R shared_ptr wrappers. + Fix leak when a cast up a class inheritance chain is required. + diff --git a/Examples/test-suite/r/li_boost_shared_ptr_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_runme.R index 607d008c0..1f7507337 100644 --- a/Examples/test-suite/r/li_boost_shared_ptr_runme.R +++ b/Examples/test-suite/r/li_boost_shared_ptr_runme.R @@ -80,8 +80,8 @@ testSuite <- function() { testSuite_verifyCount(2, kret) } + # pass by shared_ptr pointer reference { - # pass by shared_ptr pointer reference k = Klass("me oh my") kret = smartpointerpointerreftest(k) val = kret$getValue() @@ -312,8 +312,8 @@ testSuite <- function() { kret = smartpointertest(k) val = kret$getValue() unittest("me oh my smartpointertest-Derived", val) - #testSuite_verifyCount(2, k) - #testSuite_verifyCount(2, kret) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) } # pass by shared_ptr pointer (mixed) @@ -322,8 +322,8 @@ testSuite <- function() { kret = smartpointerpointertest(k) val = kret$getValue() unittest("me oh my smartpointerpointertest-Derived", val) - #testSuite_verifyCount(2, k) - #testSuite_verifyCount(2, kret) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) } # pass by shared_ptr reference (mixed) @@ -332,8 +332,8 @@ testSuite <- function() { kret = smartpointerreftest(k) val = kret$getValue() unittest("me oh my smartpointerreftest-Derived", val) - #testSuite_verifyCount(2, k) - #testSuite_verifyCount(2, kret) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) } # pass by shared_ptr pointer reference (mixed) @@ -342,8 +342,8 @@ testSuite <- function() { kret = smartpointerpointerreftest(k) val = kret$getValue() unittest("me oh my smartpointerpointerreftest-Derived", val) - #testSuite_verifyCount(2, k) - #testSuite_verifyCount(2, kret) + testSuite_verifyCount(2, k) + testSuite_verifyCount(2, kret) } # pass by value (mixed) @@ -352,8 +352,8 @@ testSuite <- function() { kret = valuetest(k) val = kret$getValue() unittest("me oh my valuetest", val) # note slicing - #testSuite_verifyCount(1, k) - #testSuite_verifyCount(1, kret) + testSuite_verifyCount(1, k) + testSuite_verifyCount(1, kret) } # pass by pointer (mixed) @@ -362,8 +362,8 @@ testSuite <- function() { kret = pointertest(k) val = kret$getValue() unittest("me oh my pointertest-Derived", val) - #testSuite_verifyCount(1, k) - #testSuite_verifyCount(1, kret) + testSuite_verifyCount(1, k) + testSuite_verifyCount(1, kret) } # pass by ref (mixed) @@ -372,8 +372,8 @@ testSuite <- function() { kret = reftest(k) val = kret$getValue() unittest("me oh my reftest-Derived", val) - #testSuite_verifyCount(1, k) - #testSuite_verifyCount(1, kret) + testSuite_verifyCount(1, k) + testSuite_verifyCount(1, kret) } @@ -420,7 +420,7 @@ testSuite <- function() { testSuite_verifyCount(1, k) val = test3rdupcast(k) unittest("me oh my-3rdDerived", val) -# testSuite_verifyCount(1, k) + testSuite_verifyCount(1, k) } # diff --git a/Lib/r/rrun.swg b/Lib/r/rrun.swg index 798446128..3ffc02f28 100644 --- a/Lib/r/rrun.swg +++ b/Lib/r/rrun.swg @@ -15,8 +15,9 @@ extern "C" { #endif /* for raw pointer */ +#define SWIG_R_ConvertPtr(obj, pptr, type, flags) SWIG_R_ConvertPtrAndOwn(obj, pptr, type, flags, 0) #define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_R_ConvertPtr(obj, pptr, type, flags) -#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_R_ConvertPtr(obj, pptr, type, flags) +#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_R_ConvertPtrAndOwn(obj, pptr, type, flags, own) #define SWIG_NewPointerObj(ptr, type, flags) SWIG_R_NewPointerObj(ptr, type, flags) #include @@ -314,9 +315,11 @@ SWIG_R_NewPointerObj(void *ptr, swig_type_info *type, int flags) { /* Convert a pointer value */ SWIGRUNTIMEINLINE int -SWIG_R_ConvertPtr(SEXP obj, void **ptr, swig_type_info *ty, int flags) { +SWIG_R_ConvertPtrAndOwn(SEXP obj, void **ptr, swig_type_info *ty, int flags, int *own) { void *vptr; if (!obj) return SWIG_ERROR; + if (own) + *own = 0; if (obj == R_NilValue) { if (ptr) *ptr = NULL; return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; @@ -331,8 +334,15 @@ SWIG_R_ConvertPtr(SEXP obj, void **ptr, swig_type_info *ty, int flags) { } else { swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); int newmemory = 0; - if (ptr) *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ + if (ptr) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc, vptr, &newmemory); + if (newmemory == SWIG_CAST_NEW_MEMORY) { + assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ + if (own) + *own = *own | SWIG_CAST_NEW_MEMORY; + } + } } } else { if (ptr) *ptr = vptr; diff --git a/Lib/r/std_vector.i b/Lib/r/std_vector.i index 62478fe6a..98840c5dc 100644 --- a/Lib/r/std_vector.i +++ b/Lib/r/std_vector.i @@ -544,7 +544,7 @@ struct traits_asptr < std::vector > { static int asptr(SEXP obj, std::vector **val) { std::vector *p; - int res = SWIG_R_ConvertPtr(obj, (void**)&p, type_info< std::vector >(), 0); + int res = SWIG_ConvertPtr(obj, (void**)&p, type_info< std::vector >(), 0); if (SWIG_IsOK(res)) { if (val) *val = p; } @@ -827,7 +827,7 @@ static int asptr(SEXP obj, std::vector< std::vector > **val) { std::vector< std::vector > *p; Rprintf("vector of vectors - unsupported content\n"); - int res = SWIG_R_ConvertPtr(obj, (void**)&p, type_info< std::vector< std::vector > > (), 0); + int res = SWIG_ConvertPtr(obj, (void**)&p, type_info< std::vector< std::vector > > (), 0); if (SWIG_IsOK(res)) { if (val) *val = p; } From f2da4f2aded709e114bf8a4a1a3791f830a06681 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 26 Oct 2022 23:25:03 +0100 Subject: [PATCH 142/217] Improve R wrapper error message calling overloaded methods when incorrect types passed are passed to the overloaded methods. Old unhelpful error message: Error in f(...) : could not find function "f" Example of new improved error message: Error in use_count(k) : cannot find overloaded function for use_count with argtypes (NULL) --- CHANGES.current | 10 ++++++++++ Examples/test-suite/r/li_boost_shared_ptr_runme.R | 2 +- Source/Modules/r.cxx | 12 +++++++----- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 8331dfd66..a72acb5b0 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -11,3 +11,13 @@ Version 4.2.0 (in progress) [R] #2386 Fix memory leak in R shared_ptr wrappers. Fix leak when a cast up a class inheritance chain is required. +2022-10-26: wsfulton + [R] Improve R wrapper error message when calling overloaded methods + when incorrect types passed are passed to the overloaded methods. + + Old unhelpful error message: + Error in f(...) : could not find function "f" + + Example of new improved error message: + Error in use_count(k) : + cannot find overloaded function for use_count with argtypes (NULL) diff --git a/Examples/test-suite/r/li_boost_shared_ptr_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_runme.R index 1f7507337..ec8c66dcf 100644 --- a/Examples/test-suite/r/li_boost_shared_ptr_runme.R +++ b/Examples/test-suite/r/li_boost_shared_ptr_runme.R @@ -570,7 +570,7 @@ testSuite <- function() { k = m$SmartMemberValue; if (!is.null(k)) stop("expected null"); - #testSuite_verifyCount(0, k); # this does not work for nulls + testSuite_verifyCount(0, k); # this does not work for nulls # plain by value bNotCatched = F diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index e1fd422dd..e3d69329b 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -1566,7 +1566,8 @@ void R::dispatchFunction(Node *n) { Printv(f->code, "argtypes <- mapply(class, list(...));\n", "argv <- list(...);\n", - "argc <- length(argtypes);\n", NIL ); + "argc <- length(argtypes);\n", + "f <- NULL;\n", NIL); Printf(f->code, "# dispatch functions %d\n", nfunc); int cur_args = -1; @@ -1649,11 +1650,12 @@ void R::dispatchFunction(Node *n) { } } if (cur_args != -1) { - Printf(f->code, "} else {\n" - "stop(\"cannot find overloaded function for %s with argtypes (\"," - "toString(argtypes),\")\");\n" - "}", sfname); + Printf(f->code, "};\n"); } + Printf(f->code, "if (is.null(f)) {\n" + "stop(\"cannot find overloaded function for %s with argtypes (\"," + "toString(argtypes),\")\");\n" + "}", sfname); Printv(f->code, ";\nf(...)", NIL); Printv(f->code, ";\n}", NIL); Wrapper_print(f, sfile); From d6d83f4df4a76e98dfa872679c2466fc59fd9d5a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 27 Oct 2022 00:14:50 +0100 Subject: [PATCH 143/217] Overloading fixes for R and rtypecheck typemap - Fix for special variable $argtype expansion in rtypecheck typemap. - Remove unnecessary () brackets when using rtypecheck typemap for single parameter functions. - Add rtypecheck typemaps for shared_ptr so that NULL can be used in overloaded functions taking shared_ptr. --- CHANGES.current | 4 ++++ .../test-suite/r/li_boost_shared_ptr_runme.R | 8 +++---- Lib/r/boost_shared_ptr.i | 6 ++++++ Source/Modules/r.cxx | 21 +++++++++++-------- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index a72acb5b0..f15464e90 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -21,3 +21,7 @@ Version 4.2.0 (in progress) Example of new improved error message: Error in use_count(k) : cannot find overloaded function for use_count with argtypes (NULL) + +2022-10-27: wsfulton + [R] Allow NULL to be used in overloaded functions taking shared_ptr. + Also fixes special variable $argtype expansion in rtypecheck typemaps. diff --git a/Examples/test-suite/r/li_boost_shared_ptr_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_runme.R index ec8c66dcf..0b0a0b770 100644 --- a/Examples/test-suite/r/li_boost_shared_ptr_runme.R +++ b/Examples/test-suite/r/li_boost_shared_ptr_runme.R @@ -512,7 +512,7 @@ testSuite <- function() { testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); - delete_MemberVariables(m); # m.delete(); + delete_MemberVariables(m); testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); } @@ -532,7 +532,7 @@ testSuite <- function() { testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); - delete_MemberVariables(m); # m.delete(); + delete_MemberVariables(m); testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); } @@ -552,7 +552,7 @@ testSuite <- function() { testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); - delete_MemberVariables(m); # m.delete(); + delete_MemberVariables(m); testSuite_verifyCount(1, kmember); testSuite_verifyCount(1, k); } @@ -570,7 +570,7 @@ testSuite <- function() { k = m$SmartMemberValue; if (!is.null(k)) stop("expected null"); - testSuite_verifyCount(0, k); # this does not work for nulls + testSuite_verifyCount(0, k); # plain by value bNotCatched = F diff --git a/Lib/r/boost_shared_ptr.i b/Lib/r/boost_shared_ptr.i index 13f041fbb..fde6ae56b 100644 --- a/Lib/r/boost_shared_ptr.i +++ b/Lib/r/boost_shared_ptr.i @@ -400,6 +400,12 @@ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(rtype, TYPE)" +%typemap(rtypecheck) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "(extends($argtype, '$typemap(rtype, TYPE)') && length($arg) == 1) || is.null($arg)" + %typemap(scoercein) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index e3d69329b..c8b34cb54 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -1595,7 +1595,7 @@ void R::dispatchFunction(Node *n) { first_compare = false; } Printv(f->code, "if (", NIL); - for (p =pi, j = 0 ; j < num_arguments ; j++) { + for (p = pi, j = 0 ; j < num_arguments ; j++) { if (debugMode) { Swig_print_node(p); } @@ -1606,21 +1606,24 @@ void R::dispatchFunction(Node *n) { String *tmcheck = Swig_typemap_lookup("rtypecheck", p, "", 0); if (tmcheck) { - String *tmp = NewString(""); - Printf(tmp, "argv[[%d]]", j+1); - Replaceall(tmcheck, "$arg", tmp); - Printf(tmp, "argtype[%d]", j+1); - Replaceall(tmcheck, "$argtype", tmp); + String *tmp_argtype = NewStringf("argtypes[%d]", j+1); + Replaceall(tmcheck, "$argtype", tmp_argtype); + String *tmp_arg = NewStringf("argv[[%d]]", j+1); + Replaceall(tmcheck, "$arg", tmp_arg); if (tm) { Replaceall(tmcheck, "$rtype", tm); } if (debugMode) { Printf(stdout, "%s\n", tmcheck); } - Printf(f->code, "%s(%s)", - j == 0 ? "" : " && ", - tmcheck); + if (num_arguments == 1) { + Printf(f->code, "%s", tmcheck); + } else { + Printf(f->code, "%s(%s)", j == 0 ? "" : " && ", tmcheck); + } p = Getattr(p, "tmap:in:next"); + Delete(tmp_arg); + Delete(tmp_argtype); continue; } // Below should be migrated into rtypecheck typemaps From 973590ff915745ade6adf2ae6340db7bdcb94c5a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 28 Oct 2022 21:53:42 +0100 Subject: [PATCH 144/217] R rtypecheck typemaps Further switch to use rtypecheck typemaps instead of hard coded logic. The full switch to typemaps is deferred until swig-4.2 as it can't be fully backwards compatible. For now a warning is provided to help the transition. It provides the full typemap that should be placed into a user's interface file, for example: %typemap("rtype") int32_t * "integer" void testmethod(int32_t * i); void testmethod(); If there is no rtypecheck typemap for int32_t *, the warning shown is: example.i:7: Warning 750: Optional rtypecheck code is deprecated. Add the following typemap to fix as the next version of SWIG will not work without it: %typemap("rtypecheck") int32_t * %{ (is.integer($arg) || is.numeric($arg)) %} The warning is shown for any code that previously used "numeric", "integer" or "character" for the rtype typemap. Copying the rtypecheck typemap as shown into the user interface file will provide the appropriate fix and the warning will disappear. This is important to do as swig-4.2 will not be able to provide this helpful warning. --- CHANGES.current | 25 ++++++++++++++++++++++++ Lib/r/rtype.swg | 40 +++++++++++++++++++++++++++++++++++--- Source/Include/swigwarn.h | 6 +++++- Source/Modules/r.cxx | 41 +++++++++++++++++++++++++++------------ 4 files changed, 96 insertions(+), 16 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index f15464e90..bbfa22839 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -25,3 +25,28 @@ Version 4.2.0 (in progress) 2022-10-27: wsfulton [R] Allow NULL to be used in overloaded functions taking shared_ptr. Also fixes special variable $argtype expansion in rtypecheck typemaps. + +2022-10-28: wsfulton + [R] R rtypecheck typemaps + + Further switch to use rtypecheck typemaps instead of hard coded logic. + The full switch to typemaps is deferred until swig-4.2 as it can't be fully + backwards compatible. For now a warning is provided to help the + transition. It provides the full typemap that should be placed into + a user's interface file, for example: + + %typemap("rtype") int32_t * "integer" + void testmethod(int32_t * i); + void testmethod(); + + If there is no rtypecheck typemap for int32_t *, the warning shown is: + + example.i:7: Warning 750: Optional rtypecheck code is deprecated. Add the + following typemap to fix as the next version of SWIG will not work without it: + %typemap("rtypecheck") int32_t * %{ (is.integer($arg) || is.numeric($arg)) %} + + The warning is shown for any code that previously used "numeric", "integer" or + "character" for the rtype typemap. Copying the rtypecheck typemap as + shown into the user interface file will provide the appropriate fix and + the warning will disappear. This is important to do as swig-4.2 will + not be able to provide this helpful warning. diff --git a/Lib/r/rtype.swg b/Lib/r/rtype.swg index a9c067589..c9d68bec8 100644 --- a/Lib/r/rtype.swg +++ b/Lib/r/rtype.swg @@ -3,6 +3,7 @@ for use in class representations. */ +%typemap("rtype") bool, bool * "logical" %typemap("rtype") int, int *, int & "integer" %typemap("rtype") long, long *, long & "integer" %typemap("rtype") float, float*, float & "numeric" @@ -11,7 +12,6 @@ %typemap("rtype") char "character" %typemap("rtype") string, string *, string & "character" %typemap("rtype") std::string, std::string *, std::string & "character" -%typemap("rtype") bool, bool * "logical" %typemap("rtype") enum SWIGTYPE "character" %typemap("rtype") enum SWIGTYPE * "character" %typemap("rtype") enum SWIGTYPE *const& "character" @@ -30,8 +30,7 @@ %typemap("rtypecheck") int *, long * %{ is.integer($arg) || is.numeric($arg) %} - -%typemap("rtypecheck") float, double +%typemap("rtypecheck") float, float &, double, double & %{ is.numeric($arg) && length($arg) == 1 %} %typemap("rtypecheck") float *, double * %{ is.numeric($arg) %} @@ -41,6 +40,41 @@ %typemap("rtypecheck") bool * %{ is.logical($arg) %} +%typemap("rtypecheck") char + %{ is.character($arg) && length($arg) == 1 %} +%typemap("rtypecheck") char *, char ** + %{ is.character($arg) %} + +%typemap("rtypecheck") string, string & + %{ is.character($arg) && length($arg) == 1 %} +%typemap("rtypecheck") string * + %{ is.character($arg) %} + +%typemap("rtypecheck") std::string, std::string & + %{ is.character($arg) && length($arg) == 1 %} +%typemap("rtypecheck") std::string * + %{ is.character($arg) %} + +%typemap("rtypecheck") enum SWIGTYPE, enum SWIGTYPE *const&, enum SWIGTYPE &, const enum SWIGTYPE &, enum SWIGTYPE && + %{ is.character($arg) && length($arg) == 1 %} +%typemap("rtypecheck") enum SWIGTYPE * + %{ is.character($arg) %} + +#if 0 +// Replacement rtypecheck typemaps (for swig-4.2, see r.cxx) +%typemap("rtypecheck") SWIGTYPE * + %{ extends($argtype, '$R_class') || is.null($arg) %} + +%typemap("rtypecheck") SWIGTYPE &, SWIGTYPE && + %{ extends($argtype, '$R_class') && length($arg) == 1 %} + +%typemap("rtypecheck") SWIGTYPE *const& + %{ extends($argtype, '$*R_class') && length($arg) == 1 %} + +%typemap("rtypecheck") SWIGTYPE + %{ extends($argtype, '$&R_class') && length($arg) == 1 %} +#endif + /* Set up type checks to insure overloading precedence. We would like non pointer items to shadow pointer items, so that diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index fc379c014..f38607f92 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -257,7 +257,11 @@ #define WARN_PYTHON_INDENT_MISMATCH 740 -/* please leave 740-759 free for Python */ +/* please leave 740-749 free for Python */ + +#define WARN_R_MISSING_RTYPECHECK_TYPEMAP 750 + +/* please leave 750-759 free for R */ #define WARN_RUBY_WRONG_NAME 801 #define WARN_RUBY_MULTIPLE_INHERITANCE 802 diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index c8b34cb54..9b465a571 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -1600,7 +1600,7 @@ void R::dispatchFunction(Node *n) { Swig_print_node(p); } String *tm = Swig_typemap_lookup("rtype", p, "", 0); - if(tm) { + if (tm) { replaceRClass(tm, Getattr(p, "type")); } @@ -1610,9 +1610,7 @@ void R::dispatchFunction(Node *n) { Replaceall(tmcheck, "$argtype", tmp_argtype); String *tmp_arg = NewStringf("argv[[%d]]", j+1); Replaceall(tmcheck, "$arg", tmp_arg); - if (tm) { - Replaceall(tmcheck, "$rtype", tm); - } + replaceRClass(tmcheck, Getattr(p, "type")); if (debugMode) { Printf(stdout, "%s\n", tmcheck); } @@ -1627,23 +1625,42 @@ void R::dispatchFunction(Node *n) { continue; } // Below should be migrated into rtypecheck typemaps + // Preparation for this has started by warning in swig-4.1.1 for "numeric", "integer", "character" typemaps + // For swig-4.2: remove the code block below and uncomment typemaps marked 'Replacement rtypecheck typemaps' in rtype.swg. + // There is a slight difference in output as the typemap approach fixes some bugs due to a missing type resolution below if (tm) { + String *tmcode = NULL; Printf(f->code, "%s", j == 0 ? "" : " && "); + if (num_arguments != 1) + Printf(f->code, "("); + Printf(f->code, " "); if (Strcmp(tm, "numeric") == 0) { - Printf(f->code, "is.numeric(argv[[%d]])", j+1); + tmcode = NewString("is.numeric($arg)"); } else if (Strcmp(tm, "integer") == 0) { - Printf(f->code, "(is.integer(argv[[%d]]) || is.numeric(argv[[%d]]))", j+1, j+1); + tmcode = NewString("(is.integer($arg) || is.numeric($arg))"); } else if (Strcmp(tm, "character") == 0) { - Printf(f->code, "is.character(argv[[%d]])", j+1); + tmcode = NewString("is.character($arg)"); } else { if (SwigType_ispointer(Getattr(p, "type"))) - Printf(f->code, "(extends(argtypes[%d], '%s') || is.null(argv[[%d]]))", j+1, tm, j+1); + Printf(f->code, "extends(argtypes[%d], '%s') || is.null(argv[[%d]])", j+1, tm, j+1); else - Printf(f->code, "extends(argtypes[%d], '%s')", j+1, tm); + Printf(f->code, "extends(argtypes[%d], '%s') && length(argv[[%d]]) == 1", j+1, tm, j+1); } - } - if (!SwigType_ispointer(Getattr(p, "type"))) { - Printf(f->code, " && length(argv[[%d]]) == 1", j+1); + if (tmcode) { + if (!SwigType_ispointer(Getattr(p, "type"))) + Printf(tmcode, " && length($arg) == 1"); + Swig_warning(WARN_R_MISSING_RTYPECHECK_TYPEMAP, input_file, line_number, + "Optional rtypecheck code is deprecated. Add the following typemap to fix as the next version of SWIG will not work without it: %%typemap(\"rtypecheck\") %s %%{ %s %%}\n", + SwigType_str(Getattr(p, "type"), 0), tmcode); + String *tmp_arg = NewStringf("argv[[%d]]", j+1); + Replaceall(tmcode, "$arg", tmp_arg); + Printv(f->code, tmcode, NIL); + Delete(tmp_arg); + } + Printf(f->code, " "); + if (num_arguments != 1) + Printf(f->code, ")"); + Delete(tmcode); } p = Getattr(p, "tmap:in:next"); } From 52edda64c10b8f0ef0a86fdeb5c8d5db4ce62570 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 2 Nov 2022 19:57:02 +0000 Subject: [PATCH 145/217] Fix infinite loop handling non-type template parameters Fixes infinite loop due to () brackets in a non-type template parameter containing an expression Fixes #2418 Non-trivial expressions are still not qualified properly though. --- CHANGES.current | 6 ++++ Examples/test-suite/common.mk | 1 + Examples/test-suite/cpp14_enable_if_t.i | 34 +++++++++++++++++++ .../java/cpp14_enable_if_t_runme.java | 19 +++++++++++ Source/Swig/symbol.c | 11 ++++-- Source/Swig/typesys.c | 1 + 6 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 Examples/test-suite/cpp14_enable_if_t.i create mode 100644 Examples/test-suite/java/cpp14_enable_if_t_runme.java diff --git a/CHANGES.current b/CHANGES.current index bbfa22839..500ab4044 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -50,3 +50,9 @@ Version 4.2.0 (in progress) shown into the user interface file will provide the appropriate fix and the warning will disappear. This is important to do as swig-4.2 will not be able to provide this helpful warning. + +2022-11-02: wsfulton + #2418 Fix infinite loop handling non-type template parameters. + + Fixes infinite loop due to () brackets in a non-type template + parameter containing an expression. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 4681571e2..c52a74dd3 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -639,6 +639,7 @@ CPP11_TEST_BROKEN = \ # C++14 test cases. CPP14_TEST_CASES += \ cpp14_binary_integer_literals \ + cpp14_enable_if_t \ # Broken C++14 test cases. CPP14_TEST_BROKEN = \ diff --git a/Examples/test-suite/cpp14_enable_if_t.i b/Examples/test-suite/cpp14_enable_if_t.i new file mode 100644 index 000000000..a2e483380 --- /dev/null +++ b/Examples/test-suite/cpp14_enable_if_t.i @@ -0,0 +1,34 @@ +%module cpp14_enable_if_t + +// test use of enable_if_t but without full %template instantiation, that is no enable_if_t definition is parsed + +%inline %{ +#include +typedef int node_t; +typedef int position_t; + +template , bool> = true> + void enableif1(const A a, const B b) {} + +// tests non-type template parameters within () brackets - was causing an infinite loop, issue #2418 +template ), bool> = true> + void enableif2(const A a, const B b) {} + +template || std::is_same_v), bool> = true> + void enableif3(const A a, const B b) {} + +template or std::is_same_v) and (std::is_integral_v or std::is_same_v), bool> = true> + void enableif4(const A a, const B b) {} + +template and std::is_integral_v), bool> = true> + int enableif5(const A a, const B b) { + return a + b; + } + +void tester() { + enableif5(10, 20); +} +%} + +// non-type template parameters working well in SWIG, below is a simple workaround as the 3rd parameter is defaulted for enable_if_t (which is just SFINAE to give a nice C++ compiler error) +%template(enableif5) enableif5; // workaround diff --git a/Examples/test-suite/java/cpp14_enable_if_t_runme.java b/Examples/test-suite/java/cpp14_enable_if_t_runme.java new file mode 100644 index 000000000..ade061be3 --- /dev/null +++ b/Examples/test-suite/java/cpp14_enable_if_t_runme.java @@ -0,0 +1,19 @@ +import cpp14_enable_if_t.*; + +public class cpp14_enable_if_t_runme { + + static { + try { + System.loadLibrary("cpp14_enable_if_t"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + if (cpp14_enable_if_t.enableif5(10, 20) != 30) + throw new RuntimeException("enableif5 not working"); + } +} diff --git a/Source/Swig/symbol.c b/Source/Swig/symbol.c index d39696f5b..107b1caef 100644 --- a/Source/Swig/symbol.c +++ b/Source/Swig/symbol.c @@ -1518,7 +1518,8 @@ Node *Swig_symbol_isoverloaded(Node *n) { static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) { String *tprefix, *tsuffix; SwigType *qprefix; - List *targs; + String *targs; + List *targslist; Node *tempn; Symtab *tscope; Iterator ti; @@ -1541,12 +1542,15 @@ static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) { tprefix = SwigType_templateprefix(e); tsuffix = SwigType_templatesuffix(e); qprefix = Swig_symbol_type_qualify(tprefix, st); - targs = SwigType_parmlist(e); + 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(targs); ti.item;) { + 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); @@ -1568,6 +1572,7 @@ static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) { Delete(tprefix); Delete(tsuffix); Delete(targs); + Delete(targslist); #ifdef SWIG_DEBUG Printf(stderr, "symbol_temp_qual %s %s\n", e, qprefix); #endif diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 74384f860..4a11790c7 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1148,6 +1148,7 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) { 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. From 1bc3b63b1142e51e7d633f9e8de4e490f5022d1c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 5 Nov 2022 10:18:02 +0000 Subject: [PATCH 146/217] Correct ordering in CHANGES.current file --- CHANGES.current | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 500ab4044..f1e26932f 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,24 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== -2022-10-26: wsfulton - [R] #2386 Fix memory leak in R shared_ptr wrappers. - Fix leak when a cast up a class inheritance chain is required. +2022-11-02: wsfulton + #2418 Fix infinite loop handling non-type template parameters. -2022-10-26: wsfulton - [R] Improve R wrapper error message when calling overloaded methods - when incorrect types passed are passed to the overloaded methods. - - Old unhelpful error message: - Error in f(...) : could not find function "f" - - Example of new improved error message: - Error in use_count(k) : - cannot find overloaded function for use_count with argtypes (NULL) - -2022-10-27: wsfulton - [R] Allow NULL to be used in overloaded functions taking shared_ptr. - Also fixes special variable $argtype expansion in rtypecheck typemaps. + Fixes infinite loop due to () brackets in a non-type template + parameter containing an expression. 2022-10-28: wsfulton [R] R rtypecheck typemaps @@ -51,8 +38,21 @@ Version 4.2.0 (in progress) the warning will disappear. This is important to do as swig-4.2 will not be able to provide this helpful warning. -2022-11-02: wsfulton - #2418 Fix infinite loop handling non-type template parameters. +2022-10-27: wsfulton + [R] Allow NULL to be used in overloaded functions taking shared_ptr. + Also fixes special variable $argtype expansion in rtypecheck typemaps. - Fixes infinite loop due to () brackets in a non-type template - parameter containing an expression. +2022-10-26: wsfulton + [R] Improve R wrapper error message when calling overloaded methods + when incorrect types passed are passed to the overloaded methods. + + Old unhelpful error message: + Error in f(...) : could not find function "f" + + Example of new improved error message: + Error in use_count(k) : + cannot find overloaded function for use_count with argtypes (NULL) + +2022-10-26: wsfulton + [R] #2386 Fix memory leak in R shared_ptr wrappers. + Fix leak when a cast up a class inheritance chain is required. From 8ab66c3125159dbbd620d8bd54f85eef1e7ba5ad Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 5 Nov 2022 10:19:36 +0000 Subject: [PATCH 147/217] Add changes entry for -swiglib CMake fix --- CHANGES.current | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index f1e26932f..3cc2c6066 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2022-11-05: wsfulton + #2417 Fix -swiglib for Windows when building with CMake. + 2022-11-02: wsfulton #2418 Fix infinite loop handling non-type template parameters. From 86b3e6061758a8a44d106560280cd00cd4f0dd5c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 5 Nov 2022 17:13:30 +0000 Subject: [PATCH 148/217] rename cpp14_enable_if_t to cpp17_enable_if_t std::enable_if_t is in C++14, but std::is_integral_v is in C++17 --- Examples/test-suite/common.mk | 2 +- .../{cpp14_enable_if_t.i => cpp17_enable_if_t.i} | 2 +- ...nable_if_t_runme.java => cpp17_enable_if_t_runme.java} | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) rename Examples/test-suite/{cpp14_enable_if_t.i => cpp17_enable_if_t.i} (98%) rename Examples/test-suite/java/{cpp14_enable_if_t_runme.java => cpp17_enable_if_t_runme.java} (68%) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index c52a74dd3..d26f2505c 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -639,13 +639,13 @@ CPP11_TEST_BROKEN = \ # C++14 test cases. CPP14_TEST_CASES += \ cpp14_binary_integer_literals \ - cpp14_enable_if_t \ # Broken C++14 test cases. CPP14_TEST_BROKEN = \ # C++17 test cases. CPP17_TEST_CASES += \ + cpp17_enable_if_t \ cpp17_hex_floating_literals \ cpp17_nested_namespaces \ cpp17_nspace_nested_namespaces \ diff --git a/Examples/test-suite/cpp14_enable_if_t.i b/Examples/test-suite/cpp17_enable_if_t.i similarity index 98% rename from Examples/test-suite/cpp14_enable_if_t.i rename to Examples/test-suite/cpp17_enable_if_t.i index a2e483380..307237549 100644 --- a/Examples/test-suite/cpp14_enable_if_t.i +++ b/Examples/test-suite/cpp17_enable_if_t.i @@ -1,4 +1,4 @@ -%module cpp14_enable_if_t +%module cpp17_enable_if_t // test use of enable_if_t but without full %template instantiation, that is no enable_if_t definition is parsed diff --git a/Examples/test-suite/java/cpp14_enable_if_t_runme.java b/Examples/test-suite/java/cpp17_enable_if_t_runme.java similarity index 68% rename from Examples/test-suite/java/cpp14_enable_if_t_runme.java rename to Examples/test-suite/java/cpp17_enable_if_t_runme.java index ade061be3..25569f303 100644 --- a/Examples/test-suite/java/cpp14_enable_if_t_runme.java +++ b/Examples/test-suite/java/cpp17_enable_if_t_runme.java @@ -1,10 +1,10 @@ -import cpp14_enable_if_t.*; +import cpp17_enable_if_t.*; -public class cpp14_enable_if_t_runme { +public class cpp17_enable_if_t_runme { static { try { - System.loadLibrary("cpp14_enable_if_t"); + System.loadLibrary("cpp17_enable_if_t"); } catch (UnsatisfiedLinkError e) { System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); System.exit(1); @@ -13,7 +13,7 @@ public class cpp14_enable_if_t_runme { public static void main(String argv[]) { - if (cpp14_enable_if_t.enableif5(10, 20) != 30) + if (cpp17_enable_if_t.enableif5(10, 20) != 30) throw new RuntimeException("enableif5 not working"); } } From db9df1b3becb154e8fd5eb951ea96246d0c556d0 Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Sat, 5 Nov 2022 20:43:15 +0100 Subject: [PATCH 149/217] more tests for R --- .../r/extend_template_method_runme.R | 50 ++++++++++++++ .../r/li_attribute_template_runme.R | 68 +++++++++++++++++++ .../r/li_boost_shared_ptr_template_runme.R | 37 ++++++++++ .../r/smart_pointer_templatevariables_runme.R | 16 +++++ 4 files changed, 171 insertions(+) create mode 100644 Examples/test-suite/r/extend_template_method_runme.R create mode 100644 Examples/test-suite/r/li_attribute_template_runme.R create mode 100644 Examples/test-suite/r/li_boost_shared_ptr_template_runme.R create mode 100644 Examples/test-suite/r/smart_pointer_templatevariables_runme.R diff --git a/Examples/test-suite/r/extend_template_method_runme.R b/Examples/test-suite/r/extend_template_method_runme.R new file mode 100644 index 000000000..eaeb69a2a --- /dev/null +++ b/Examples/test-suite/r/extend_template_method_runme.R @@ -0,0 +1,50 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) +#source("unittest.R") + +dyn.load(paste("extend_template_method", .Platform$dynlib.ext, sep="")) +source("extend_template_method.R") +cacheMetaData(1) + + +em = ExtendMe() + +ret_double = em$do_stuff_double(1, 1.1) +unittest(ret_double, 1.1) + +ret_string = em$do_stuff_string(1, "hello there") +unittest(ret_string, "hello there") + +ret_double = em$do_overloaded_stuff(1.1) +unittest(ret_double, 1.1) + +ret_string = em$do_overloaded_stuff("hello there") +unittest(ret_string, "hello there") + + +unittest(ExtendMe_static_method(123), 123) + +em2 = ExtendMe(123) + +em = TemplateExtend() + +ret_double = em$do_template_stuff_double(1, 1.1) +unittest(ret_double, 1.1) + +ret_string = em$do_template_stuff_string(1, "hello there") +unittest(ret_string, "hello there") + + +ret_double = em$do_template_overloaded_stuff(1.1) +unittest(ret_double, 1.1) + +ret_string = em$do_template_overloaded_stuff("hello there") +unittest(ret_string, "hello there") + +unittest(TemplateExtend_static_template_method(123), 123) + + +em2 = TemplateExtend(123) + + +q(save="no") diff --git a/Examples/test-suite/r/li_attribute_template_runme.R b/Examples/test-suite/r/li_attribute_template_runme.R new file mode 100644 index 000000000..2f1510e29 --- /dev/null +++ b/Examples/test-suite/r/li_attribute_template_runme.R @@ -0,0 +1,68 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) +#source("unittest.R") + +dyn.load(paste("li_attribute_template", .Platform$dynlib.ext, sep="")) +source("li_attribute_template.R") +cacheMetaData(1) + + +# Check usage of template attributes +chell = Cintint(1, 2, 3) + +# Testing primitive by value attribute +unittest(chell$a, 1) + +chell$a = 3 +unittest(chell$a, 3) + +# Testing primitive by ref attribute +unittest(chell$b, 2) + +chell$b = 5 +unittest(chell$b, 5) + +# Testing string +chell$str = "abc" +unittest(chell$str, "abc") + +# Testing class by value +unittest(chell$d$value, 1) + +chell$d = Foo(2) +unittest(chell$d$value, 2) + +# Testing class by reference +unittest(chell$e$value, 2) + +chell$e = Foo(3) +unittest(chell$e$value, 3) + +chell$e$value = 4 +unittest(chell$e$value, 4) + + +# Testing moderately complex template by value +unittest(chell$f$first, 1) +unittest(chell$f$second, 2) + +pair = pair_intint(3, 4) +chell$f = pair +unittest(chell$f$first, 3) +unittest(chell$f$second, 4) + +# Testing moderately complex template by ref +unittest(chell$g$first, 2) +unittest(chell$g$second, 3) + +pair = pair_intint(4, 5) +chell$g = pair +unittest(chell$g$first, 4) +unittest(chell$g$second, 5) + +chell$g$first = 6 +chell$g$second = 7 +unittest(chell$g$first, 6) +unittest(chell$g$second, 7) + +q(save="no") diff --git a/Examples/test-suite/r/li_boost_shared_ptr_template_runme.R b/Examples/test-suite/r/li_boost_shared_ptr_template_runme.R new file mode 100644 index 000000000..8391b31f4 --- /dev/null +++ b/Examples/test-suite/r/li_boost_shared_ptr_template_runme.R @@ -0,0 +1,37 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) +#source("unittest.R") + +dyn.load(paste("li_boost_shared_ptr_template", .Platform$dynlib.ext, sep="")) +source("li_boost_shared_ptr_template.R") +cacheMetaData(1) + +b = BaseINTEGER() +d = DerivedINTEGER() + +unittest(BaseINTEGER_bar(b), 1) +unittest(b$bar(), 1) + +unittest(DerivedINTEGER_bar(d), 2) +unittest(d$bar(), 2) + +unittest(bar_getter(b), 1) +unittest(bar_getter(d), 2) + + +b = BaseDefaultInt() +d = DerivedDefaultInt() +d2 = DerivedDefaultInt2() + +unittest(BaseDefaultInt_bar2(b), 3) +unittest(b$bar2(), 3) + +unittest(DerivedDefaultInt_bar2(d), 4) +unittest(d$bar2(), 4) + +unittest(bar2_getter(b), 3) +unittest(bar2_getter(d), 4) +unittest(bar2_getter(d2), 4) + + +q(save="no") diff --git a/Examples/test-suite/r/smart_pointer_templatevariables_runme.R b/Examples/test-suite/r/smart_pointer_templatevariables_runme.R new file mode 100644 index 000000000..11b9f2e58 --- /dev/null +++ b/Examples/test-suite/r/smart_pointer_templatevariables_runme.R @@ -0,0 +1,16 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) +#source("unittest.R") + +dyn.load(paste("smart_pointer_templatevariables", .Platform$dynlib.ext, sep="")) +source("smart_pointer_templatevariables.R") +cacheMetaData(1) + + +d = DiffImContainerPtr_D(create(1234, 5678)) +unittest(d$id, 1234) + +d$id = 4321 +unittest(d$id, 4321) + +q(save="no") From 62be0de3d04b1843b9d63d99cd08c40360f8c1d7 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 6 Nov 2022 16:52:59 +0000 Subject: [PATCH 150/217] Workaround for incomplete or/and keyword support in VC++ --- Examples/test-suite/cpp17_enable_if_t.i | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Examples/test-suite/cpp17_enable_if_t.i b/Examples/test-suite/cpp17_enable_if_t.i index 307237549..b361775d0 100644 --- a/Examples/test-suite/cpp17_enable_if_t.i +++ b/Examples/test-suite/cpp17_enable_if_t.i @@ -3,6 +3,11 @@ // test use of enable_if_t but without full %template instantiation, that is no enable_if_t definition is parsed %inline %{ +#if defined(_MSC_VER) && _MSC_VER < 1920 +#define or || +#define and && +#endif + #include typedef int node_t; typedef int position_t; From ea3f043920f2f8a208e9171b9996a2279cad2512 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 8 Nov 2022 09:11:35 +0000 Subject: [PATCH 151/217] SwigValueWrapper and SwigType * correction Modifying the type by adding in SwigValueWrapper needs to follow the normal SwigType conventions for correct and proper type handling. --- Source/Swig/typesys.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 4a11790c7..fc2224bf5 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1565,11 +1565,7 @@ SwigType *SwigType_alttype(const SwigType *t, int local_tmap) { } 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); + w = NewStringf("SwigValueWrapper<(%s)>", td); } Delete(td); return w; From 2acdfd77e9e498d604e1dc0636cf675f9ce10244 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 9 Nov 2022 22:11:27 +0000 Subject: [PATCH 152/217] SwigType * handling corrections Further corrections to pass SwigType * to methods expecting types instead of passing readable type strings. Required reworking code that adds a fake inheritance for smart pointers using the smartptr feature. Swig_smartptr_upcast() added as a support function for this. --- Source/Modules/csharp.cxx | 21 ++++++------- Source/Modules/d.cxx | 19 +++++------- Source/Modules/java.cxx | 21 ++++++------- Source/Modules/swigmod.h | 1 + Source/Modules/typepass.cxx | 30 +++++------------- Source/Modules/utils.cxx | 62 +++++++++++++++++++++++++++++++++++++ Source/Swig/typemap.c | 3 ++ 7 files changed, 98 insertions(+), 59 deletions(-) diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 240a002b4..8d4b03151 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -1744,35 +1744,32 @@ public: Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name); - String *classname = SwigType_namestr(c_classname); - String *baseclassname = SwigType_namestr(c_baseclassname); if (smart) { + SwigType *bsmart = Swig_smartptr_upcast(smart, c_classname, c_baseclassname); String *smartnamestr = SwigType_namestr(smart); - String *bsmartnamestr = SwigType_namestr(smart); - - // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates - SwigType *rclassname = SwigType_typedef_resolve_all(classname); - SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname); - Replaceall(bsmartnamestr, rclassname, rbaseclassname); + String *bsmartnamestr = SwigType_namestr(bsmart); Printv(upcasts_code, "SWIGEXPORT ", bsmartnamestr, " * SWIGSTDCALL ", wname, "(", smartnamestr, " *jarg1) {\n", " return jarg1 ? new ", bsmartnamestr, "(*jarg1) : 0;\n" "}\n", "\n", NIL); - Delete(rbaseclassname); - Delete(rclassname); Delete(bsmartnamestr); Delete(smartnamestr); + Delete(bsmart); } else { + String *classname = SwigType_namestr(c_classname); + String *baseclassname = SwigType_namestr(c_baseclassname); + Printv(upcasts_code, "SWIGEXPORT ", baseclassname, " * SWIGSTDCALL ", wname, "(", classname, " *jarg1) {\n", " return (", baseclassname, " *)jarg1;\n" "}\n", "\n", NIL); + + Delete(baseclassname); + Delete(classname); } - Delete(baseclassname); - Delete(classname); Delete(wname); } diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index 31f300f2e..ecf931633 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -3374,19 +3374,15 @@ private: String *upcast_name = Swig_name_member(getNSpace(), d_class_name, (smart != 0 ? "SmartPtrUpcast" : "Upcast")); String *upcast_wrapper_name = Swig_name_wrapper(upcast_name); - writeImDModuleFunction(upcast_name, "void*", "(void* objectRef)", - upcast_wrapper_name); + writeImDModuleFunction(upcast_name, "void*", "(void* objectRef)", upcast_wrapper_name); String *classname = SwigType_namestr(c_classname); String *baseclassname = SwigType_namestr(c_baseclassname); - if (smart) { - String *smartnamestr = SwigType_namestr(smart); - String *bsmartnamestr = SwigType_namestr(smart); - // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates - SwigType *rclassname = SwigType_typedef_resolve_all(classname); - SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname); - Replaceall(bsmartnamestr, rclassname, rbaseclassname); + if (smart) { + SwigType *bsmart = Swig_smartptr_upcast(smart, c_classname, c_baseclassname); + String *smartnamestr = SwigType_namestr(smart); + String *bsmartnamestr = SwigType_namestr(bsmart); Printv(upcasts_code, "SWIGEXPORT ", bsmartnamestr, " * ", upcast_wrapper_name, @@ -3395,10 +3391,9 @@ private: "}\n", "\n", NIL); - Delete(rbaseclassname); - Delete(rclassname); Delete(bsmartnamestr); Delete(smartnamestr); + Delete(bsmart); } else { Printv(upcasts_code, "SWIGEXPORT ", baseclassname, " * ", upcast_wrapper_name, @@ -3413,8 +3408,8 @@ private: Delete(baseclassname); Delete(classname); - Delete(upcast_name); Delete(upcast_wrapper_name); + Delete(upcast_name); Delete(smart); } diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 773945af2..d625d0476 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -1883,16 +1883,10 @@ public: Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method_name); - String *classname = SwigType_namestr(c_classname); - String *baseclassname = SwigType_namestr(c_baseclassname); if (smart) { + SwigType *bsmart = Swig_smartptr_upcast(smart, c_classname, c_baseclassname); String *smartnamestr = SwigType_namestr(smart); - String *bsmartnamestr = SwigType_namestr(smart); - - // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates - SwigType *rclassname = SwigType_typedef_resolve_all(classname); - SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname); - Replaceall(bsmartnamestr, rclassname, rbaseclassname); + String *bsmartnamestr = SwigType_namestr(bsmart); Printv(upcasts_code, "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", @@ -1905,11 +1899,13 @@ public: " return baseptr;\n" "}\n", "\n", NIL); - Delete(rbaseclassname); - Delete(rclassname); Delete(bsmartnamestr); Delete(smartnamestr); + Delete(bsmart); } else { + String *classname = SwigType_namestr(c_classname); + String *baseclassname = SwigType_namestr(c_baseclassname); + Printv(upcasts_code, "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", " jlong baseptr = 0;\n" @@ -1918,10 +1914,11 @@ public: " *(", baseclassname, " **)&baseptr = *(", classname, " **)&jarg1;\n" " return baseptr;\n" "}\n", "\n", NIL); + + Delete(baseclassname); + Delete(classname); } - Delete(baseclassname); - Delete(classname); Delete(wname); Delete(jniname); } diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index c605edf9d..dfeb2bace 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -423,6 +423,7 @@ void Wrapper_cast_dispatch_mode_set(int); void Wrapper_naturalvar_mode_set(int); void clean_overloaded(Node *n); +SwigType *Swig_smartptr_upcast(SwigType *smart, SwigType *c_classname, SwigType *c_baseclassname); extern "C" { const char *Swig_to_string(DOH *object, int count = -1); diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index 2a1dadf73..4a2a9df90 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -254,7 +254,7 @@ class TypePass:private Dispatcher { int i; for (i = 0; i < len; i++) { Node *n = Getitem(ilist, i); - String *bname = Getattr(n, "name"); + SwigType *bname = Getattr(n, "name"); Node *bclass = n; /* Getattr(n,"class"); */ Hash *scopes = Getattr(bclass, "typescope"); SwigType_inherit(clsname, bname, cast, 0); @@ -266,36 +266,20 @@ class TypePass:private Dispatcher { /* Record a (fake) inheritance relationship between smart pointer and smart pointer to base class, so that smart pointer upcasts are automatically generated. */ - SwigType *bsmart = Copy(smart); - - // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates - SwigType *rclsname = SwigType_typedef_resolve_all(clsname); - SwigType *rbname = SwigType_typedef_resolve_all(bname); - int replace_count = Replaceall(bsmart, rclsname, rbname); - if (replace_count == 0) { - // If no replacement made, it will be because rclsname is fully resolved, but the - // type in the smartptr feature used a typedef or not fully resolved name. - String *firstname = Getattr(first, "name"); - Replaceall(bsmart, firstname, rbname); - } - // The code above currently creates a smartptr of the base class by substitution, replacing Derived - // with Base resulting in something like: 'smartptr< Derived >' from 'smartptr< Base >'. Instead - // the feature:smartptr should be used as it also contains 'smartptr< Base >' as specified by the user. - // A similar fix should also be done in upcastsCode in java.cxx, csharp.cxx and writeClassUpcast in d.cxx. - // Printf(stdout, "smartcomparison %s <=> %s\n", SwigType_namestr(bsmart), Getattr(bclass, "feature:smartptr")); - - Delete(rclsname); - Delete(rbname); + SwigType *bsmart = Swig_smartptr_upcast(smart, clsname, bname); String *smartnamestr = SwigType_namestr(smart); String *bsmartnamestr = SwigType_namestr(bsmart); + /* construct casting code */ String *convcode = NewStringf("\n *newmemory = SWIG_CAST_NEW_MEMORY;\n return (void *) new %s(*(%s *)$from);\n", bsmartnamestr, smartnamestr); - Delete(bsmartnamestr); - Delete(smartnamestr); + /* setup inheritance relationship between smart pointer templates */ SwigType_inherit(smart, bsmart, 0, convcode); if (!GetFlag(bclass, "feature:smartptr")) Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Base class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(bclass, "name")), SwigType_namestr(Getattr(first, "name"))); + + Delete(bsmartnamestr); + Delete(smartnamestr); Delete(convcode); Delete(bsmart); } diff --git a/Source/Modules/utils.cxx b/Source/Modules/utils.cxx index de6f87d8c..2072b73fa 100644 --- a/Source/Modules/utils.cxx +++ b/Source/Modules/utils.cxx @@ -115,6 +115,68 @@ void Swig_set_max_hash_expand(int count) { SetMaxHashExpand(count); } +/* ----------------------------------------------------------------------------- + * misc_identifier_fix() + * + * If a template, return template with all template parameters fully resolved. + * + * This is a copy and modification of feature_identifier_fix and typemap_identifier_fix. + * ----------------------------------------------------------------------------- */ + +static SwigType *misc_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; +} + +/* ----------------------------------------------------------------------------- + * Swig_smartptr_upcast() + * + * Replace classname with baseclassname in smart (smart pointer) to morph smart into a + * smart pointer containing the base class instead of the given classname. + * All parameters should be fully qualified types. + * ----------------------------------------------------------------------------- */ + +SwigType *Swig_smartptr_upcast(SwigType *smart, SwigType *classname, SwigType *baseclassname) { + SwigType *bsmart = Copy(smart); + + SwigType *rclassname = SwigType_typedef_resolve_all(classname); + SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname); + + int replace_count = Replaceall(bsmart, rclassname, rbaseclassname); + if (replace_count == 0) { + // If no replacement made, it will be because rclassname is fully resolved, but the + // type in the smartptr feature used a typedef or is not a fully resolved name. + replace_count = Replaceall(bsmart, classname, rbaseclassname); + if (replace_count == 0) { + // Next try with all the template parameters in the smartptr resolved + Delete(bsmart); + SwigType *bsmart = misc_identifier_fix(smart); + if (bsmart) { + replace_count = Replaceall(bsmart, rclassname, rbaseclassname); + } + assert(replace_count); // failed to substitute + } + } + + Delete(rbaseclassname); + Delete(rclassname); + return bsmart; +} + + extern "C" { /* ----------------------------------------------------------------------------- diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index f0dee59d9..28e87702c 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -69,6 +69,8 @@ static Hash *typemaps; * resolving the template parameters. * * This is a copy and modification of feature_identifier_fix in parser.y. + * Also, Swig_smartptr_upcast() could be removed if SwigType_typedef_resolve_all + * is fixed to resolve all template parameters like below. * ----------------------------------------------------------------------------- */ static SwigType *typemap_identifier_fix(const SwigType *s) { @@ -102,6 +104,7 @@ static Hash *get_typemap(const SwigType *type) { dtype = Swig_symbol_type_qualify(ty, 0); type = dtype; Delete(ty); + Delete(rty); } /* remove unary scope operator (::) prefix indicating global scope for looking up in the hashmap */ From 6a9be797e127d83c1f1de77270bb8b93110dd495 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 12 Nov 2022 06:42:36 +0000 Subject: [PATCH 153/217] SwigType * handling corrections - mangling Further corrections to pass SwigType * to methods expecting types instead of passing readable type strings. Swig_string_mangle() takes a generic String *, but it was calling functions that require SwigType *. Swig_string_mangle_type() is now provided for SwigType *r. The special template handling on types now occurs in this function. --- Source/Modules/go.cxx | 12 ++++----- Source/Modules/lang.cxx | 4 ++- Source/Modules/octave.cxx | 2 +- Source/Modules/tcl8.cxx | 8 +++--- Source/Swig/fragment.c | 6 ++--- Source/Swig/misc.c | 51 +++++++++++++++++++++------------------ Source/Swig/naming.c | 5 +++- Source/Swig/swig.h | 1 + Source/Swig/typemap.c | 4 +-- 9 files changed, 51 insertions(+), 42 deletions(-) diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index bf63bec63..0d6ee958b 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -4656,8 +4656,8 @@ private: * 'X'. * ---------------------------------------------------------------------- */ - String *exportedName(String *name) { - String *copy = Copy(name); + String *exportedName(SwigType *name) { + SwigType *copy = Copy(name); char c = *Char(copy); if (islower(c)) { char l[2]; @@ -4677,7 +4677,7 @@ private: u[2] = '\0'; Replace(copy, l, u, DOH_REPLACE_FIRST); } - String *ret = Swig_name_mangle(copy); + String *ret = Swig_string_mangle_type(copy); Delete(copy); return ret; } @@ -5556,11 +5556,11 @@ private: return NewString("int"); } - String *type = Getattr(n, "enumtype"); + SwigType *type = Getattr(n, "enumtype"); assert(type); char *p = Char(type); int len = Len(type); - String *s = NewString(""); + SwigType *s = NewString(""); bool capitalize = true; for (int i = 0; i < len; ++i, ++p) { if (*p == ':') { @@ -5576,7 +5576,7 @@ private: } } - ret = Swig_name_mangle(s); + ret = Swig_string_mangle_type(s); Delete(s); return ret; } diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 1e10e51d6..b88f66549 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -1310,9 +1310,11 @@ int Language::staticmemberfunctionHandler(Node *n) { else cname = NewStringf("%s::%s", sname, name); } else { - String *mname = Swig_name_mangle(ClassName); + String *classname_str = SwigType_namestr(ClassName); + String *mname = Swig_name_mangle(classname_str); cname = Swig_name_member(NSpace, mname, name); Delete(mname); + Delete(classname_str); } mrename = Swig_name_member(NSpace, ClassPrefix, symname); diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index 352105b9b..aba76624d 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -946,7 +946,7 @@ public: // This is a bug, due to the fact that swig_type -> octave_class mapping // is 1-to-n. static Hash *emitted = NewHash(); - String *mangled_classname = Swig_name_mangle(Getattr(n, "name")); + String *mangled_classname = Swig_string_mangle_type(Getattr(n, "name")); if (Getattr(emitted, mangled_classname)) { Delete(mangled_classname); return SWIG_NOWRAP; diff --git a/Source/Modules/tcl8.cxx b/Source/Modules/tcl8.cxx index 975230e84..12a65e9b6 100644 --- a/Source/Modules/tcl8.cxx +++ b/Source/Modules/tcl8.cxx @@ -712,7 +712,7 @@ public: virtual int classHandler(Node *n) { static Hash *emitted = NewHash(); String *mangled_classname = 0; - String *real_classname = 0; + SwigType *real_classname = 0; have_constructor = 0; have_destructor = 0; @@ -740,7 +740,7 @@ public: return SWIG_ERROR; real_classname = Getattr(n, "name"); - mangled_classname = Swig_name_mangle(real_classname); + mangled_classname = Swig_string_mangle_type(real_classname); if (Getattr(emitted, mangled_classname)) return SWIG_NOWRAP; @@ -806,7 +806,7 @@ public: int index = 0; b = First(baselist); while (b.item) { - String *bname = Getattr(b.item, "name"); + SwigType *bname = Getattr(b.item, "name"); if ((!bname) || GetFlag(b.item, "feature:ignore") || (!Getattr(b.item, "module"))) { b = Next(b); continue; @@ -816,7 +816,7 @@ public: Printv(base_classes, bname, " ", NIL); Printv(base_class_init, " ", bname, "Ptr::constructor $ptr\n", NIL); } - String *bmangle = Swig_name_mangle(bname); + String *bmangle = Swig_string_mangle_type(bname); // Printv(f_wrappers,"extern swig_class _wrap_class_", bmangle, ";\n", NIL); // Printf(base_class,"&_wrap_class_%s",bmangle); Printf(base_class, "0"); diff --git a/Source/Swig/fragment.c b/Source/Swig/fragment.c index 03b231fa1..099eb0ef7 100644 --- a/Source/Swig/fragment.c +++ b/Source/Swig/fragment.c @@ -41,7 +41,7 @@ void Swig_fragment_register(Node *fragment) { String *type = Getattr(fragment, "type"); if (type) { SwigType *rtype = SwigType_typedef_resolve_all(type); - String *mangle = Swig_string_mangle(type); + String *mangle = Swig_string_mangle_type(type); Append(name, mangle); Delete(mangle); Delete(rtype); @@ -106,7 +106,7 @@ void Swig_fragment_emit(Node *n) { type = Getattr(n, "type"); if (type) { - mangle = Swig_string_mangle(type); + mangle = Swig_string_mangle_type(type); } if (debug) @@ -162,7 +162,7 @@ void Swig_fragment_emit(Node *n) { SwigType *rtype = SwigType_typedef_resolve_all(type); if (!Equal(type, rtype)) { String *name = Copy(Getattr(n, "value")); - String *mangle = Swig_string_mangle(type); + String *mangle = Swig_string_mangle_type(type); Append(name, mangle); Setfile(name, Getfile(n)); Setline(name, Getline(n)); diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index 7d1119c5e..af0b24951 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -702,6 +702,31 @@ String *Swig_string_typecode(String *s) { return ns; } +/* ----------------------------------------------------------------------------- + * Swig_string_mangle_type() + * + * Same as Swig_string_mangle, but converting internal SwigType * to a human + * readable string of the type (for templates). Simplifies a type that is a + * template to the default template if possible. + * ----------------------------------------------------------------------------- */ + +String *Swig_string_mangle_type(const SwigType *s) { + String *mangled = 0; + 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; + } + mangled = Swig_string_mangle(b); + Delete(b); + return mangled; +} + /* ----------------------------------------------------------------------------- * Swig_string_mangle() * @@ -725,32 +750,12 @@ String *Swig_string_typecode(String *s) { * ----------------------------------------------------------------------------- */ 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); + + pc = cb = Char(s); while (*pc) { char c = *pc; if (isalnum((int) c) || (c == '_')) { @@ -856,9 +861,7 @@ String *Swig_string_mangle(const String *s) { } ++pc; } - Delete(b); return result; -#endif } String *Swig_string_emangle(String *s) { diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index c4613f6c6..da70b21dd 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -196,9 +196,11 @@ String *Swig_name_wrapper(const_String_or_char_ptr fname) { 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; + String *rmembername; char *cname; rclassname = SwigType_namestr(classname); + rmembername = SwigType_namestr(membername); 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))) { @@ -206,9 +208,10 @@ String *Swig_name_member(const_String_or_char_ptr nspace, const_String_or_char_p } replace_nspace(r, nspace); Replace(r, "%c", cname, DOH_REPLACE_ANY); - Replace(r, "%m", membername, DOH_REPLACE_ANY); + Replace(r, "%m", rmembername, DOH_REPLACE_ANY); /* name_mangle(r); */ Delete(rclassname); + Delete(rmembername); return r; } diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 19e61b455..d0156e53f 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -324,6 +324,7 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern int Swig_storage_isstatic(Node *n); extern String *Swig_string_escape(String *s); extern String *Swig_string_mangle(const String *s); + extern String *Swig_string_mangle_type(const SwigType *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); diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index 28e87702c..7132ab700 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -1293,7 +1293,7 @@ static void typemap_merge_fragment_kwargs(Parm *kw) { reattach_kw = prev_kw; } if (kwtype) { - String *mangle = Swig_string_mangle(kwtype); + String *mangle = Swig_string_mangle_type(kwtype); Append(fragment, mangle); Delete(mangle); /* Remove 'type' from kwargs so it's not duplicated later */ @@ -1541,7 +1541,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No Delete(parm_sublist); } if (kwtype) { - String *mangle = Swig_string_mangle(kwtype); + String *mangle = Swig_string_mangle_type(kwtype); Append(value, mangle); Delete(mangle); } From 3364c18d06a0d5c308c9cd8c12a416e8df657a81 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 12 Nov 2022 09:06:26 +0000 Subject: [PATCH 154/217] Remove unused code in mzscheme.cxx --- Source/Modules/mzscheme.cxx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx index e22f8bb7a..c3ac2d415 100644 --- a/Source/Modules/mzscheme.cxx +++ b/Source/Modules/mzscheme.cxx @@ -641,8 +641,6 @@ public: * classHandler() * ------------------------------------------------------------ */ virtual int classHandler(Node *n) { - String *mangled_classname = 0; - String *real_classname = 0; String *scm_structname = NewString(""); SwigType *ctype_ptr = NewStringf("p.%s", getClassType()); @@ -663,9 +661,6 @@ public: Printv(scm_structname, struct_name, NIL); Replaceall(scm_structname, "_", "-"); - real_classname = Getattr(n, "name"); - mangled_classname = Swig_name_mangle(real_classname); - Printv(fieldnames_tab, "static const char *_swig_struct_", cls_swigtype, "_field_names[] = { \n", NIL); Printv(convert_proto_tab, "static Scheme_Object *_swig_convert_struct_", cls_swigtype, "(", SwigType_str(ctype_ptr, "ptr"), ");\n", NIL); @@ -695,7 +690,6 @@ public: " = SWIG_MzScheme_new_scheme_struct(menv, \"", scm_structname, "\", ", "_swig_struct_", cls_swigtype, "_field_names_cnt,", "(char**) _swig_struct_", cls_swigtype, "_field_names);\n", NIL); - Delete(mangled_classname); Delete(swigtype_ptr); swigtype_ptr = 0; Delete(fieldnames_tab); From 46f27784127b95a51561a01ae453d8c875b00d06 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 12 Nov 2022 09:18:19 +0000 Subject: [PATCH 155/217] Consolidate name mangling functions Swig_string_mangle => Swig_name_mangle_string Swig_name_mangle => Swig_name_mangle_string Swig_string_mangle_type => Swig_name_mangle_type --- Source/Modules/go.cxx | 8 +- Source/Modules/guile.cxx | 2 +- Source/Modules/javascript.cxx | 2 +- Source/Modules/lang.cxx | 6 +- Source/Modules/lua.cxx | 4 +- Source/Modules/mzscheme.cxx | 4 +- Source/Modules/octave.cxx | 2 +- Source/Modules/ruby.cxx | 2 +- Source/Modules/tcl8.cxx | 4 +- Source/Preprocessor/cpp.c | 4 +- Source/Swig/cwrap.c | 14 +-- Source/Swig/fragment.c | 6 +- Source/Swig/misc.c | 168 +-------------------------------- Source/Swig/naming.c | 169 +++++++++++++++++++++++++++++++--- Source/Swig/swig.h | 5 +- Source/Swig/typemap.c | 4 +- 16 files changed, 194 insertions(+), 210 deletions(-) diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index 0d6ee958b..27e3060bf 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -4677,7 +4677,7 @@ private: u[2] = '\0'; Replace(copy, l, u, DOH_REPLACE_FIRST); } - String *ret = Swig_string_mangle_type(copy); + String *ret = Swig_name_mangle_type(copy); Delete(copy); return ret; } @@ -4725,7 +4725,7 @@ private: Append(nw, c3); Delete(c2); Delete(c3); - String *ret = Swig_name_mangle(nw); + String *ret = Swig_name_mangle_string(nw); Delete(nw); return ret; } @@ -4742,7 +4742,7 @@ private: String *buildGoWrapperName(String *name, String *overname) { String *s1 = NewString("_swig_wrap_"); Append(s1, name); - String *s2 = Swig_name_mangle(s1); + String *s2 = Swig_name_mangle_string(s1); Delete(s1); if (overname) { Append(s2, overname); @@ -5576,7 +5576,7 @@ private: } } - ret = Swig_string_mangle_type(s); + ret = Swig_name_mangle_type(s); Delete(s); return ret; } diff --git a/Source/Modules/guile.cxx b/Source/Modules/guile.cxx index 605e03197..8ce44d069 100644 --- a/Source/Modules/guile.cxx +++ b/Source/Modules/guile.cxx @@ -1396,7 +1396,7 @@ public: SwigType *ct = NewStringf("p.%s", Getattr(n, "name")); swigtype_ptr = SwigType_manglestr(ct); - String *mangled_classname = Swig_name_mangle(Getattr(n, "sym:name")); + String *mangled_classname = Swig_name_mangle_string(Getattr(n, "sym:name")); /* Export clientdata structure */ Printf(f_runtime, "static swig_guile_clientdata _swig_guile_clientdata%s = { NULL, SCM_EOL };\n", mangled_classname); diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx index 17effc220..50d7a7cef 100644 --- a/Source/Modules/javascript.cxx +++ b/Source/Modules/javascript.cxx @@ -1461,7 +1461,7 @@ Hash *JSEmitter::createNamespaceEntry(const char *_name, const char *parent, con Hash *entry = NewHash(); String *name = NewString(_name); Setattr(entry, NAME, Swig_scopename_last(name)); - Setattr(entry, NAME_MANGLED, Swig_name_mangle(name)); + Setattr(entry, NAME_MANGLED, Swig_name_mangle_string(name)); Setattr(entry, PARENT, NewString(parent)); Setattr(entry, PARENT_MANGLED, NewString(parent_mangled)); diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index b88f66549..0aecc70ad 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -1311,7 +1311,7 @@ int Language::staticmemberfunctionHandler(Node *n) { cname = NewStringf("%s::%s", sname, name); } else { String *classname_str = SwigType_namestr(ClassName); - String *mname = Swig_name_mangle(classname_str); + String *mname = Swig_name_mangle_string(classname_str); cname = Swig_name_member(NSpace, mname, name); Delete(mname); Delete(classname_str); @@ -1321,7 +1321,7 @@ int Language::staticmemberfunctionHandler(Node *n) { if (Extend) { String *code = Getattr(n, "code"); String *defaultargs = Getattr(n, "defaultargs"); - String *mangled = Swig_name_mangle(mrename); + String *mangled = Swig_name_mangle_string(mrename); Delete(mrename); mrename = mangled; @@ -1335,7 +1335,7 @@ int Language::staticmemberfunctionHandler(Node *n) { if (!defaultargs) { /* Hmmm. An added static member. We have to create a little wrapper for this */ - String *mangled_cname = Swig_name_mangle(cname); + String *mangled_cname = Swig_name_mangle_string(cname); Swig_add_extension_code(n, mangled_cname, parms, type, code, CPlusPlus, 0); Setattr(n, "extendname", mangled_cname); Delete(mangled_cname); diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx index d3cf96b52..96e5706ed 100644 --- a/Source/Modules/lua.cxx +++ b/Source/Modules/lua.cxx @@ -1269,7 +1269,7 @@ public: full_proxy_class_name = NewStringf("%s.%s", nspace, proxy_class_name); assert(full_proxy_class_name); - mangled_full_proxy_class_name = Swig_name_mangle(full_proxy_class_name); + mangled_full_proxy_class_name = Swig_name_mangle_string(full_proxy_class_name); SwigType *t = Copy(Getattr(n, "name")); SwigType *fr_t = SwigType_typedef_resolve_all(t); /* Create fully resolved type */ @@ -1803,7 +1803,7 @@ public: if (nspace == 0 || Len(nspace) == 0) mangled_name = NewString("SwigModule"); else - mangled_name = Swig_name_mangle(nspace); + mangled_name = Swig_name_mangle_string(nspace); String *cname = NewStringf("swig_%s", mangled_name); Setattr(carrays_hash, "cname", cname); diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx index c3ac2d415..d1bf085e7 100644 --- a/Source/Modules/mzscheme.cxx +++ b/Source/Modules/mzscheme.cxx @@ -569,7 +569,7 @@ public: // Make a static variable; - Printf(var_name, "_wrap_const_%s", Swig_name_mangle(Getattr(n, "sym:name"))); + Printf(var_name, "_wrap_const_%s", Swig_name_mangle_string(Getattr(n, "sym:name"))); // Build the name for scheme. Printv(proc_name, iname, NIL); @@ -656,7 +656,7 @@ public: convert_proto_tab = NewString(""); struct_name = Getattr(n, "sym:name"); - mangled_struct_name = Swig_name_mangle(Getattr(n, "sym:name")); + mangled_struct_name = Swig_name_mangle_string(Getattr(n, "sym:name")); Printv(scm_structname, struct_name, NIL); Replaceall(scm_structname, "_", "-"); diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index aba76624d..53ba99bee 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -946,7 +946,7 @@ public: // This is a bug, due to the fact that swig_type -> octave_class mapping // is 1-to-n. static Hash *emitted = NewHash(); - String *mangled_classname = Swig_string_mangle_type(Getattr(n, "name")); + String *mangled_classname = Swig_name_mangle_type(Getattr(n, "name")); if (Getattr(emitted, mangled_classname)) { Delete(mangled_classname); return SWIG_NOWRAP; diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 0208435f0..804a7aa94 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -85,7 +85,7 @@ public: /* Mangled name */ Delete(mname); - mname = Swig_name_mangle(cname); + mname = Swig_name_mangle_string(cname); /* Renamed class name */ Clear(name); diff --git a/Source/Modules/tcl8.cxx b/Source/Modules/tcl8.cxx index 12a65e9b6..ba0d9827e 100644 --- a/Source/Modules/tcl8.cxx +++ b/Source/Modules/tcl8.cxx @@ -740,7 +740,7 @@ public: return SWIG_ERROR; real_classname = Getattr(n, "name"); - mangled_classname = Swig_string_mangle_type(real_classname); + mangled_classname = Swig_name_mangle_type(real_classname); if (Getattr(emitted, mangled_classname)) return SWIG_NOWRAP; @@ -816,7 +816,7 @@ public: Printv(base_classes, bname, " ", NIL); Printv(base_class_init, " ", bname, "Ptr::constructor $ptr\n", NIL); } - String *bmangle = Swig_string_mangle_type(bname); + String *bmangle = Swig_name_mangle_type(bname); // Printv(f_wrappers,"extern swig_class _wrap_class_", bmangle, ";\n", NIL); // Printf(base_class,"&_wrap_class_%s",bmangle); Printf(base_class, "0"); diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index a80434323..10faa17d5 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -950,14 +950,14 @@ static String *expand_macro(String *name, List *args, String *line_file) { /* Non-standard mangle expansions. The #@Name is replaced by mangle_arg(Name). */ if (strstr(Char(ns), "\004")) { - String *marg = Swig_string_mangle(arg); + String *marg = Swig_name_mangle_string(arg); Clear(temp); Printf(temp, "\004%s", aname); Replace(ns, temp, marg, DOH_REPLACE_ID_END); Delete(marg); } if (strstr(Char(ns), "\005")) { - String *marg = Swig_string_mangle(arg); + String *marg = Swig_name_mangle_string(arg); Clear(temp); Clear(tempa); Printf(temp, "\005%s", aname); diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index b7d01bc11..b4be5d728 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -1075,7 +1075,7 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas 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); + String *mangled = Swig_name_mangle_string(membername); int is_smart_pointer = flags & CWRAP_SMART_POINTER; type = Getattr(n, "type"); @@ -1238,7 +1238,7 @@ int Swig_ConstructorToFunction(Node *n, const_String_or_char_ptr nspace, String String *defaultargs = Getattr(n, "defaultargs"); String *code = Getattr(n, "code"); String *membername = Swig_name_construct(nspace, classname); - String *mangled = Swig_name_mangle(membername); + String *mangled = Swig_name_mangle_string(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 @@ -1356,7 +1356,7 @@ int Swig_DestructorToFunction(Node *n, const_String_or_char_ptr nspace, String * String *call; String *membername, *mangled, *code; membername = Swig_name_destroy(nspace, classname); - mangled = Swig_name_mangle(membername); + mangled = Swig_name_mangle_string(membername); code = Getattr(n, "code"); if (code) { Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus, "self"); @@ -1443,7 +1443,7 @@ int Swig_MembersetToFunction(Node *n, String *classname, int flags) { String *sname = Swig_name_set(0, name); String *membername = Swig_name_member(0, classname, sname); - String *mangled = Swig_name_mangle(membername); + String *mangled = Swig_name_mangle_string(membername); if (code) { /* I don't think this ever gets run - WSF */ @@ -1525,7 +1525,7 @@ int Swig_MembergetToFunction(Node *n, String *classname, int flags) { String *gname = Swig_name_get(0, name); String *membername = Swig_name_member(0, classname, gname); - String *mangled = Swig_name_mangle(membername); + String *mangled = Swig_name_mangle_string(membername); if (code) { /* I don't think this ever gets run - WSF */ @@ -1577,7 +1577,7 @@ int Swig_VarsetToFunction(Node *n, int flags) { if (flags & CWRAP_EXTEND) { String *sname = Swig_name_set(0, name); - String *mangled = Swig_name_mangle(sname); + String *mangled = Swig_name_mangle_string(sname); String *call = Swig_cfunction_call(mangled, parms); String *cres = NewStringf("%s;", call); Setattr(n, "wrap:action", cres); @@ -1631,7 +1631,7 @@ int Swig_VargetToFunction(Node *n, int flags) { if (flags & CWRAP_EXTEND) { String *sname = Swig_name_get(0, name); - String *mangled = Swig_name_mangle(sname); + String *mangled = Swig_name_mangle_string(sname); call = Swig_cfunction_call(mangled, 0); cres = Swig_cresult(ty, Swig_cresult_name(), call); Setattr(n, "wrap:action", cres); diff --git a/Source/Swig/fragment.c b/Source/Swig/fragment.c index 099eb0ef7..84731f52f 100644 --- a/Source/Swig/fragment.c +++ b/Source/Swig/fragment.c @@ -41,7 +41,7 @@ void Swig_fragment_register(Node *fragment) { String *type = Getattr(fragment, "type"); if (type) { SwigType *rtype = SwigType_typedef_resolve_all(type); - String *mangle = Swig_string_mangle_type(type); + String *mangle = Swig_name_mangle_type(type); Append(name, mangle); Delete(mangle); Delete(rtype); @@ -106,7 +106,7 @@ void Swig_fragment_emit(Node *n) { type = Getattr(n, "type"); if (type) { - mangle = Swig_string_mangle_type(type); + mangle = Swig_name_mangle_type(type); } if (debug) @@ -162,7 +162,7 @@ void Swig_fragment_emit(Node *n) { SwigType *rtype = SwigType_typedef_resolve_all(type); if (!Equal(type, rtype)) { String *name = Copy(Getattr(n, "value")); - String *mangle = Swig_string_mangle_type(type); + String *mangle = Swig_name_mangle_type(type); Append(name, mangle); Setfile(name, Getfile(n)); Setline(name, Getline(n)); diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index af0b24951..1f4080af4 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -702,170 +702,8 @@ String *Swig_string_typecode(String *s) { return ns; } -/* ----------------------------------------------------------------------------- - * Swig_string_mangle_type() - * - * Same as Swig_string_mangle, but converting internal SwigType * to a human - * readable string of the type (for templates). Simplifies a type that is a - * template to the default template if possible. - * ----------------------------------------------------------------------------- */ - -String *Swig_string_mangle_type(const SwigType *s) { - String *mangled = 0; - 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; - } - mangled = Swig_string_mangle(b); - Delete(b); - return mangled; -} - -/* ----------------------------------------------------------------------------- - * 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' and - * 'std::pair', 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) { - String *result = NewStringEmpty(); - int space = 0; - int state = 0; - char *pc, *cb; - - pc = cb = Char(s); - 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; - } - return result; -} - -String *Swig_string_emangle(String *s) { - return Swig_string_mangle(s); +static String *string_mangle(String *s) { + return Swig_name_mangle_string(s); } @@ -1542,7 +1380,7 @@ void Swig_init(void) { DohEncoding("lctitle", Swig_string_lccase); DohEncoding("utitle", Swig_string_ucase); DohEncoding("typecode", Swig_string_typecode); - DohEncoding("mangle", Swig_string_emangle); + DohEncoding("mangle", string_mangle); DohEncoding("command", Swig_string_command); DohEncoding("schemify", Swig_string_schemify); DohEncoding("strip", Swig_string_strip); diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index da70b21dd..517b056a7 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -157,21 +157,168 @@ static void replace_nspace(String *name, const_String_or_char_ptr nspace) { } /* ----------------------------------------------------------------------------- - * Swig_name_mangle() - * - * Converts all of the non-identifier characters of a string to underscores. + * Swig_name_mangle_type() + * + * Same as Swig_name_mangle_string, but converting internal SwigType * to a human + * readable string of the type (for templates). Simplifies a type that is a + * template to the default template if possible. * ----------------------------------------------------------------------------- */ -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 +String *Swig_name_mangle_type(const SwigType *s) { + String *mangled = 0; + 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; + } + mangled = Swig_name_mangle_string(b); + Delete(b); + return mangled; } +/* ----------------------------------------------------------------------------- + * Swig_name_mangle_string() + * + * 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' and + * 'std::pair', 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_name_mangle_string(const String *s) { + String *result = NewStringEmpty(); + int space = 0; + int state = 0; + char *pc, *cb; + + pc = cb = Char(s); + 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; + } + return result; +} + + /* ----------------------------------------------------------------------------- * Swig_name_wrapper() * diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index d0156e53f..b392d179d 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -271,7 +271,8 @@ extern int ParmList_is_compactdefargs(ParmList *p); 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_mangle_string(const String *s); + extern String *Swig_name_mangle_type(const SwigType *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); @@ -323,8 +324,6 @@ extern int ParmList_is_compactdefargs(ParmList *p); 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 String *Swig_string_mangle_type(const SwigType *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); diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index 7132ab700..8eabc1474 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -1293,7 +1293,7 @@ static void typemap_merge_fragment_kwargs(Parm *kw) { reattach_kw = prev_kw; } if (kwtype) { - String *mangle = Swig_string_mangle_type(kwtype); + String *mangle = Swig_name_mangle_type(kwtype); Append(fragment, mangle); Delete(mangle); /* Remove 'type' from kwargs so it's not duplicated later */ @@ -1541,7 +1541,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No Delete(parm_sublist); } if (kwtype) { - String *mangle = Swig_string_mangle_type(kwtype); + String *mangle = Swig_name_mangle_type(kwtype); Append(value, mangle); Delete(mangle); } From e3ccabbd4dc22a7e59a9d1b93308d96a97d35328 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 12 Nov 2022 11:45:20 +0000 Subject: [PATCH 156/217] Simpler names when using SwigType_manglestr for templates The default template name is generated instead of one with the default template parameter. Used in various places such as the type system. --- Source/Swig/stype.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index f227778f6..79e011c77 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -1190,7 +1190,9 @@ static String *manglestr_default(const SwigType *s) { SwigType *type = ss; if (SwigType_istemplate(ss)) { - SwigType *ty = Swig_symbol_template_deftype(ss, 0); + SwigType *dt = Swig_symbol_template_deftype(ss, 0); + String *ty = Swig_symbol_type_qualify(dt, 0); + Delete(dt); Delete(ss); ss = ty; type = ss; From 777fd2c280fbeb0dea79d900f115369bc2295f65 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 12 Nov 2022 16:25:17 +0000 Subject: [PATCH 157/217] Minor refactor of D, C#, Java director code for overloaded methods. Fixes regression (crash) in director_ignore D testcase since string mangling names change. --- Source/Modules/csharp.cxx | 45 ++++++++++++++++++++++----------------- Source/Modules/d.cxx | 14 ++++++++---- Source/Modules/java.cxx | 26 +++++++++++++--------- 3 files changed, 51 insertions(+), 34 deletions(-) diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 8d4b03151..14025f246 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -2973,7 +2973,7 @@ public: /* A C# HandleRef is used for all classes in the SWIG intermediary class. * The intermediary class methods are thus mangled when overloaded to give * a unique name. */ - String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name")); + String *overloaded_name = Copy(Getattr(n, "sym:name")); if (Getattr(n, "sym:overloaded")) { Printv(overloaded_name, Getattr(n, "sym:overname"), NIL); @@ -3817,7 +3817,7 @@ public: String *name = Getattr(n, "name"); String *symname = Getattr(n, "sym:name"); SwigType *returntype = Getattr(n, "type"); - String *overloaded_name = getOverloadedName(n); + String *overloaded_name = 0; String *storage = Getattr(n, "storage"); String *value = Getattr(n, "value"); String *decl = Getattr(n, "decl"); @@ -3839,7 +3839,6 @@ public: String *qualified_name = NewStringf("%s::%s", dirclassname, name); SwigType *c_ret_type = NULL; String *jupcall_args = NewString(""); - String *imclass_dmethod; String *callback_typedef_parms = NewString(""); String *delegate_parms = NewString(""); String *proxy_method_types = NewString(""); @@ -3853,7 +3852,8 @@ public: // we're consistent with the sym:overload name in functionWrapper. (?? when // does the overloaded method name get set?) - imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name)); + if (!ignored_method) + overloaded_name = getOverloadedName(n); qualified_return = SwigType_rcaststr(returntype, "c_result"); @@ -3906,28 +3906,28 @@ public: } } - /* Create the intermediate class wrapper */ - tm = Swig_typemap_lookup("imtype", n, "", 0); - if (tm) { - String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap - if (imtypeout) - tm = imtypeout; - const String *im_directoroutattributes = Getattr(n, "tmap:imtype:directoroutattributes"); - if (im_directoroutattributes) { - Printf(callback_def, " %s\n", im_directoroutattributes); - if (!ignored_method) - Printf(director_delegate_definitions, " %s\n", im_directoroutattributes); - } + if (!ignored_method) { + /* Create the intermediate class wrapper */ + tm = Swig_typemap_lookup("imtype", n, "", 0); + if (tm) { + String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap + if (imtypeout) + tm = imtypeout; + const String *im_directoroutattributes = Getattr(n, "tmap:imtype:directoroutattributes"); + if (im_directoroutattributes) { + Printf(callback_def, " %s\n", im_directoroutattributes); + if (!ignored_method) + Printf(director_delegate_definitions, " %s\n", im_directoroutattributes); + } - Printf(callback_def, " private %s SwigDirectorMethod%s(", tm, overloaded_name); - if (!ignored_method) { + Printf(callback_def, " private %s SwigDirectorMethod%s(", tm, overloaded_name); const String *csdirectordelegatemodifiers = Getattr(n, "feature:csdirectordelegatemodifiers"); String *modifiers = (csdirectordelegatemodifiers ? NewStringf("%s%s", csdirectordelegatemodifiers, Len(csdirectordelegatemodifiers) > 0 ? " " : "") : NewStringf("public ")); Printf(director_delegate_definitions, " %sdelegate %s", modifiers, tm); Delete(modifiers); + } else { + Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0)); } - } else { - Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0)); } if ((c_ret_type = Swig_typemap_lookup("ctype", n, "", 0))) { @@ -4285,6 +4285,8 @@ public: if (!ignored_method) { /* Emit the actual upcall through */ + String *member_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name); + String *imclass_dmethod = NewStringf("SwigDirector_%s", member_name); UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, decl, overloaded_name); String *methid = Getattr(udata, "class_methodidx"); Setattr(n, "upcalldata", udata); @@ -4300,6 +4302,9 @@ public: Printf(director_delegate_instances, " private SwigDelegate%s_%s swigDelegate%s;\n", classname, methid, methid); Printf(director_method_types, " private static global::System.Type[] swigMethodTypes%s = new global::System.Type[] { %s };\n", methid, proxy_method_types); Printf(director_connect_parms, "SwigDirector%s%s delegate%s", classname, methid, methid); + + Delete(imclass_dmethod); + Delete(member_name); } Delete(pre_code); diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index ecf931633..70ac0c684 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -1943,7 +1943,7 @@ public: String *name = Getattr(n, "name"); String *symname = Getattr(n, "sym:name"); SwigType *returntype = Getattr(n, "type"); - String *overloaded_name = getOverloadedName(n); + String *overloaded_name = 0; String *storage = Getattr(n, "storage"); String *value = Getattr(n, "value"); String *decl = Getattr(n, "decl"); @@ -1962,7 +1962,6 @@ public: String *qualified_name = NewStringf("%s::%s", dirclassname, name); SwigType *c_ret_type = NULL; String *dcallback_call_args = NewString(""); - String *imclass_dmethod; String *callback_typedef_parms = NewString(""); String *delegate_parms = NewString(""); String *proxy_method_param_list = NewString(""); @@ -1977,7 +1976,8 @@ public: // we're consistent with the sym:overload name in functionWrapper. (?? when // does the overloaded method name get set?) - imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(getNSpace(), classname, overloaded_name)); + if (!ignored_method) + overloaded_name = getOverloadedName(n); qualified_return = SwigType_rcaststr(returntype, "c_result"); @@ -2381,8 +2381,9 @@ public: dp_return_type = NewString(""); } + String *member_name = Swig_name_member(getNSpace(), classname, overloaded_name); + String *imclass_dmethod = NewStringf("SwigDirector_%s", member_name); UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, decl, overloaded_name, dp_return_type, proxy_method_param_list); - Delete(dp_return_type); // Write the global callback function pointer on the C code. String *methid = Getattr(udata, "class_methodidx"); @@ -2396,6 +2397,10 @@ public: String *dirClassName = directorClassName(parent); Printf(proxy_callback_type, "%s_Callback%s", dirClassName, methid); Printf(im_dmodule_code, "alias extern(C) %s function(void*%s) %s;\n", proxy_callback_return_type, delegate_parms, proxy_callback_type); + + Delete(imclass_dmethod); + Delete(member_name); + Delete(dp_return_type); Delete(proxy_callback_type); Delete(dirClassName); } @@ -4281,6 +4286,7 @@ private: * D::getOverloadedName() * --------------------------------------------------------------------------- */ String *getOverloadedName(Node *n) const { + // A void* parameter is used for all wrapped classes in the wrapper code. // Thus, the wrapper function names for overloaded functions are postfixed // with a counter string to make them unique. diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index d625d0476..20403714a 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -2988,7 +2988,7 @@ public: * a Java long is used for all classes in the SWIG intermediary class. * The intermediary class methods are thus mangled when overloaded to give * a unique name. */ - String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name")); + String *overloaded_name = Copy(Getattr(n, "sym:name")); if (Getattr(n, "sym:overloaded")) { Printv(overloaded_name, Getattr(n, "sym:overname"), NIL); @@ -4003,7 +4003,7 @@ public: String *name = Getattr(n, "name"); String *symname = Getattr(n, "sym:name"); SwigType *returntype = Getattr(n, "type"); - String *overloaded_name = getOverloadedName(n); + String *overloaded_name = 0; String *storage = Getattr(n, "storage"); String *value = Getattr(n, "value"); String *decl = Getattr(n, "decl"); @@ -4026,7 +4026,7 @@ public: String *classret_desc = NewString(""); SwigType *c_ret_type = NULL; String *jupcall_args = NewString("swigjobj"); - String *imclass_dmethod; + String *imclass_dmethod = 0; String *callback_def = NewString(""); String *callback_code = NewString(""); String *imcall_args = NewString(""); @@ -4039,7 +4039,11 @@ public: // we're consistent with the sym:overload name in functionWrapper. (?? when // does the overloaded method name get set?) - imclass_dmethod = NewStringf("%s", Swig_name_member(getNSpace(), dirclassname, overloaded_name)); + if (!ignored_method) { + overloaded_name = getOverloadedName(n); + imclass_dmethod = Swig_name_member(getNSpace(), dirclassname, overloaded_name); + } + qualified_return = SwigType_rcaststr(returntype, "c_result"); @@ -4092,12 +4096,14 @@ public: } } - /* Create the intermediate class wrapper */ - tm = Swig_typemap_lookup("jtype", n, "", 0); - if (tm) { - Printf(callback_def, " public static %s %s(%s jself", tm, imclass_dmethod, qualified_classname); - } else { - Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(returntype, 0)); + if (!ignored_method) { + /* Create the intermediate class wrapper */ + tm = Swig_typemap_lookup("jtype", n, "", 0); + if (tm) { + Printf(callback_def, " public static %s %s(%s jself", tm, imclass_dmethod, qualified_classname); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(returntype, 0)); + } } String *cdesc = NULL; From f1f77c218f0270fc9800b6d709794e2bf81c911a Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 13 Nov 2022 15:23:42 +1300 Subject: [PATCH 158/217] [PHP] Update docs for removal of -noproxy in SWIG 4.1.0 Closes #2419 --- CHANGES.current | 4 ++++ Doc/Manual/Php.html | 33 +++++---------------------------- Doc/Manual/SWIGPlus.html | 2 +- 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 3cc2c6066..3f36a80df 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2022-11-13: olly + [PHP] #2419 Update the documentation to reflect that SWIG 4.1.0 + dropped support for -noproxy when generating PHP wrappers. + 2022-11-05: wsfulton #2417 Fix -swiglib for Windows when building with CMake. diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 97a48b707..fad7f6a2f 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -635,18 +635,12 @@ variable, or assigning NULL to a variable.

      -SWIG defaults to wrapping C++ structs and classes with PHP classes. +SWIG wraps C++ structs and classes with PHP classes. Since SWIG 4.1.0, this is done entirely via PHP's C API - earlier SWIG versions generated a PHP wrapper script which defined proxy classes which called a set of flat functions which actually wrapped the C++ class.

      -

      -If you don't want the class wrappers, you can pass the command-line option -"-noproxy" in which case you'll get C++ classes wrapped as flat functions -as described below. -

      -

      This interface file

      @@ -699,33 +693,16 @@ Member variables and methods are accessed using the -> operator.

      -The -noproxy option flattens the object structure and -generates collections of named functions. The above example results -in the following PHP functions: +SWIG/PHP used to support a -noproxy option to flatten the class +structure and generate collections of named flat functions. This is no +longer supported as of SWIG 4.1.0.

      -
      -new_Vector();
      -Vector_x_set($obj, $d);
      -Vector_x_get($obj);
      -Vector_y_set($obj, $d);
      -Vector_y_get($obj);
      -Vector_z_set($obj, $d);
      -Vector_z_get($obj);
      -Vector_magnitude($obj);
      -new_Complex();
      -Complex_re_set($obj, $d);
      -Complex_re_get($obj);
      -Complex_im_set($obj, $d);
      -Complex_im_get($obj);
      -
      -

      32.2.6.2 Constructors and Destructors

      -The constructor is called when new Object() (or -new_Object() if using -noproxy) is used to create an +The constructor is called when new Object() is used to create an instance of the object. If multiple constructors are defined for an object, function overloading will be used to determine which constructor to execute. diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index b4b9acb17..a3f600b40 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -254,7 +254,7 @@ details. The SWIG Wiki also has further details.

      Compatibility Note: Early versions of SWIG generated just a flattened low-level C style API to C++ classes by default. -The -noproxy commandline option is recognised by many target languages and will generate just this +The -noproxy commandline option is recognised by some target languages and will generate just this interface as in earlier versions.

      6.5 Proxy classes

      From 63821f1bb5bc34656bd79775a27d5a175624d3dc Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Wed, 16 Nov 2022 20:54:45 +0100 Subject: [PATCH 159/217] added testcase pointer_reference --- .../test-suite/r/pointer_reference_runme.R | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Examples/test-suite/r/pointer_reference_runme.R diff --git a/Examples/test-suite/r/pointer_reference_runme.R b/Examples/test-suite/r/pointer_reference_runme.R new file mode 100644 index 000000000..4a2a7ea1b --- /dev/null +++ b/Examples/test-suite/r/pointer_reference_runme.R @@ -0,0 +1,24 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) +#source("unittest.R") + +dyn.load(paste("pointer_reference", .Platform$dynlib.ext, sep="")) +source("pointer_reference.R") +cacheMetaData(1) + + +s = Struct_value_get(Struct_pInstance_get()) +unittest(s, 10) + +ss = Struct(20) +Struct_pInstance_set(ss) +s = Struct_value_get(Struct_pInstance_get()) +unittest(s, 20) + +s = overloading(1) +unittest(s, 111) + +s = overloading(ss) +unittest(s, 222) + + From a88995a11d4031ffac9d8cf3d663f1a83ad4576f Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Wed, 16 Nov 2022 22:17:25 +0100 Subject: [PATCH 160/217] more r tests --- .../r/template_class_reuse_name_runme.R | 52 +++++++++++++++++ .../test-suite/r/template_classes_runme.R | 57 +++++++++++++++++++ ...late_default_arg_overloaded_extend_runme.R | 25 ++++++++ .../r/template_default_arg_overloaded_runme.R | 53 +++++++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 Examples/test-suite/r/template_class_reuse_name_runme.R create mode 100644 Examples/test-suite/r/template_classes_runme.R create mode 100644 Examples/test-suite/r/template_default_arg_overloaded_extend_runme.R create mode 100644 Examples/test-suite/r/template_default_arg_overloaded_runme.R diff --git a/Examples/test-suite/r/template_class_reuse_name_runme.R b/Examples/test-suite/r/template_class_reuse_name_runme.R new file mode 100644 index 000000000..256482213 --- /dev/null +++ b/Examples/test-suite/r/template_class_reuse_name_runme.R @@ -0,0 +1,52 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) +#source("unittest.R") + +dyn.load(paste("template_class_reuse_name", .Platform$dynlib.ext, sep="")) +source("template_class_reuse_name.R") +cacheMetaData(1) + + + + + +Bool1()$tt() +Bool1False()$ff() + +Bool2()$tt() +Bool2False()$ff() + +Bool3()$tt() +Bool3False()$ff() + +Bool4()$tt() +Bool4False()$ff() + + +BoolForward1()$tt() +BoolForward1False()$ff() + +BoolForward2()$tt() +BoolForward2False()$ff() + +BoolForward3()$tt() +BoolForward3False()$ff() + +BoolForward4()$tt() +BoolForward4False()$ff() + + +IntBool1()$tt() +IntBool1False()$ff() + +IntBool2()$tt() +IntBool2False()$ff() + +IntBool3()$tt() +IntBool3False()$ff() + +IntBool4()$tt() +IntBool4False()$ff() + +Duplicate2_0_n(Duplicate2_0()) +Duplicate3_n(Duplicate3()) diff --git a/Examples/test-suite/r/template_classes_runme.R b/Examples/test-suite/r/template_classes_runme.R new file mode 100644 index 000000000..e40dfd4cc --- /dev/null +++ b/Examples/test-suite/r/template_classes_runme.R @@ -0,0 +1,57 @@ + +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) +#source("unittest.R") + +dyn.load(paste("template_classes", .Platform$dynlib.ext, sep="")) +source("template_classes.R") +cacheMetaData(1) + + +# This test is just testing incorrect number of arguments/parameters checking + +point = PointInt() +rectangle = RectangleInt() + +p = RectangleInt_getPoint(rectangle) +unittest(PointInt_getX(p), 0) + +RectangleInt_setPoint(rectangle, point) + +unittest(RectangleInt_static_noargs(), 0) +unittest(RectangleInt_static_onearg(12), 12) + + +argCheckFailed = F +try({ + RectangleInt_setPoint(rectangle) + argCheckFailed = T +}, silent=T) +unittest(argCheckFailed, F) + + +argCheckFailed = F +try({ + RectangleInt_getPoint(rectangle, 0, .copy = F) + argCheckFailed = T +}, silent=T) +unittest(argCheckFailed, F) + + +argCheckFailed = F +try({ + RectangleInt_static_noargs(123, .copy = F) + argCheckFailed = T +}, silent=T) +unittest(argCheckFailed, F) + + + +argCheckFailed = F +try({ + RectangleInt_static_onearg() + argCheckFailed = T +}, silent=T) +unittest(argCheckFailed, F) + + diff --git a/Examples/test-suite/r/template_default_arg_overloaded_extend_runme.R b/Examples/test-suite/r/template_default_arg_overloaded_extend_runme.R new file mode 100644 index 000000000..3ec4eb3e9 --- /dev/null +++ b/Examples/test-suite/r/template_default_arg_overloaded_extend_runme.R @@ -0,0 +1,25 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) +#source("unittest.R") + +dyn.load(paste("template_default_arg_overloaded_extend", .Platform$dynlib.ext, sep="")) +source("template_default_arg_overloaded_extend.R") +cacheMetaData(1) + + + + +rs = ResultSet() + +unittest(rs$go_get_method(0, SearchPoint()), -1) +unittest(rs$go_get_method(0, SearchPoint(), 100), 100) + +unittest(rs$go_get_template(0, SearchPoint()), -2) +unittest(rs$go_get_template(0, SearchPoint(), 100), 100) + +unittest(rs$over(), "over(int)") +unittest(rs$over(10), "over(int)") +unittest(rs$over(SearchPoint()), "over(giai2::SearchPoint, int)") +unittest(rs$over(SearchPoint(), 10), "over(giai2::SearchPoint, int)") +unittest(rs$over(T, SearchPoint()), "over(bool, gaia2::SearchPoint, int)") +unittest(rs$over(T, SearchPoint(), 10), "over(bool, gaia2::SearchPoint, int)") diff --git a/Examples/test-suite/r/template_default_arg_overloaded_runme.R b/Examples/test-suite/r/template_default_arg_overloaded_runme.R new file mode 100644 index 000000000..bf9272d3c --- /dev/null +++ b/Examples/test-suite/r/template_default_arg_overloaded_runme.R @@ -0,0 +1,53 @@ + +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) +#source("unittest.R") + +dyn.load(paste("template_default_arg_overloaded", .Platform$dynlib.ext, sep="")) +source("template_default_arg_overloaded.R") +cacheMetaData(1) + + + + +pl = PropertyList() +unittest(1, pl$setInt("int", 10)) +unittest(1, pl$setInt("int", 10, F)) + +unittest(2, pl$set("int", pl)) +unittest(2, pl$set("int", pl, F)) + +unittest(3, pl$setInt("int", 10, "int")) +unittest(3, pl$setInt("int", 10, "int", F)) + + +pl = PropertyListGlobal() +unittest(1, pl$setIntGlobal("int", 10)) +unittest(1, pl$setIntGlobal("int", 10, F)) + +unittest(2, pl$set("int", pl)) +unittest(2, pl$set("int", pl, F)) + +unittest(3, pl$setIntGlobal("int", 10, "int")) +unittest(3, pl$setIntGlobal("int", 10, "int", F)) + + +unittest(1, GoopIntGlobal(10)) +unittest(1, GoopIntGlobal(10, T)) + +unittest(2, goopGlobal(3)) +unittest(2, goopGlobal()) + +unittest(3, GoopIntGlobal("int", F)) +unittest(3, GoopIntGlobal("int")) + + +unittest(1, GoopInt(10)) +unittest(1, GoopInt(10, T)) + +unittest(2, goop(3)) +unittest(2, goop()) + +unittest(3, GoopInt("int", F)) +unittest(3, GoopInt("int")) + From 4729cf2b1f44e57f46d13758009b10cec5af47b6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 18 Nov 2022 18:49:48 +0000 Subject: [PATCH 161/217] Duplicate class template instantiations via %template changes Named duplicate class template instantiations now issue a warning and are ignored. Duplicate empty class template instantiations are quietly ignored. The test cases are fixed for this new behaviour. This commit is a pre-requisite for the near future so that the Python builtin wrappers can correctly use the SwigType_namestr function without generating duplicate symbol names. --- CHANGES.current | 44 ++++++ Doc/Manual/Contents.html | 1 + Doc/Manual/SWIGPlus.html | 139 ++++++++++++++---- Doc/Manual/Warnings.html | 1 + .../errors/cpp_template_class_repeat.i | 34 +++++ .../errors/cpp_template_class_repeat.stderr | 6 + .../cpp_template_duplicate_names.stderr | 12 +- .../test-suite/errors/cpp_template_repeat.i | 13 +- .../errors/cpp_template_repeat.stderr | 6 + .../test-suite/template_class_reuse_name.i | 3 + Examples/test-suite/template_default2.i | 14 +- .../template_specialization_defarg.i | 2 + Source/CParse/cparse.h | 2 +- Source/CParse/parser.y | 15 +- Source/CParse/templ.c | 45 +++++- Source/Modules/typepass.cxx | 1 + 16 files changed, 283 insertions(+), 55 deletions(-) create mode 100644 Examples/test-suite/errors/cpp_template_class_repeat.i create mode 100644 Examples/test-suite/errors/cpp_template_class_repeat.stderr diff --git a/CHANGES.current b/CHANGES.current index 3cc2c6066..e184cc6d8 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,50 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2022-11-18: wsfulton + Duplicate class template instantiations via %template now issue a warning and are ignored. + + %template(Aint) A; + %template(Aint2) A; // Now ignored and issues a warning + + example.i:7: Warning 404: Duplicate template instantiation of 'A< int >' with name 'Aint2' ignored, + example.i:6: Warning 404: previous instantiation of 'A< int >' with name 'Aint'. + + A single empty template instantiation before a named instantiation is the one exception + for allowing duplicate template instantiations as the empty template instantation does not + create a wrapper for the template, it merely adds the instantiation into SWIG's internal + type system. + Duplicate empty template instantiations are quietly ignored. + + %template() B; + %template(Bint) B; // OK + + %template() C; + %template() C; // Quietly ignored now + %template(Cint) C; // OK + + Note that default template parameters are considered when looking for duplicates such as: + + template struct D {}; + %template(Dint) D; + %template(Dintshort) D; + + example.i:7: Warning 404: Duplicate template instantiation of 'D< int,short >' with name 'Dintshort' ignored, + example.i:6: Warning 404: previous instantiation of 'D< int >' with name 'Dint'. + + Note that the following always was ignored, but that was because the chosen name was a + duplicate rather than the template being a duplicate: + + %template(Eint) E; + %template(Eint) E; // Always has been ignored as a redefined identifier + + The old warning was: + + example.i:7: Warning 302: Identifier 'Eint' redefined (ignored) (Renamed from 'E< int >'), + example.i:6: Warning 302: previous definition of 'Eint' (Renamed from 'E< int >'). + + *** POTENTIAL INCOMPATIBILITY *** + 2022-11-05: wsfulton #2417 Fix -swiglib for Windows when building with CMake. diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index fd74ab299..cecd54958 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -260,6 +260,7 @@
    • Function templates
    • Default template arguments
    • Template base classes +
    • Empty template instantiation
    • Template specialization
    • Member templates
    • Scoping and templates diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index b4b9acb17..cc33d6152 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -57,6 +57,7 @@
    • Function templates
    • Default template arguments
    • Template base classes +
    • Empty template instantiation
    • Template specialization
    • Member templates
    • Scoping and templates @@ -3261,10 +3262,28 @@ void foo(List<Integer> *x); In this case, List<Integer> is exactly the same type as List<int>. Any use of List<Integer> is mapped back to the instantiation of List<int> created earlier. Therefore, it is -not necessary to instantiate a new class for the type Integer (doing so is -redundant and will simply result in code bloat). +not correct to instantiate a new class for the type Integer. +An attempt to do so such as:

      +
      +
      +%template(intList) List<int>;
      +%template(IntegerList) List<Integer>;   // Ignored
      +
      +
      + +

      +will result in the duplicate instantiation being ignored with a warning: +

      + +
      +
      +example.i:48: Warning 404: Duplicate template instantiation of 'List< Integer >' with name 'IntegerList' ignored,
      +example.i:47: Warning 404: previous instantiation of 'List< int >' with name 'intList'.
      +
      +
      +

      The template provided to %template for instantiation must be the actual template and not a typedef to a template.

      @@ -3333,36 +3352,49 @@ original template definition. Template default arguments are supported. For ex
      -template vector<typename T, int max=100> class vector {
      +template <typename T, int max=100> class vector {
       ...
       };
       
      -%template(intvec) vector<int>;           // OK
      +%template(intvec) vector<int>;            // OK
       %template(vec1000) vector<int, 1000>;     // OK
       

      The %template directive should not be used to wrap the same -template instantiation more than once in the same scope. This will -generate an error. For example: +template instantiation more than once. This also applies to default parameters +where a template parameter specified in the instantiation is the same as the default parameter. +For example:

      -%template(intList) List<int>;
      -%template(Listint) List<int>;    // Error.   Template already wrapped.
      +%template(vec) vector<double>;            // OK
      +%template(vec100) vector<double, 100>;    // Ignored
       

      -This error is caused because the template expansion results in two -identical classes with the same name. This generates a symbol table -conflict. Besides, it probably more efficient to only wrap a specific -instantiation only once in order to reduce the potential for code -bloat. +will warn:

      +
      +
      +example.i:59: Warning 404: Duplicate template instantiation of 'vector< double,100 >' with name 'vec100' ignored,
      +example.i:58: Warning 404: previous instantiation of 'vector< double >' with name 'vec'.
      +
      +
      + +

      +If this was not ignored, the template expansion would result in two identical classes. +An identical instantiation is only wrapped once in order to reduce code bloat. +

      + +

      +Compatibility Note: Versions prior to SWIG-4.2.0 would sometimes not detect and prevent duplicate +instantiations, such as when the wrapped name was different. +

      6.18.4 Template base classes

      @@ -3429,20 +3461,6 @@ code (and base classes need to be wrapped before derived classes). Don't worry--if you get the order wrong, SWIG should generate a warning message.

      -

      -Occasionally, you may need to tell SWIG about base classes that are defined by templates, -but which aren't supposed to be wrapped. Since SWIG is not able to automatically -instantiate templates for this purpose, you must do it manually. To do this, simply -use the empty template instantiation, that is, %template with no name. For example: -

      - -
      -
      -// Instantiate traits<double, double>, but don't wrap it.
      -%template() traits<double, double>;
      -
      -
      -

      If you have to instantiate a lot of different classes for many different types, you might consider writing a SWIG macro. For example: @@ -3468,7 +3486,66 @@ TEMPLATE_WRAP(PairStringInt, std::pair<string, int>) Note the use of a vararg macro for the type T. If this wasn't used, the comma in the templated type in the last example would not be possible.

      -

      6.18.5 Template specialization

      +

      6.18.5 Empty template instantiation

      + + +

      +Occasionally, you may need to tell SWIG about classes that are defined by templates, +but which aren't supposed to be wrapped. Since SWIG is not able to automatically +instantiate templates for this purpose, you must do it manually. To do this, simply +use %template(), that is the empty template instantiation that omits providing a name. For example: +

      + +
      +
      +template<typename T> struct Traits {
      +  typedef T type;
      +};
      +%}
      +
      +%template() Traits<int>; // instantiate Traits<int>, but don't wrap it
      +
      +void traitor(Traits<int>::type val);
      +
      +
      + +

      +Without a template instantiation, SWIG does not know that the first parameter to the traitor +function is type int and passing an integer to this function from any target language won't work. +The empty template instantiation adds the appropriate type information into SWIG's type system, without +forcing one to wrap the Traits class. +

      + +

      +Duplicate template instantiation are not allowed, as described in the +Default template arguments section above. +There is one exception where a named template instantiation can be followed by an empty template instantiation. +Duplicate empty template instantiations are silently ignored, unlike duplicate named template instantiations. +

      + +

      +Unlike template class instantiations, template function instantiations must have a name. +Consider the following: +

      + +
      +
      +template<class T> T tfunc(T x) { };
      +%template() tfunc<double>;
      +
      +
      + +

      +The empty template instantiation will be ignored with: +

      + +
      +
      +example.i:9: Warning 519: %template() contains no name. Template method ignored: tfunc< double >(double)
      +
      +
      + +

      6.18.6 Template specialization

      @@ -3558,7 +3635,7 @@ SWIG implements template argument deduction so that the following partial specia -

      6.18.6 Member templates

      +

      6.18.7 Member templates

      @@ -3770,7 +3847,7 @@ constructor, that will dispatch the proper call depending on the argument type.

      -

      6.18.7 Scoping and templates

      +

      6.18.8 Scoping and templates

      @@ -3871,7 +3948,7 @@ template class C<int>;

      -

      6.18.8 More on templates

      +

      6.18.9 More on templates

      diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index b20b69cef..9d5361dae 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -493,6 +493,7 @@ example.i(4) : Syntax error in input(1).

    • 401. Nothing known about class 'name'. Ignored.
    • 402. Base class 'name' is incomplete.
    • 403. Class 'name' might be abstract. +
    • 404. Duplicate template instantiation of 'type' with name 'name' ignored, previous instantiation of 'type' with name 'name'.
    • 450. Reserved
    • 451. Setting const char * variable may leak memory.
    • 452. Reserved diff --git a/Examples/test-suite/errors/cpp_template_class_repeat.i b/Examples/test-suite/errors/cpp_template_class_repeat.i new file mode 100644 index 000000000..c8bffd47a --- /dev/null +++ b/Examples/test-suite/errors/cpp_template_class_repeat.i @@ -0,0 +1,34 @@ +%module xxx + +template struct A {}; +%template(Aint) A; +%template(Aint2) A; // Now ignored and issues a warning + +template struct B {}; +%template() B; +%template(Bint) B; // OK + +template struct C {}; +%template() C; +%template() C; // Quietly ignored now +%template(Cint) C; // OK + +template struct D {}; +%template(Dint) D; +%template(Dintshort) D; + +template struct E {}; +%template(Eint) E; +%template(Eint) E; // Always has been ignored as a redefined identifier + + +template struct F {}; +%template(Fint) F; +%template() F; // Quietly ignored +%template() F; // Quietly ignored + +template struct G {}; +%template() G; +%template() G; // Quietly ignored +%template(Gint) G; +%template() G; // Quietly ignored diff --git a/Examples/test-suite/errors/cpp_template_class_repeat.stderr b/Examples/test-suite/errors/cpp_template_class_repeat.stderr new file mode 100644 index 000000000..db283dc26 --- /dev/null +++ b/Examples/test-suite/errors/cpp_template_class_repeat.stderr @@ -0,0 +1,6 @@ +cpp_template_class_repeat.i:5: Warning 404: Duplicate template instantiation of 'A< int >' with name 'Aint2' ignored, +cpp_template_class_repeat.i:4: Warning 404: previous instantiation of 'A< int >' with name 'Aint'. +cpp_template_class_repeat.i:18: Warning 404: Duplicate template instantiation of 'D< int,short >' with name 'Dintshort' ignored, +cpp_template_class_repeat.i:17: Warning 404: previous instantiation of 'D< int >' with name 'Dint'. +cpp_template_class_repeat.i:22: Warning 404: Duplicate template instantiation of 'E< int >' with name 'Eint' ignored, +cpp_template_class_repeat.i:21: Warning 404: previous instantiation of 'E< int >' with name 'Eint'. diff --git a/Examples/test-suite/errors/cpp_template_duplicate_names.stderr b/Examples/test-suite/errors/cpp_template_duplicate_names.stderr index 9856ff563..9e70963a8 100644 --- a/Examples/test-suite/errors/cpp_template_duplicate_names.stderr +++ b/Examples/test-suite/errors/cpp_template_duplicate_names.stderr @@ -2,13 +2,13 @@ cpp_template_duplicate_names.i:14: Warning 302: Identifier 'Duplicate1' redefine cpp_template_duplicate_names.i:13: Warning 302: previous definition of 'Duplicate1'. cpp_template_duplicate_names.i:14: Warning 302: Identifier 'Duplicate1' redefined (ignored), cpp_template_duplicate_names.i:13: Warning 302: previous definition of 'Duplicate1'. -cpp_template_duplicate_names.i:25: Warning 302: Identifier 'Duplicate2_0' redefined (ignored) (Renamed from 'Duplicate2< 0 >'), -cpp_template_duplicate_names.i:24: Warning 302: previous definition of 'Duplicate2_0' (Renamed from 'Duplicate2< 0 >'). -cpp_template_duplicate_names.i:35: Warning 302: Identifier 'Duplicate3' redefined (ignored) (Renamed from 'Duplicate3< 0 >'), -cpp_template_duplicate_names.i:31: Warning 302: previous definition of 'Duplicate3'. +cpp_template_duplicate_names.i:25: Warning 404: Duplicate template instantiation of 'Duplicate2< 0 >' with name 'Duplicate2_0' ignored, +cpp_template_duplicate_names.i:24: Warning 404: previous instantiation of 'Duplicate2< 0 >' with name 'Duplicate2_0'. +cpp_template_duplicate_names.i:35: Warning 404: Duplicate template instantiation of 'Duplicate3< 0 >' with name 'Duplicate3' ignored, +cpp_template_duplicate_names.i:34: Warning 404: previous instantiation of 'Duplicate3< 0 >' with name 'Duplicate3'. cpp_template_duplicate_names.i:47: Warning 302: Identifier 'Duplicate4' redefined (ignored), cpp_template_duplicate_names.i:46: Warning 302: previous definition of 'Duplicate4'. cpp_template_duplicate_names.i:47: Warning 302: Identifier 'Duplicate4' redefined (ignored), cpp_template_duplicate_names.i:46: Warning 302: previous definition of 'Duplicate4'. -cpp_template_duplicate_names.i:50: Warning 302: Identifier 'Duplicate4' redefined (ignored) (Renamed from 'Duplicate4< 0 >'), -cpp_template_duplicate_names.i:46: Warning 302: previous definition of 'Duplicate4'. +cpp_template_duplicate_names.i:50: Warning 404: Duplicate template instantiation of 'Duplicate4< 0 >' with name 'Duplicate4' ignored, +cpp_template_duplicate_names.i:49: Warning 404: previous instantiation of 'Duplicate4< 0 >' with name 'Duplicate4'. diff --git a/Examples/test-suite/errors/cpp_template_repeat.i b/Examples/test-suite/errors/cpp_template_repeat.i index f170080b7..08d378223 100644 --- a/Examples/test-suite/errors/cpp_template_repeat.i +++ b/Examples/test-suite/errors/cpp_template_repeat.i @@ -4,4 +4,15 @@ template T blah(T x) { }; %template(iblah) blah; %template(iiblah) blah; -// The second %template instantiation above should surely be ignored with a warning, but doesn't atm + +// empty template instantiations for template functions warn (unlike for template classes) +%template() blah; +%template() blah; +%template() blah; + +%template(sblah) blah; +%template(sblah) blah; + +%template() blah; +%template() blah; +%template(sblah) blah; diff --git a/Examples/test-suite/errors/cpp_template_repeat.stderr b/Examples/test-suite/errors/cpp_template_repeat.stderr index e69de29bb..7ab04f2a3 100644 --- a/Examples/test-suite/errors/cpp_template_repeat.stderr +++ b/Examples/test-suite/errors/cpp_template_repeat.stderr @@ -0,0 +1,6 @@ +cpp_template_repeat.i:6: Warning 404: Duplicate template instantiation of 'blah< int >' with name 'iiblah' ignored, +cpp_template_repeat.i:5: Warning 404: previous instantiation of 'blah< int >' with name 'iblah'. +cpp_template_repeat.i:14: Warning 404: Duplicate template instantiation of 'blah< short >' with name 'sblah' ignored, +cpp_template_repeat.i:13: Warning 404: previous instantiation of 'blah< short >' with name 'sblah'. +cpp_template_repeat.i:9: Warning 519: %template() contains no name. Template method ignored: blah< double >(double) +cpp_template_repeat.i:16: Warning 519: %template() contains no name. Template method ignored: blah< char const * >(char const *) diff --git a/Examples/test-suite/template_class_reuse_name.i b/Examples/test-suite/template_class_reuse_name.i index 818816d0e..03c5c8d1f 100644 --- a/Examples/test-suite/template_class_reuse_name.i +++ b/Examples/test-suite/template_class_reuse_name.i @@ -97,6 +97,7 @@ namespace Space { %warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate2; +%warnfilter(SWIGWARN_TYPE_REDEFINED) Space::Duplicate2; %inline %{ namespace Space { template struct Duplicate2 { void n(){}; }; @@ -107,6 +108,7 @@ namespace Space { %warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate3; +%warnfilter(SWIGWARN_TYPE_REDEFINED) Space::Duplicate3; %inline %{ namespace Space { template struct Duplicate3 { void n(){}; }; @@ -123,6 +125,7 @@ namespace Space { %} %warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate4; +%warnfilter(SWIGWARN_TYPE_REDEFINED) Space::Duplicate4<0>; namespace Space { template struct Duplicate4 { void ff(){}; }; template struct Duplicate4 { void ff(){}; }; diff --git a/Examples/test-suite/template_default2.i b/Examples/test-suite/template_default2.i index 9ba0455f1..1a22410d2 100644 --- a/Examples/test-suite/template_default2.i +++ b/Examples/test-suite/template_default2.i @@ -17,6 +17,16 @@ static const Polarization pmode = UnaryPolarization; }; + struct traits2 + { + static const Polarization pmode = UnaryPolarization; + }; + + struct traits3 + { + static const Polarization pmode = UnaryPolarization; + }; + template > // **** problem here ***** @@ -37,8 +47,8 @@ namespace oss Interface_tpl >; // These don't - %template(Module_UP2) Module; - %template(Module_UP3) Module; + %template(Module_UP2) Module; + %template(Module_UP3) Module; } diff --git a/Examples/test-suite/template_specialization_defarg.i b/Examples/test-suite/template_specialization_defarg.i index 2f664c6f2..1216ab09c 100644 --- a/Examples/test-suite/template_specialization_defarg.i +++ b/Examples/test-suite/template_specialization_defarg.i @@ -1,5 +1,7 @@ %module template_specialization_defarg +%warnfilter(SWIGWARN_TYPE_REDEFINED) C; // note that warning is actually for the equivalent C diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h index 2b63f034d..42ce87cef 100644 --- a/Source/CParse/cparse.h +++ b/Source/CParse/cparse.h @@ -66,7 +66,7 @@ extern "C" { /* templ.c */ extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope); - extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms, Symtab *tscope); + extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms, String *symname, Symtab *tscope); extern void Swig_cparse_debug_templates(int); #ifdef __cplusplus diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 7f685e84e..61fac2b2e 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -2822,6 +2822,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va Symtab *tscope = 0; int specialized = 0; int variadic = 0; + String *symname = $3 ? NewString($3) : 0; $$ = 0; @@ -2841,7 +2842,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va This is closer to the C++ (typedef) behavior. */ - n = Swig_cparse_template_locate($5,$7,tscope); + n = Swig_cparse_template_locate($5, $7, symname, tscope); /* Patch the argument types to respect namespaces */ p = $7; @@ -2966,7 +2967,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va Setattr(templnode,"sym:typename","1"); } /* for now, nested %template is allowed only in the same scope as the template declaration */ - if ($3 && !(nnisclass && ((outer_class && (outer_class != Getattr(nn, "nested:outer"))) + if (symname && !(nnisclass && ((outer_class && (outer_class != Getattr(nn, "nested:outer"))) ||(extendmode && current_class && (current_class != Getattr(nn, "nested:outer")))))) { /* Comment this out for 1.3.28. We need to @@ -2974,11 +2975,10 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va move %ignore from using %rename to use %feature(ignore). - String *symname = Swig_name_make(templnode,0,$3,0,0); + String *symname = Swig_name_make(templnode, 0, symname, 0, 0); */ - String *symname = NewString($3); - Swig_cparse_template_expand(templnode,symname,temparms,tscope); - Setattr(templnode,"sym:name",symname); + Swig_cparse_template_expand(templnode, symname, temparms, tscope); + Setattr(templnode, "sym:name", symname); } else { static int cnt = 0; String *nname = NewStringf("__dummy_%d__", cnt++); @@ -2987,7 +2987,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va SetFlag(templnode,"hidden"); Delete(nname); Setattr(templnode,"feature:onlychildren", "typemap,typemapitem,typemapcopy,typedef,types,fragment,apply"); - if ($3) { + if (symname) { Swig_warning(WARN_PARSE_NESTED_TEMPLATE, cparse_file, cparse_line, "Named nested template instantiations not supported. Processing as if no name was given to %%template().\n"); } } @@ -3106,6 +3106,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va Swig_symbol_setscope(tscope); Delete(Namespaceprefix); Namespaceprefix = Swig_symbol_qualifiedscopename(0); + Delete(symname); } ; diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index 0dec21586..b02df8d05 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -605,7 +605,7 @@ static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, const * Search for a template that matches name with given parameters. * ----------------------------------------------------------------------------- */ -static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) { +static Node *template_locate(String *name, Parm *tparms, String *symname, Symtab *tscope) { Node *n = 0; String *tname = 0; Node *templ; @@ -626,7 +626,10 @@ static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) { tname = Copy(name); SwigType_add_template(tname, tparms); Printf(stdout, "\n"); - Swig_diagnostic(cparse_file, cparse_line, "template_debug: Searching for match to: '%s'\n", tname); + if (symname) + Swig_diagnostic(cparse_file, cparse_line, "Template debug: Searching for match to: '%s' for instantiation of template named '%s'\n", tname, symname); + else + Swig_diagnostic(cparse_file, cparse_line, "Template debug: Searching for match to: '%s' for instantiation of empty template\n", tname); Delete(tname); tname = 0; } @@ -682,11 +685,39 @@ static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) { } tn = Getattr(n, "template"); if (tn) { - if (template_debug) { - Printf(stdout, " previous instantiation found: '%s'\n", Getattr(n, "name")); + /* Previously wrapped by a template instantiation */ + Node *previous_named_instantiation = GetFlag(n, "hidden") ? Getattr(n, "csym:nextSibling") : n; /* "hidden" is set when "sym:name" is a __dummy_ name */ + if (!symname) { + /* Quietly ignore empty template instantiations if there is a previous (empty or non-empty) template instantiation */ + if (template_debug) { + if (previous_named_instantiation) + Printf(stdout, " previous instantiation with name '%s' found: '%s' - duplicate empty template instantiation ignored\n", Getattr(previous_named_instantiation, "sym:name"), Getattr(n, "name")); + else + Printf(stdout, " previous empty template instantiation found: '%s' - duplicate empty template instantiation ignored\n", Getattr(n, "name")); + } + return 0; } + /* Accept a second instantiation only if previous template instantiation is empty */ + if (previous_named_instantiation) { + String *previous_name = Getattr(previous_named_instantiation, "name"); + String *previous_symname = Getattr(previous_named_instantiation, "sym:name"); + String *unprocessed_tname = Copy(name); + SwigType_add_template(unprocessed_tname, tparms); + + if (template_debug) + Printf(stdout, " previous instantiation with name '%s' found: '%s' - duplicate instantiation ignored\n", previous_symname, Getattr(n, "name")); + SWIG_WARN_NODE_BEGIN(n); + Swig_warning(WARN_TYPE_REDEFINED, cparse_file, cparse_line, "Duplicate template instantiation of '%s' with name '%s' ignored,\n", SwigType_namestr(unprocessed_tname), symname); + Swig_warning(WARN_TYPE_REDEFINED, Getfile(n), Getline(n), "previous instantiation of '%s' with name '%s'.\n", SwigType_namestr(previous_name), previous_symname); + SWIG_WARN_NODE_END(n); + + Delete(unprocessed_tname); + return 0; + } + if (template_debug) + Printf(stdout, " previous empty template instantiation found: '%s' - using as duplicate instantiation overrides empty template instantiation\n", Getattr(n, "name")); n = tn; - goto success; /* Previously wrapped by a template instantiation */ + goto success; } Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n)); Delete(tname); @@ -929,8 +960,8 @@ success: * template exists. * ----------------------------------------------------------------------------- */ -Node *Swig_cparse_template_locate(String *name, Parm *tparms, Symtab *tscope) { - Node *n = template_locate(name, tparms, tscope); /* this function does what we want for templated classes */ +Node *Swig_cparse_template_locate(String *name, Parm *tparms, String *symname, Symtab *tscope) { + Node *n = template_locate(name, tparms, symname, tscope); /* this function does what we want for templated classes */ if (n) { String *nodeType = nodeType(n); diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index 4a2a9df90..83ec8ad72 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -446,6 +446,7 @@ class TypePass:private Dispatcher { SwigType_typedef_class(fname); scopename = Copy(fname); } else { + // Does this code ever get executed ?? Swig_warning(WARN_TYPE_REDEFINED, Getfile(n), Getline(n), "Template '%s' was already wrapped,\n", SwigType_namestr(name)); Swig_warning(WARN_TYPE_REDEFINED, Getfile(cn), Getline(cn), "previous wrap of '%s'.\n", SwigType_namestr(Getattr(cn, "name"))); scopename = 0; From 29bc7492a2ec300997eaf670bf24f1556fef08cd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 18 Nov 2022 19:44:00 +0000 Subject: [PATCH 162/217] SwigType * handling corrections - Python builtin mangling Further corrections to pass SwigType * to methods expecting types instead of passing readable type strings. Swig_string_mangle() takes a generic String *, but it was calling functions that require SwigType *. Swig_string_mangle_type() is now provided for SwigType *. The previous commit is a pre-requisite in order to prevent duplicate symbols from being generated in the C++ wrappers. --- Source/Modules/python.cxx | 46 +++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 6f30c1faa..b613b2bd0 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1898,16 +1898,20 @@ public: String *str = Getattr(n, "feature:docstring"); if (!str || Len(str) == 0) { if (builtin) { - String *name = Getattr(n, "name"); - String *rname = add_explicit_scope(SwigType_namestr(name)); + SwigType *name = Getattr(n, "name"); + SwigType *sname = add_explicit_scope(name); + String *rname = SwigType_namestr(sname); Printf(doc, "%s", rname); + Delete(sname); Delete(rname); } else { + String *classname_str = SwigType_namestr(real_classname); if (CPlusPlus) { - Printf(doc, "Proxy of C++ %s class.", SwigType_namestr(real_classname)); + Printf(doc, "Proxy of C++ %s class.", classname_str); } else { - Printf(doc, "Proxy of C %s struct.", SwigType_namestr(real_classname)); + Printf(doc, "Proxy of C %s struct.", classname_str); } + Delete(classname_str); } } } @@ -3922,35 +3926,36 @@ public: * classHandler() * ------------------------------------------------------------ */ - String *add_explicit_scope(String *s) { + SwigType *add_explicit_scope(SwigType *s) { if (!Strstr(s, "::")) { - String *ss = NewStringf("::%s", s); - Delete(s); - s = ss; + return NewStringf("::%s", s); } - return s; + return Copy(s); } void builtin_pre_decl(Node *n) { - String *name = Getattr(n, "name"); - String *rname = add_explicit_scope(SwigType_namestr(name)); - String *mname = SwigType_manglestr(rname); + SwigType *name = Getattr(n, "name"); + SwigType *sname = add_explicit_scope(name); + String *rname = SwigType_namestr(sname); + String *mname = SwigType_manglestr(sname); Printf(f_init, "\n/* type '%s' */\n", rname); Printf(f_init, " builtin_pytype = (PyTypeObject *)&SwigPyBuiltin_%s_type;\n", mname); Printf(f_init, " builtin_pytype->tp_dict = d = PyDict_New();\n"); + Delete(sname); Delete(rname); Delete(mname); } void builtin_post_decl(File *f, Node *n) { - String *name = Getattr(n, "name"); - String *pname = Copy(name); + SwigType *name = Getattr(n, "name"); + SwigType *pname = Copy(name); SwigType_add_pointer(pname); String *symname = Getattr(n, "sym:name"); - String *rname = add_explicit_scope(SwigType_namestr(name)); - String *mname = SwigType_manglestr(rname); + SwigType *sname = add_explicit_scope(name); + String *rname = SwigType_namestr(sname); + String *mname = SwigType_manglestr(sname); String *pmname = SwigType_manglestr(pname); String *templ = NewStringf("SwigPyBuiltin_%s", mname); int funpack = fastunpack; @@ -4381,9 +4386,10 @@ public: Delete(clientdata); Delete(smart); + Delete(sname); Delete(rname); - Delete(pname); Delete(mname); + Delete(pname); Delete(pmname); Delete(templ); Delete(tp_flags); @@ -4480,9 +4486,11 @@ public: Setattr(n, "feature:python:tp_doc", ds); Delete(ds); } else { - String *name = Getattr(n, "name"); - String *rname = add_explicit_scope(SwigType_namestr(name)); + SwigType *name = Getattr(n, "name"); + SwigType *sname = add_explicit_scope(name); + String *rname = SwigType_namestr(sname); Setattr(n, "feature:python:tp_doc", rname); + Delete(sname); Delete(rname); } } else { From 1dd31446ce5e24901b9671927a098e23e40c4651 Mon Sep 17 00:00:00 2001 From: AndLLA <44858649+AndLLA@users.noreply.github.com> Date: Sun, 20 Nov 2022 18:52:00 +0100 Subject: [PATCH 163/217] more r tests --- Examples/test-suite/r/template_ref_type_runme.R | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Examples/test-suite/r/template_ref_type_runme.R diff --git a/Examples/test-suite/r/template_ref_type_runme.R b/Examples/test-suite/r/template_ref_type_runme.R new file mode 100644 index 000000000..2565019d7 --- /dev/null +++ b/Examples/test-suite/r/template_ref_type_runme.R @@ -0,0 +1,14 @@ + +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) +#source("unittest.R") + +dyn.load(paste("template_ref_type", .Platform$dynlib.ext, sep="")) +source("template_ref_type.R") +cacheMetaData(1) + +xr = XC() +y = Y() + +unittest(Y_find(y, xr), FALSE) + From 0341258af7003121cdddda78c868ea2d497f8364 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 22 Nov 2022 08:30:39 +0000 Subject: [PATCH 164/217] Fix seg fault handling template parameter expressions containing '<=' Recent commits ensure types are correctly stored in SwigType *. In particular template parameters are enclosed within '<(' and ')>'. Now we can confidently handle template parameters as really being delimited as such to fix an infinite loop handling template expressions containing '<' or '>'. The previous implementation only assumed template parameters were delimited by '<' and '>'. Issue #1037 --- CHANGES.current | 3 +++ Examples/test-suite/cpp17_enable_if_t.i | 13 +++++++++++++ Source/Swig/typeobj.c | 13 ++++++++----- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index e184cc6d8..e3165b178 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2022-11-22: wsfulton + #1037 Fix seg fault handling template parameter expressions containing '<='. + 2022-11-18: wsfulton Duplicate class template instantiations via %template now issue a warning and are ignored. diff --git a/Examples/test-suite/cpp17_enable_if_t.i b/Examples/test-suite/cpp17_enable_if_t.i index b361775d0..7c188dcfa 100644 --- a/Examples/test-suite/cpp17_enable_if_t.i +++ b/Examples/test-suite/cpp17_enable_if_t.i @@ -37,3 +37,16 @@ void tester() { // non-type template parameters working well in SWIG, below is a simple workaround as the 3rd parameter is defaulted for enable_if_t (which is just SFINAE to give a nice C++ compiler error) %template(enableif5) enableif5; // workaround + + +%inline %{ +// #1037 infinite loop +template > +void destId(T el) {} + +/* +not yet fixed +template = 3>> +void destId(const T& el) {} +*/ +%} diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c index 8cd2e28e9..569d2a406 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -1234,17 +1234,20 @@ String *SwigType_prefix(const SwigType *t) { while (d > c) { d--; - if (*d == '>') { + if (*d == '>' && (d > c) && *(d - 1) == ')') { + /* skip over template parameters */ int nest = 1; d--; + d--; while ((d > c) && (nest)) { - if (*d == '>') + if (*d == '>' && *(d - 1) == ')') nest++; - if (*d == '<') + if (*d == '<' && *(d + 1) == '(') nest--; d--; } } + if (*d == ')') { /* Skip over params */ int nparen = 1; @@ -1259,10 +1262,10 @@ String *SwigType_prefix(const SwigType *t) { } if (*d == '.') { - char t = *(d + 1); + char x = *(d + 1); *(d + 1) = 0; r = NewString(c); - *(d + 1) = t; + *(d + 1) = x; return r; } } From ca5c68e5441fa8334381bd26ea2ff5132c26e6ab Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 22 Nov 2022 21:40:38 +0000 Subject: [PATCH 165/217] Fix seg fault handling template parameter expressions containing '>=' Similar to previous commit Issue #1037 --- CHANGES.current | 3 ++- Examples/test-suite/cpp17_enable_if_t.i | 3 --- Source/Swig/typeobj.c | 22 ++++++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index e3165b178..2e991b61b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -8,7 +8,8 @@ Version 4.2.0 (in progress) =========================== 2022-11-22: wsfulton - #1037 Fix seg fault handling template parameter expressions containing '<='. + #1037 Fix seg fault handling template parameter expressions containing '<=' + or '>='. 2022-11-18: wsfulton Duplicate class template instantiations via %template now issue a warning and are ignored. diff --git a/Examples/test-suite/cpp17_enable_if_t.i b/Examples/test-suite/cpp17_enable_if_t.i index 7c188dcfa..46515b9a3 100644 --- a/Examples/test-suite/cpp17_enable_if_t.i +++ b/Examples/test-suite/cpp17_enable_if_t.i @@ -44,9 +44,6 @@ void tester() { template > void destId(T el) {} -/* -not yet fixed template = 3>> void destId(const T& el) {} -*/ %} diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c index 569d2a406..584e2424b 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -1043,16 +1043,17 @@ String *SwigType_templateprefix(const SwigType *t) { * ----------------------------------------------------------------------------- */ String *SwigType_templatesuffix(const SwigType *t) { - const char *c; + const char *c, *d; c = Char(t); - while (*c) { + d = c + strlen(c); + while (d > c) { if ((*c == '<') && (*(c + 1) == '(')) { int nest = 1; c++; - while (*c && nest) { - if (*c == '<') + while ((d > c) && nest) { + if (*c == '<' && *(c + 1) == '(') nest++; - if (*c == '>') + if (*c == '>' && *(c - 1) == ')') nest--; c++; } @@ -1120,18 +1121,19 @@ String *SwigType_istemplate_only_templateprefix(const SwigType *t) { * ----------------------------------------------------------------------------- */ String *SwigType_templateargs(const SwigType *t) { - const char *c; + const char *c, *d; const char *start; c = Char(t); - while (*c) { + d = c + strlen(c); + while (d > c) { if ((*c == '<') && (*(c + 1) == '(')) { int nest = 1; start = c; c++; - while (*c && nest) { - if (*c == '<') + while ((d > c) && nest) { + if (*c == '<' && *(c + 1) == '(') nest++; - if (*c == '>') + if (*c == '>' && *(c - 1) == ')') nest--; c++; } From e0904f44eb1eed9913bb8c93452d7662ea5b2c6f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 23 Nov 2022 07:32:12 +0000 Subject: [PATCH 166/217] Restore testing template_expr testcase Problems handling < and > in template parameters are now fixed. Remove illegal C++ code (template typedefs) - replace with a function using same template. --- Examples/test-suite/common.mk | 2 +- Examples/test-suite/template_expr.i | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index d26f2505c..2539a65ba 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -90,7 +90,6 @@ CPP_TEST_BROKEN += \ nested_private \ template_default_pointer \ template_private_assignment \ - template_expr \ $(CPP11_TEST_BROKEN) \ $(CPP14_TEST_BROKEN) \ $(CPP17_TEST_BROKEN) \ @@ -459,6 +458,7 @@ CPP_TEST_CASES += \ template_enum_ns_inherit \ template_enum_typedef \ template_explicit \ + template_expr \ template_extend1 \ template_extend2 \ template_extend_overload \ diff --git a/Examples/test-suite/template_expr.i b/Examples/test-suite/template_expr.i index a1bb7ef09..98e66e3c4 100644 --- a/Examples/test-suite/template_expr.i +++ b/Examples/test-suite/template_expr.i @@ -2,8 +2,11 @@ // bug #925555 %inline %{ +struct ThisType {}; +template + class vctFixedLengthConstSequenceBase {}; - template inline const ThisType & ConcatenationOf(const vctFixedLengthConstSequenceBase<_size - 1, @@ -30,9 +33,15 @@ class X {}; // bug #646275 %inline %{ +struct Ty {}; +template struct Test {}; +template struct CondRetType { + typedef Type TestRm1; +}; + template - typedef typename CondRetType< Rank!=1, - Test, Type>::TestRm1 TestRm1; + void Func(typename CondRetType< Rank!=1, + Test, Type>::TestRm1) {} %} From d3095144e1c04b4e8c33fd43ad08b9db9f63b084 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 23 Nov 2022 19:57:20 +0000 Subject: [PATCH 167/217] Optimise SwigType_base implementation Also fixes assumption that templates start '<' instead of '<('. Checked java and python test-suite - no changes in output. --- Source/Swig/typeobj.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c index 584e2424b..088497fa5 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -1181,20 +1181,9 @@ SwigType *SwigType_base(const SwigType *t) { 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 == '<' && *(c + 1) == '(') { + /* start of template parameters --- the remainder is part of the base */ + break; } if (*c == '(') { /* Skip over params */ From eef3de65749d9411d61b38f0b3d7cc7aa52226a2 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 23 Nov 2022 20:39:24 +0000 Subject: [PATCH 168/217] Variadic template docs correction --- Doc/Manual/CPlusPlus11.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index a84ca5f51..db47ee9dc 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -1106,7 +1106,7 @@ initializers) with some limitations. The following code is correctly parsed:

      template <typename... BaseClasses> class ClassName : public BaseClasses... { public: ClassName (BaseClasses &&... baseClasses) : BaseClasses(baseClasses)... {} -} +};

      From 81c6a6389873d58795a9b75a8b39f38dd32f850f Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 25 Nov 2022 09:51:58 +1300 Subject: [PATCH 169/217] Fix undefined behaviour in parser Fix undefined behaviour in swig's parser when handling default parameter expressions containing method calls. Fixes #2447 --- CHANGES.current | 4 ++++ Examples/test-suite/default_arg_expressions.i | 4 +++- Source/CParse/parser.y | 8 ++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index e268b30ea..ba8bc36ef 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2022-11-25: olly + #2447 Fix undefined behaviour in swig's parser when handling + default parameter expressions containing method calls. + 2022-11-22: wsfulton #1037 Fix seg fault handling template parameter expressions containing '<=' or '>='. diff --git a/Examples/test-suite/default_arg_expressions.i b/Examples/test-suite/default_arg_expressions.i index 99d54c3b9..ce4d3f4a1 100644 --- a/Examples/test-suite/default_arg_expressions.i +++ b/Examples/test-suite/default_arg_expressions.i @@ -29,7 +29,7 @@ struct TfToken { struct Tokens { const TfToken face; const TfToken *pface; - const TfToken& g_face() const { return face; } + const TfToken& g_face(int = 0, int = 0) const { return face; } const TfToken* g_pface() const { return pface; } Tokens() : face(), pface(&face) {} }; @@ -68,4 +68,6 @@ void CreateMaterialBindSubsetu(int num = UsdGeomTokensPtr->g_pface()->g_val().g_ void CreateMaterialBindSubsetv(int num = UsdGeomTokensPtr->g_pface()->g_ptr()->g_val()) {} void CreateMaterialBindSubsetw(int num = UsdGeomTokensPtr->g_face().g_val().g_val()) {} void CreateMaterialBindSubsetx(int num = UsdGeomTokens.g_face().g_val().g_val()) {} +void CreateMaterialBindSubsety(int num = UsdGeomTokens.g_face(1).g_val().g_val()) {} +void CreateMaterialBindSubsetz(int num = UsdGeomTokens.g_face(1,2).g_val().g_val()) {} %} diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 61fac2b2e..7b5df73ee 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -6582,7 +6582,7 @@ exprmem : ID ARROW ID { $$.type = 0; } | ID ARROW ID LPAREN callparms RPAREN { - $$.val = NewStringf("%s->%s(%s)", $1, $3, $5); + $$.val = NewStringf("%s->%s(%s)", $1, $3, $5.val); $$.type = 0; } | exprmem ARROW ID { @@ -6591,14 +6591,14 @@ exprmem : ID ARROW ID { } | exprmem ARROW ID LPAREN callparms RPAREN { $$ = $1; - Printf($$.val, "->%s(%s)", $3, $5); + Printf($$.val, "->%s(%s)", $3, $5.val); } | ID PERIOD ID { $$.val = NewStringf("%s.%s", $1, $3); $$.type = 0; } | ID PERIOD ID LPAREN callparms RPAREN { - $$.val = NewStringf("%s.%s(%s)", $1, $3, $5); + $$.val = NewStringf("%s.%s(%s)", $1, $3, $5.val); $$.type = 0; } | exprmem PERIOD ID { @@ -6607,7 +6607,7 @@ exprmem : ID ARROW ID { } | exprmem PERIOD ID LPAREN callparms RPAREN { $$ = $1; - Printf($$.val, ".%s(%s)", $3, $5); + Printf($$.val, ".%s(%s)", $3, $5.val); } ; From 081d44d45ea4ef4247580a9baa1f8bb64bd16b77 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 25 Nov 2022 12:29:52 +1300 Subject: [PATCH 170/217] Follow-on fix for previous change These cases don't trigger ubsan warnings and seem to work locally for me, but CI was failing on a number of builds. See #2447 --- Source/CParse/parser.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 7b5df73ee..c92f82a18 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -5294,13 +5294,13 @@ valparm : parm { callparms : valexpr callptail { $$ = $1; - Printf($$.val, "%s", $2); + Printf($$.val, "%s", $2.val); } | empty { $$.val = NewStringEmpty(); } ; callptail : COMMA valexpr callptail { - $$.val = NewStringf(",%s%s", $2, $3); + $$.val = NewStringf(",%s%s", $2.val, $3.val); $$.type = 0; } | empty { $$.val = NewStringEmpty(); } From 9b91b24d6be0c5296b08b527b70e6abd5507b3c2 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 25 Nov 2022 08:29:01 +0000 Subject: [PATCH 171/217] Fix syntax error parsing unnamed template parameters with a default. Closes #961 --- CHANGES.current | 3 ++ Examples/test-suite/cpp17_enable_if_t.i | 42 ++++++++++++++++++++++++- Source/CParse/parser.y | 3 +- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index ba8bc36ef..e240ca3bc 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2022-11-25: wsfulton + #961 Fix syntax error parsing unnamed template parameters with a default value. + 2022-11-25: olly #2447 Fix undefined behaviour in swig's parser when handling default parameter expressions containing method calls. diff --git a/Examples/test-suite/cpp17_enable_if_t.i b/Examples/test-suite/cpp17_enable_if_t.i index 46515b9a3..a6695bca9 100644 --- a/Examples/test-suite/cpp17_enable_if_t.i +++ b/Examples/test-suite/cpp17_enable_if_t.i @@ -32,11 +32,12 @@ template and st void tester() { enableif5(10, 20); + enableif5(10, 20); } %} // non-type template parameters working well in SWIG, below is a simple workaround as the 3rd parameter is defaulted for enable_if_t (which is just SFINAE to give a nice C++ compiler error) -%template(enableif5) enableif5; // workaround +%template(enableif5) enableif5; // workaround (overriding default) %inline %{ @@ -47,3 +48,42 @@ void destId(T el) {} template = 3>> void destId(const T& el) {} %} + +%inline %{ +// #961 no name for defaulted template parameter +template::value>> +void uuu() {} +template::value>> +void uuuE() {} + +template::value>::type> +void vvv() {} +template::value>::type> +void vvvE() {} + +// More variations of enable_if and enable_if_t +template::value>::type* = nullptr> +void www() {} + +template::value, int> = 0> +void xxx() {} + +enum TestEnum { Enum1 = 1, Enum2 }; +struct TestStruct {}; + +void tester2() { + uuu(); +// uuu(); // compilation error + uuuE(); +// uuuE(); // compilation error + vvv(); +// vvv(); // compilation error + vvvE(); +// vvvE(); // compilation error + + www(); +// www(); // compilation error + xxx(); +// xxx(); // compilation error +} +%} diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index c92f82a18..04e6e9809 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -4489,8 +4489,9 @@ templateparameters : templateparameter templateparameterstail { | empty { $$ = 0; } ; -templateparameter : templcpptype { +templateparameter : templcpptype def_args { $$ = NewParmWithoutFileLineInfo(NewString($1), 0); + Setattr($$, "value", $2.rawval ? $2.rawval : $2.val); } | parm { $$ = $1; From 2a1711e4364afe0250282e032650e3ac543e73a3 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 26 Nov 2022 01:16:20 +0000 Subject: [PATCH 172/217] Slightly better decltype() support for expressions decltype now accepts C++ expressions instead of just an ID, such as: int i,j; ... decltype(i+j) ... ... decltype(&i) ... These result in a warning for non-trivial expressions which SWIG cannot evaluate: Warning 344: Unable to deduce decltype for 'i+j'. See 'Type Inference' in CPlusPlus.html for workarounds. Issue #1589 Issue #1590 --- CHANGES.current | 14 ++++++++ Doc/Manual/CPlusPlus11.html | 35 ++++++++++++++++--- Doc/Manual/Warnings.html | 3 ++ Examples/test-suite/common.mk | 1 + Examples/test-suite/cpp11_decltype.i | 28 +++++++++++++-- .../test-suite/python/cpp11_decltype_runme.py | 8 ++--- Source/CParse/parser.y | 9 ++--- Source/Include/swigwarn.h | 1 + 8 files changed, 85 insertions(+), 14 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index e240ca3bc..9de2a3e72 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,20 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2022-11-26: wsfulton + #1589 #1590 Slightly better decltype() support for expressions, such as: + + int i,j; + ... decltype(i+j) ... + ... decltype(&i) ... + + These result in a warning for non-trivial expressions which SWIG cannot evaluate: + + Warning 344: Unable to deduce decltype for 'i+j'. + + See 'Type Inference' in CPlusPlus.html for workarounds. + + 2022-11-25: wsfulton #961 Fix syntax error parsing unnamed template parameters with a default value. diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index db47ee9dc..50402cefd 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -720,18 +720,45 @@ AltStruct var2{2, 4.3}; // calls the constructor

      7.2.6 Type inference

      -

      SWIG supports decltype() with some limitations. Single -variables are allowed, however, expressions are not supported yet. For +

      SWIG supports decltype() with limitations. Single +variables are allowed, however, non-trivial expressions are not supported very well. For example, the following code will work:

       int i;
       decltype(i) j;
       
      -

      However, using an expression inside the decltype results in syntax error:

      +

      SWIG is able to deduce that the variable, i, is type int. +

      + +

      +Using a non-trivial expression for the decltype results in a warning:

       int i; int j;
      -decltype(i+j) k;  // syntax error
      +decltype(i+j) k;  // Warning 344: Unable to deduce decltype for 'i+j'.
      +
      + +

      +This warning should be viewed as a prompt to add in a manual ignore of the variable/function as +in most cases the generated code will not compile. +For the example above, ignore the symbol that uses decltype and perhaps additionally +suppress the warning as follows: +

      + +
      +#pragma SWIG nowarn=SWIGWARN_CPP11_DECLTYPE
      +%ignore k;
      +
      + +

      +If an ignore is not acceptable, a workaround is to redefine the symbol with the actual type, for example: +

      + +
      +int k; // define k with the actual type
      +%ignore k; // ignore the real definition of k
      +int i; int j;
      +decltype(i+j) k;  // Warning 344: Unable to deduce decltype for 'i+j'.
       

      SWIG does not support auto as a type specifier for variables, only diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index 9d5361dae..1cdf37ec2 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -438,6 +438,9 @@ example.i(4) : Syntax error in input(1).

    • 325. Nested kind not currently supported (name ignored).
    • 326. Deprecated %extend name used - the kind name 'name' should be used instead of the typedef name 'name'.
    • 327. Extern template ignored. +
    • 340. Lambda expressions and closures are not fully supported yet. +
    • 343. Only the first variadic template argument is currently supported. +
    • 344. Unable to deduce decltype for 'expr'.
    • 350. operator new ignored.
    • 351. operator delete ignored.
    • 352. operator+ ignored. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 2539a65ba..cd634081c 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -624,6 +624,7 @@ CPP11_TEST_CASES += \ cpp11_thread_local \ cpp11_template_double_brackets \ cpp11_template_explicit \ + cpp11_template_parameters_decltype \ cpp11_template_typedefs \ cpp11_type_traits \ cpp11_type_aliasing \ diff --git a/Examples/test-suite/cpp11_decltype.i b/Examples/test-suite/cpp11_decltype.i index deedd5953..ec2772d0c 100644 --- a/Examples/test-suite/cpp11_decltype.i +++ b/Examples/test-suite/cpp11_decltype.i @@ -9,11 +9,35 @@ int i; decltype(i) j; - auto foo( decltype(i) a ) -> decltype(i) { + auto get_number(decltype(i) a) -> decltype(i) { if (a==5) return 10; else return 0; } }; - %} +%} + + +// These are ignored as unable to deduce decltype for (i+j) +%ignore B::k; +%ignore B::get_number_sum; +%ignore B::get_number_address; +#pragma SWIG nowarn=SWIGWARN_CPP11_DECLTYPE + +%inline %{ + class B { + public: + int i; + decltype(i) j; + decltype(i+j) k; + + auto get_number_sum(decltype(i+j) a) -> decltype(i+j) { + return i+j; + } + + auto get_number_address(decltype(&i) a) -> decltype(&i) { + return &i; + } + }; +%} diff --git a/Examples/test-suite/python/cpp11_decltype_runme.py b/Examples/test-suite/python/cpp11_decltype_runme.py index a18f334dc..436443988 100644 --- a/Examples/test-suite/python/cpp11_decltype_runme.py +++ b/Examples/test-suite/python/cpp11_decltype_runme.py @@ -9,10 +9,10 @@ a.j = 10 if a.j != 10: raise RuntimeError("Assignment to a.j failed.") -b = a.foo(5) +b = a.get_int(5) if b != 10: - raise RuntimeError("foo(5) should return 10.") + raise RuntimeError("get_int(5) should return 10.") -b = a.foo(6) +b = a.get_int(6) if b != 0: - raise RuntimeError("foo(6) should return 0.") + raise RuntimeError("get_int(6) should return 0.") diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 04e6e9809..526d65ff6 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -6241,11 +6241,12 @@ type_right : primitive_type { $$ = $1; } ; -decltype : DECLTYPE LPAREN idcolon RPAREN { - Node *n = Swig_symbol_clookup($3,0); +decltype : DECLTYPE LPAREN expr RPAREN { + Node *n = Swig_symbol_clookup($3.val, 0); if (!n) { - Swig_error(cparse_file, cparse_line, "Identifier %s not defined.\n", $3); - $$ = $3; + Swig_warning(WARN_CPP11_DECLTYPE, cparse_file, cparse_line, "Unable to deduce decltype for '%s'.\n", $3.val); + + $$ = NewStringf("decltype(%s)", $3.val); } else { $$ = Getattr(n, "type"); } diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index f38607f92..cc8192d29 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -99,6 +99,7 @@ #define WARN_CPP11_ALIAS_DECLARATION 341 /* redundant now */ #define WARN_CPP11_ALIAS_TEMPLATE 342 /* redundant now */ #define WARN_CPP11_VARIADIC_TEMPLATE 343 +#define WARN_CPP11_DECLTYPE 344 #define WARN_IGNORE_OPERATOR_NEW 350 /* new */ #define WARN_IGNORE_OPERATOR_DELETE 351 /* delete */ From 15692f0e89a75131a56732b828ba88a82fa67203 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 26 Nov 2022 01:27:04 +0000 Subject: [PATCH 173/217] Add missing testcase cpp11_template_parameters_decltype --- .../cpp11_template_parameters_decltype.i | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 Examples/test-suite/cpp11_template_parameters_decltype.i diff --git a/Examples/test-suite/cpp11_template_parameters_decltype.i b/Examples/test-suite/cpp11_template_parameters_decltype.i new file mode 100644 index 000000000..ab2c3e4fc --- /dev/null +++ b/Examples/test-suite/cpp11_template_parameters_decltype.i @@ -0,0 +1,51 @@ +%module cpp11_template_parameters_decltype + +%include +%include +%include + +#pragma SWIG nowarn=SWIGWARN_CPP11_DECLTYPE + +#if 0 +// to fix (non-template expression equivalent to template expression further down): +%inline %{ +#include +#include + void f(bool c = std::is_constructible>>().begin()->first)>::value) {} +%} +#endif + +%inline %{ +// Github issue #1590 +struct Converter { + std::string to_json() const {} +}; +struct Json { + Json(std::string s) {} + template < class T, class = decltype(&T::to_json) > + Json(const T & t) : Json(t.to_json()) {} + +// Github issue #1589 +// To fix +#if !defined(SWIG) + // Implicit constructor: map-like objects (std::map, std::unordered_map, etc) + template ().begin()->first)>::value, + int>::type = 0> + Json(const M & m) : Json(object(m.begin(), m.end())) {} +#endif +}; +%} + +// %template(Json) Json::Json; // not working +%template(Json) Json::Json; // workaround + + +%inline %{ +// Github issue #1589 +template +void A() { } +%} + +// %template(A) A<>; // not working +%template(A) A; // workaround From ecf05445b9317d15dc5336230dbf55d6d18597b0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 26 Nov 2022 09:59:55 +0000 Subject: [PATCH 174/217] Test cases fix --- Examples/test-suite/cpp11_template_parameters_decltype.i | 2 +- Examples/test-suite/python/cpp11_decltype_runme.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Examples/test-suite/cpp11_template_parameters_decltype.i b/Examples/test-suite/cpp11_template_parameters_decltype.i index ab2c3e4fc..1d00124f1 100644 --- a/Examples/test-suite/cpp11_template_parameters_decltype.i +++ b/Examples/test-suite/cpp11_template_parameters_decltype.i @@ -18,7 +18,7 @@ %inline %{ // Github issue #1590 struct Converter { - std::string to_json() const {} + std::string to_json() const { return std::string(); } }; struct Json { Json(std::string s) {} diff --git a/Examples/test-suite/python/cpp11_decltype_runme.py b/Examples/test-suite/python/cpp11_decltype_runme.py index 436443988..82fdcd771 100644 --- a/Examples/test-suite/python/cpp11_decltype_runme.py +++ b/Examples/test-suite/python/cpp11_decltype_runme.py @@ -9,10 +9,10 @@ a.j = 10 if a.j != 10: raise RuntimeError("Assignment to a.j failed.") -b = a.get_int(5) +b = a.get_number(5) if b != 10: - raise RuntimeError("get_int(5) should return 10.") + raise RuntimeError("get_number(5) should return 10.") -b = a.get_int(6) +b = a.get_number(6) if b != 0: - raise RuntimeError("get_int(6) should return 0.") + raise RuntimeError("get_number(6) should return 0.") From 637e2976721ab69936d408e7f7044746e79264fe Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 26 Nov 2022 10:18:11 +0000 Subject: [PATCH 175/217] Test case fix for std::complex and non-floating types deprecation From Visual Studio 2022: warning C4996: 'std::complex::complex': warning STL4037: The effect of instantiating the template std::complex for any type other than float, double, or long double is unspecified. You can define _SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING to suppress this warning. --- Examples/test-suite/director_basic.i | 4 ++-- Examples/test-suite/director_property.i | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/director_basic.i b/Examples/test-suite/director_basic.i index abb1a3d13..6c9769532 100644 --- a/Examples/test-suite/director_basic.i +++ b/Examples/test-suite/director_basic.i @@ -49,7 +49,7 @@ %inline %{ struct A{ - A(std::complex i, double d=0.0) {} + A(std::complex i, double d=0.0) {} A(int i, bool j=false) {} virtual ~A() {} @@ -60,7 +60,7 @@ namespace hi { struct A1 : public A { - A1(std::complex i, double d=0.0) : A(i, d) {} + A1(std::complex i, double d=0.0) : A(i, d) {} A1(int i, bool j=false) : A(i, j) {} virtual int ff(int i = 0) {return i;} diff --git a/Examples/test-suite/director_property.i b/Examples/test-suite/director_property.i index 3f4f57aaa..ef0f2ffe1 100644 --- a/Examples/test-suite/director_property.i +++ b/Examples/test-suite/director_property.i @@ -54,7 +54,7 @@ %inline %{ struct A{ - A(std::complex i, double d=0.0) {} + A(std::complex i, double d=0.0) {} A(int i, bool j=false) {} virtual ~A() {} @@ -65,7 +65,7 @@ namespace hi { struct A1 : public A { - A1(std::complex i, double d=0.0) : A(i, d) {} + A1(std::complex i, double d=0.0) : A(i, d) {} A1(int i, bool j=false) : A(i, j) {} virtual int ff(int i = 0) {return i;} From 60af317956714c23452c1593575511e0577e08ac Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 26 Nov 2022 17:46:09 +0000 Subject: [PATCH 176/217] Fix UBSAN errors in ccache-swig ccache.c:738:18: runtime error: null pointer passed as argument 1, which is declared to never be null Fixes stderr redirect in testname CCACHE_CPP2, when the CCACHE_CPP2 environment variable is defined. mdfour.c:91:20: runtime error: left shift of 139 by 24 places cannot be represented in type 'int' Looks like this brings some stability to the md4 hash calculation. Closes #2449 --- CCache/ccache.c | 16 +++++++++------- CCache/mdfour.c | 4 ++-- CHANGES.current | 4 ++++ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/CCache/ccache.c b/CCache/ccache.c index c5c510388..a28d38324 100644 --- a/CCache/ccache.c +++ b/CCache/ccache.c @@ -735,13 +735,15 @@ static void from_cache(int first) } /* send the cpp stderr, if applicable */ - fd_cpp_stderr = open(cpp_stderr, O_RDONLY | O_BINARY); - if (fd_cpp_stderr != -1) { - copy_fd(fd_cpp_stderr, 2); - close(fd_cpp_stderr); - unlink(cpp_stderr); - free(cpp_stderr); - cpp_stderr = NULL; + if (cpp_stderr) { + fd_cpp_stderr = open(cpp_stderr, O_RDONLY | O_BINARY); + if (fd_cpp_stderr != -1) { + copy_fd(fd_cpp_stderr, 2); + close(fd_cpp_stderr); + unlink(cpp_stderr); + free(cpp_stderr); + cpp_stderr = NULL; + } } /* send the stderr */ diff --git a/CCache/mdfour.c b/CCache/mdfour.c index b098e0215..5b304852b 100644 --- a/CCache/mdfour.c +++ b/CCache/mdfour.c @@ -88,8 +88,8 @@ static void copy64(uint32 *M, const unsigned char *in) int i; for (i=0;i<16;i++) - M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) | - (in[i*4+1]<<8) | (in[i*4+0]<<0); + M[i] = ((uint32)in[i*4+3]<<24) | ((uint32)in[i*4+2]<<16) | + ((uint32)in[i*4+1]<<8) | ((uint32)in[i*4+0]<<0); } static void copy4(unsigned char *out,uint32 x) diff --git a/CHANGES.current b/CHANGES.current index 9de2a3e72..82c6dbee8 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2022-11-26: wsfulton + #2449 Fix undefined behaviour in ccache-swig calculating md4 hashes and possibly + also handling errors when CCACHE_CPP2 is set. + 2022-11-26: wsfulton #1589 #1590 Slightly better decltype() support for expressions, such as: From acf040c3fe5bd719c97ee3cbba171895c4b7da14 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 26 Nov 2022 14:53:22 +0000 Subject: [PATCH 177/217] Add SWIG-4.1.1 RELEASENOTES summary --- RELEASENOTES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASENOTES b/RELEASENOTES index 39bc80cc4..ee5bde625 100644 --- a/RELEASENOTES +++ b/RELEASENOTES @@ -7,6 +7,11 @@ Release Notes Detailed release notes are available with the release and are also published on the SWIG web site at https://swig.org/release.html. +SWIG-4.1.1 summary: +- Couple of stability fixes. +- Some template handling improvements. +- R - minor fixes plus deprecation for rtypecheck typemaps being optional. + SWIG-4.1.0 summary: - Add Javascript Node v12-v18 support, remove support prior to v6. - Octave 6.0 to 6.4 support added. From 8ece583aa00ef1e5b2b80bfbcdad42e6e9178da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20Rosenkr=C3=A4nzer?= Date: Tue, 29 Nov 2022 00:41:27 +0100 Subject: [PATCH 178/217] Fix push/pop mismatch Without this, perlhead.swg does `#pragma GCC diagnostic pop` if `__GNUC__ >= 10` - without any prior `#pragma GCC diagnostic push`. There's also a mismatch between the conditions that trigger `#pragma GCC diagnostic ignored` (where the `push` should be) and the attempt to `#pragma GCC diagnostic pop`. --- CHANGES.current | 3 +++ Lib/perl5/perlhead.swg | 3 +++ 2 files changed, 6 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 82c6dbee8..417bca656 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2022-11-29: bero + Fix mismatch between #pragma GCC diagnostic push and pop statements + 2022-11-26: wsfulton #2449 Fix undefined behaviour in ccache-swig calculating md4 hashes and possibly also handling errors when CCACHE_CPP2 is set. diff --git a/Lib/perl5/perlhead.swg b/Lib/perl5/perlhead.swg index 773adee92..11ea50a9e 100644 --- a/Lib/perl5/perlhead.swg +++ b/Lib/perl5/perlhead.swg @@ -7,6 +7,7 @@ extern "C" { #if __GNUC__ >= 10 #if defined(__cplusplus) +#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wvolatile" #endif #endif @@ -16,8 +17,10 @@ extern "C" { #include "XSUB.h" #if __GNUC__ >= 10 +#if defined(__cplusplus) #pragma GCC diagnostic pop #endif +#endif /* PERL_REVISION was added in Perl 5.6. */ #if !defined PERL_REVISION || (PERL_REVISION-0 == 5 && PERL_VERSION-0 < 8) From c5e02bf327ff6c06cb92f030671a84bdb564b735 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 29 Nov 2022 08:04:37 +0000 Subject: [PATCH 179/217] Ocaml name mangling fix Fixes testcase template_expr which was resulting in OCaml syntax errors. --- Source/Modules/ocaml.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx index 963a0c2d1..13889c93d 100644 --- a/Source/Modules/ocaml.cxx +++ b/Source/Modules/ocaml.cxx @@ -1181,6 +1181,7 @@ public: /* * Produce the symbol name that ocaml will use when referring to the * target item. I wonder if there's a better way to do this: + * (WF - use Swig_name_mangle_string/Swig_name_mangle_type) * * I shudder to think about doing it with a hash lookup, but that would * make a couple of things easier: @@ -1209,6 +1210,8 @@ public: Replaceall(out, "=", "_xx_equals"); Replaceall(out, "/", "_xx_slash"); Replaceall(out, ".", "_xx_dot"); + Replaceall(out, "?", "_xx_question"); + Replaceall(out, ":", "_xx_colon"); return out; } From c85e7f1625f8b421c92b8c1a8279d134ba050ecc Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 30 Nov 2022 07:34:19 +0000 Subject: [PATCH 180/217] Add ccache-swig hash fix to RELEASENOTES --- RELEASENOTES | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASENOTES b/RELEASENOTES index ee5bde625..493f19954 100644 --- a/RELEASENOTES +++ b/RELEASENOTES @@ -9,6 +9,7 @@ published on the SWIG web site at https://swig.org/release.html. SWIG-4.1.1 summary: - Couple of stability fixes. +- Stability fix in ccache-swig when calculating hashes of inputs. - Some template handling improvements. - R - minor fixes plus deprecation for rtypecheck typemaps being optional. From 05b93b1f06fe5299e5bda2c2b1e0d70c7599af61 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 2 Dec 2022 19:16:02 +0000 Subject: [PATCH 181/217] Improved template template parameters support. Previously, specifying more than one simple template template parameter resulted in a parse error. Now multiple template template parameters are working including instantiation with %template. Example: template class, class> class Op, template class X, class Y> class C { ... }; Closes #624 Closes #1021 --- CHANGES.current | 9 ++ Examples/test-suite/common.mk | 1 + Examples/test-suite/cpp11_type_aliasing.i | 36 +++++++ .../template_template_parameters_runme.java | 8 +- ...te_template_template_parameters_runme.java | 36 +++++++ .../template_template_parameters_runme.py | 7 +- .../test-suite/template_template_parameters.i | 33 +++++-- .../template_template_template_parameters.i | 45 +++++++++ Source/CParse/parser.y | 99 +++++++++---------- 9 files changed, 212 insertions(+), 62 deletions(-) create mode 100644 Examples/test-suite/java/template_template_template_parameters_runme.java create mode 100644 Examples/test-suite/template_template_template_parameters.i diff --git a/CHANGES.current b/CHANGES.current index 417bca656..d54db5ba8 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,15 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2022-12-02: wsfulton + #624 #1021 Improved template template parameters support. Previously, specifying more + than one simple template template parameter resulted in a parse error. Now + multiple template template parameters are working including instantiation with + %template. Example: + + template class, class> class Op, template class X, class Y> + class C { ... }; + 2022-11-29: bero Fix mismatch between #pragma GCC diagnostic push and pop statements diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index cd634081c..3a5e7f678 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -497,6 +497,7 @@ CPP_TEST_CASES += \ template_static \ template_tbase_template \ template_template_parameters \ + template_template_template_parameters \ template_typedef \ template_typedef_class_template \ template_typedef_cplx \ diff --git a/Examples/test-suite/cpp11_type_aliasing.i b/Examples/test-suite/cpp11_type_aliasing.i index ea4048408..8bef71247 100644 --- a/Examples/test-suite/cpp11_type_aliasing.i +++ b/Examples/test-suite/cpp11_type_aliasing.i @@ -112,3 +112,39 @@ using callback_t = int(*)(int); callback_t get_callback() { return mult2; } int call(callback_t funk, int param) { return funk(param); } %} + + +// Template template parameters - from #1021 +%inline %{ +#include + +class Node {}; +struct AnyVal { typedef AnyVal Super; }; + +template class C, typename T, typename Super, typename Root, typename O> + using DeriveToBase = typename std::conditional::value, Root, C >::type; + +template + using ImmediateBase = typename std::conditional::value, Root, RParent >::type; + +template class Expression { + typedef _Super Super; +}; + +void TestInstantiationsPart4() { + Expression express; + DeriveToBase derive_to_base = AnyVal(); +} +%} + +#if 0 +// TODO define and instantiate std::conditional and std::is_same +%template(ExpressionInstantiation) Expression; +%template(AnyTypeInstantiation) DeriveToBase; + +%inline %{ +AnyVal takeAnyVal(DeriveToBase av) { + return av; +} +%} +#endif diff --git a/Examples/test-suite/java/template_template_parameters_runme.java b/Examples/test-suite/java/template_template_parameters_runme.java index 613f9087c..244e12985 100644 --- a/Examples/test-suite/java/template_template_parameters_runme.java +++ b/Examples/test-suite/java/template_template_parameters_runme.java @@ -14,7 +14,7 @@ public class template_template_parameters_runme { } public static void main(String argv[]) { - // Test first part + // Test part 1 ListFastBool listBool = new ListFastBool(); listBool.setItem(true); boolean x_boolean = listBool.getAllotype(); @@ -27,7 +27,7 @@ public class template_template_parameters_runme { if (listDouble.getItem() != 10.2) throw new RuntimeException("Failed"); - // Test second part + // Test part 2 FloatTestStruct floatTestStruct = new FloatTestStruct(); FloatContainer2 floatContainer2 = floatTestStruct.getX(); floatContainer2.setX(8.1f); @@ -41,6 +41,10 @@ public class template_template_parameters_runme { IntTestStruct intTestStructReturned = template_template_parameters.TestStructContainer1Method(intTestStruct); if (intTestStructReturned.getX().getX() != 101) throw new RuntimeException("Failed"); + + // Test part 3 + MyFootInt99 mfi99 = new MyFootInt99(); + mfi99.OperatorPlusEquals(mfi99); } } diff --git a/Examples/test-suite/java/template_template_template_parameters_runme.java b/Examples/test-suite/java/template_template_template_parameters_runme.java new file mode 100644 index 000000000..519a9e068 --- /dev/null +++ b/Examples/test-suite/java/template_template_template_parameters_runme.java @@ -0,0 +1,36 @@ + + +import template_template_template_parameters.*; + +public class template_template_template_parameters_runme { + + static { + try { + System.loadLibrary("template_template_template_parameters"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + CustomAttrs custom_attrs = new CustomAttrs(); + AC ac = new AC(); + BAC bac = new BAC(); + CBAC cbac = new CBAC(); + DBAC dbac = new DBAC(); + + custom_attrs = ac.getAttributes(); + custom_attrs = bac.getAttributes(); + custom_attrs = cbac.getAttributes(); + custom_attrs = dbac.getAttributes(); + + bac.BMethod(custom_attrs, ac); + cbac.BMethod(custom_attrs, ac); + dbac.BMethod(custom_attrs, ac); + + cbac.CMethod(custom_attrs, bac); + dbac.DMethod(custom_attrs, bac); + } +} + diff --git a/Examples/test-suite/python/template_template_parameters_runme.py b/Examples/test-suite/python/template_template_parameters_runme.py index 4b0e27d9c..312935970 100644 --- a/Examples/test-suite/python/template_template_parameters_runme.py +++ b/Examples/test-suite/python/template_template_parameters_runme.py @@ -1,6 +1,6 @@ from template_template_parameters import * -# Test first part +# Test part 1 listBool = ListFastBool() listBool.item = True x_boolean = listBool.allotype @@ -13,7 +13,7 @@ x_double = listDouble.allotype if listDouble.item != 10.2: raise RuntimeError("Failed") -# Test second part +# Test part 2 floatTestStruct = FloatTestStruct() floatContainer2 = floatTestStruct.x floatContainer2.x = 8.1 @@ -28,3 +28,6 @@ intTestStructReturned = TestStructContainer1Method(intTestStruct) if intTestStructReturned.x.x != 101: raise RuntimeError("Failed") +# Test part 3 +mfi99 = MyFootInt99() +mfi99 += mfi99 # __iadd__ diff --git a/Examples/test-suite/template_template_parameters.i b/Examples/test-suite/template_template_parameters.i index 53b18b0b0..68c26bebe 100644 --- a/Examples/test-suite/template_template_parameters.i +++ b/Examples/test-suite/template_template_parameters.i @@ -1,9 +1,8 @@ %module template_template_parameters - %inline %{ -/* part 1 */ +// part 1 namespace pfc { template class t_alloc> class array_t {}; @@ -33,7 +32,7 @@ void TestInstantiations() { (void) myListImplInt; } -/* part 2 */ +// part 2 template struct Container1 { @@ -52,10 +51,10 @@ TestStruct TestStructContainer1Method(TestStruct >; %template(ListFastBool) list_tt; @@ -65,9 +64,31 @@ TestStruct TestStructContainer1Method(TestStruct; %template(DoubleAllocFast) pfc::alloc_fast; -/* part 2 */ +// part 2 %template(IntContainer1) Container1; %template(FloatContainer2) Container2; %template(IntTestStruct) TestStruct; %template(FloatTestStruct) TestStruct; + +// part 3 - from #624 + +%rename("") operator+=; // For Ruby and Octave that ignore operator+= + +%inline %{ +template struct Foot { + template