diff --git a/ANNOUNCE b/ANNOUNCE index 9ef41142a..770df1b20 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,10 +1,10 @@ -*** ANNOUNCE: SWIG 1.3.40 (in progress) *** +*** ANNOUNCE: SWIG 1.3.41 (in progress) *** http://www.swig.org -We're pleased to announce SWIG-1.3.40, the latest installment in the -SWIG development effort. SWIG-1.3.40 includes a number of bug fixes +We're pleased to announce SWIG-1.3.41, the latest installment in the +SWIG development effort. SWIG-1.3.41 includes a number of bug fixes and enhancements. What is SWIG? @@ -24,11 +24,11 @@ Availability: ------------- The release is available for download on Sourceforge at - http://prdownloads.sourceforge.net/swig/swig-1.3.40.tar.gz + http://prdownloads.sourceforge.net/swig/swig-1.3.41.tar.gz A Windows version is also available at - http://prdownloads.sourceforge.net/swig/swigwin-1.3.40.zip + http://prdownloads.sourceforge.net/swig/swigwin-1.3.41.zip Please report problems with this release to the swig-dev mailing list, details at http://www.swig.org/mail.html. diff --git a/CCache/Makefile.in b/CCache/Makefile.in index 29cf8db1b..ef20f48a0 100644 --- a/CCache/Makefile.in +++ b/CCache/Makefile.in @@ -37,7 +37,6 @@ $(PACKAGE_NAME).1: ccache.yo -yodl2man -o $(PACKAGE_NAME).1 ccache.yo web/ccache-man.html: ccache.yo - mkdir -p man yodl2html -o web/ccache-man.html ccache.yo install: $(PACKAGE_NAME)$(EXEEXT) $(PACKAGE_NAME).1 @@ -64,8 +63,11 @@ test: test.sh check: test distclean: clean distclean-docs - /bin/rm -f Makefile config.h config.sub config.log build-stamp config.status configure config.h + /bin/rm -f Makefile config.h config.sub config.log build-stamp config.status config.h.in ccache_swig_config.h +maintainer-clean: distclean + /bin/rm -f configure + # FIXME: To fix this, test.sh needs to be able to take ccache from the # installed prefix, not from the source dir. installcheck: diff --git a/CHANGES b/CHANGES index d9426512b..509484e2f 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,264 @@ SWIG (Simplified Wrapper and Interface Generator) See CHANGES.current for current version. +Version 1.3.40 (18 August 2009) +=============================== + +2009-08-17: olly + [Perl] Add "#undef do_exec" to our clean up of Perl global + namespace pollution. + +2009-08-17: olly + [PHP] Fix to wrap a resource returned by __get() in a PHP object (SF#2549217). + +2009-08-17: wsfulton + Fix #2797485 After doing a 'make clean', install fails if yodl2man or yodl2html + is not available. + +2009-08-16: wsfulton + [Octave] Caught exceptions display the type of the C++ exception instead of the + generic "c++-side threw an exception" message. + +2009-08-16: wsfulton + [Java] When %catches is used, fix so that any classes specified in the "throws" + attribute of the "throws" typemap are generated into the Java method's throws clause. + +2009-08-16: wsfulton + [C#] Fix exception handling when %catches is used, reported by Juan Manuel Alvarez. + +2009-08-15: wsfulton + Fix %template seg fault on some cases of overloading the templated method. + Bug reported by Jan Kupec. + +2009-08-15: wsfulton + [Ruby] Add numerous missing wrapped methods for std::vector specialization + as reported by Youssef Jones. + +2009-08-14: wsfulton + [Perl] Add SWIG_ConvertPtrAndOwn() method into the runtime for smart pointer + memory ownership control. shared_ptr support still to be added. Patch from + David Fletcher. + +2009-08-14: olly + [PHP] PHP5 now wraps static member variables as documented. + +2009-08-14: olly + [PHP] Update the PHP "class" example to work with PHP5 and use + modern wrapping features. + +2009-08-13: wsfulton + [PHP] std::vector wrappers overhaul. They no longer require the + specialize_std_vector() macro. Added wrappers for capacity() and reserve(). + +2009-08-13: wsfulton + [PHP] Add const reference typemaps. const reference primitive types are + now passed by value rather than pointer like the other target languages. + Fixes SF#2524029. + +2009-08-08: wsfulton + [Python] More user friendly AttributeError is raised when there are + no constructors generated for the proxy class in the event that the + class is abstract - the error message is now + "No constructor defined - class is abstract" whereas if there are no + public constructors for any other reason and the class is not abstract, + the message remains + "No constructor defined". + [tcl] Similarly for tcl when using -itcl. + +2009-08-04: olly + [PHP] Fix generated code to work with PHP 5.3. + +2009-08-04: vmiklos + [PHP] Various mathematical functions (which would conflict + with the built-in PHP ones) are now automatically handled by + adding a 'c_' prefix. + +2009-08-03: wsfulton + [C#] The std::vector implementation is improved and now uses $typemap such + that the proxy class for T no longer has to be specified in some macros + for correct C# compilation; the following macros are deprecated, where + CSTYPE was the C# type for the C++ class CTYPE: + + SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(CSTYPE, CTYPE) + usage should be removed altogether + + SWIG_STD_VECTOR_SPECIALIZE(CSTYPE, CTYPE) + should be replaced with: + SWIG_STD_VECTOR_ENHANCED(CTYPE) + + Some more details in csharp/std_vector.i + + *** POTENTIAL INCOMPATIBILITY *** + +2009-07-31: olly + [Python] Fix indentation so that we give a useful error if the + module can't be loaded. Patch from Gaetan Lehmann in SF#2829853. + +2009-07-29: wsfulton + Add $typemap(method, typelist) special variable macro. This allows + the contents of a typemap to be inserted within another typemap. + Fully documented in Typemaps.html. + +2009-07-29: vmiklos + [PHP] Static member variables are now prefixed with the + class name. This allows static member variables with the + same name in different classes. + +2009-07-29: olly + [Python] Add missing locks to std::map wrappers. Patch from + Paul Hampson in SF#2813836. + +2009-07-29: olly + [PHP] Fix memory leak in PHP OUTPUT typemaps. Reported by Hitoshi + Amano in SF#2826322. + +2009-07-29: olly + [PHP] Fix memory leak in PHP resource destructor for classes + without a destructor and non-class types. Patch from Hitoshi Amano + in SF#2825303. + +2009-07-28: olly + [PHP] Update warnings about clashes between identifiers and PHP + keywords and automatic renaming to work with the PHP5 class + wrappers. Fixes SF#1613679. + +2009-07-28: vmiklos + [PHP] If a member function is not public but it has a base + which is public, then now a warning is issued and the member + function will be public, as PHP requires this. + +2009-07-21: vmiklos + [PHP] Director support added. + +2009-07-15: olly + [Perl] Don't specify Perl prototype "()" for a constructor with a + different name to the class, as such constructors can still take + parameters. + +2009-07-12: xavier98 + [Octave] Add support for Octave 3.2 API + +2009-07-05: olly + [PHP] Update the list of PHP keywords - "cfunction" is no longer a + keyword in PHP5 and PHP 5.3 added "goto", "namespace", "__DIR__", + and "__NAMESPACE__". + +2009-07-03: olly + [Tcl] To complement USE_TCL_STUBS, add support for USE_TK_STUBS + and SWIG_TCL_STUBS_VERSION. Document all three in the Tcl chapter + of the manual. Based on patch from SF#2810380 by Christian + Gollwitzer. + +2009-07-02: vmiklos + [PHP] Added factory.i for PHP, see the li_factory testcase + for more info on how to use it. + +2009-07-02: wsfulton + Fix -Wallkw option as reported by Solomon Gibbs. + +2009-07-02: wsfulton + Fix syntax error when a nested struct contains a comment containing a * followed + eventually by a /. Regression from 1.3.37, reported by Solomon Gibbs. + +2009-07-01: vmiklos + [PHP] Unknown properties are no longer ignored in proxy + classes. + +2009-07-01: vmiklos + [PHP] Fixed %newobject behaviour, previously any method + marked with %newobject was handled as a constructor. + +2009-06-30: olly + [Ruby] Undefine close and connect macros defined by Ruby API + headers as we don't need them and they can clash with C++ methods + being wrapped. Patch from Vit Ondruch in SF#2814430. + +2009-06-26: olly + [Ruby] Fix to handle FIXNUM values greater than MAXINT passed for a + double parameter. + +2009-06-24: wsfulton + Fix wrapping methods with default arguments and the compactdefaultargs feature + where a class is passed by value and is assigned a default value. The SwigValueWrapper + template workaround for a missing default constructor is no longer used as the code + generated does not call the default constructor. + +2009-06-16: wsfulton + [Java,C#] Fix enum marshalling when %ignore is used on one of the enum items. + Incorrect enum values were being passed to the C++ layer or compilation errors resulted. + +2009-06-02: talby + [Perl] Resolved reference.i overload support problem + identified by John Potowsky. + +2009-05-26: wsfulton + [C#] Improved std::map wrappers based on patch from Yuval Baror. The C# proxy + now implements System.Collections.Generic.IDictionary<>. + + These std:map wrappers have a non-backwards compatible overhaul to make them + like a .NET IDictionary. Some method names have changed as following: + set -> setitem (use this[] property now) + get -> getitem (use this[] property now) + has_key -> ContainsKey + del -> Remove + clear -> Clear + + The following macros used for std::map wrappers are deprecated and will no longer work: + specialize_std_map_on_key + specialize_std_map_on_value + specialize_std_map_on_both + + *** POTENTIAL INCOMPATIBILITY *** + +2009-05-20: vmiklos + [PHP] Add the 'thisown' member to classes. The usage of it + is the same as the Python thisown one: it's 1 by default and + you can set it to 0 if you want to prevent freeing it. (For + example to prevent a double free.) + +2009-05-14: bhy + [Python] Fix the wrong pointer value returned by SwigPyObject_repr(). + +2009-05-13: mutandiz (Mikel Bancroft) + [allegrocl] Minor tweak when wrapping in -nocwrap mode. + +2009-05-11: wsfulton + [C#] Improved std::vector wrappers on the C# proxy side from Yuval Baror. These + implement IList<> instead of IEnumerable<> where possible. + +2009-04-29: wsfulton + [Java, C#] Add the 'notderived' attribute to the javabase and csbase typemaps. + When this attribute is set, the typemap will not apply to classes that are derived + from a C++ base class, eg + %typemap(csbase, notderived="1") SWIGTYPE "CommonBase" + +2009-04-29: olly + [Python] Don't attempt to acquire the GIL in situations where we + know that it will already be locked. This avoids some dead-locks + with mod_python (due to mod_python bugs which are apparently + unlikely to ever be fixed), and results in smaller wrappers which + run a little faster (in tests with Xapian on x86-64 Ubuntu 9.04, + the stripped wrapper library was 11% smaller and ran 2.7% faster). + +2009-04-21: wsfulton + [C#] Fix #2753469 - bool &OUTPUT and bool *OUTPUT typemaps initialisation. + +2009-04-09: wsfulton + Fix #2746858 - C macro expression using floating point numbers + +2009-03-30: olly + [PHP] The default out typemap for char[ANY] now returns the string up to a + zero byte, or the end of the array if there is no zero byte. This + is the same as Python does, and seems more generally useful than + the previous behaviour of returning the whole contents of the array + including any zero bytes. If you want the old behaviour, you can provide + your own typemap to do this: + + %typemap(out) char [ANY] + %{ + RETVAL_STRINGL($1, $1_dim0, 1); + %} + Version 1.3.39 (21 March 2009) ============================== diff --git a/CHANGES.current b/CHANGES.current index 1021106f1..f435f9cb8 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,257 +1,295 @@ -Version 1.3.40 (in progress) +Version 1.3.41 (in progress) ============================ -2009-08-17: olly - [Perl] Add "#undef do_exec" to our clean up of Perl global - namespace pollution. +2010-01-11: wsfulton + Slight change to warning, error and diagnostic reporting. The warning number is no + longer shown within brackets. This is to help default parsing of warning messages by + other tools, vim on Unix in particular. -2009-08-17: olly - [PHP] Fix to wrap a resource returned by __get() in a PHP object (SF#2549217). + Example original display using -Fstandard: + example.i:20: Warning(401): Nothing known about base class 'B'. Ignored. + New display: + example.i:20: Warning 401: Nothing known about base class 'B'. Ignored. -2009-08-17: wsfulton - Fix #2797485 After doing a 'make clean', install fails if yodl2man or yodl2html - is not available. + Also subtle fix to -Fmicrosoft format adding in missing space. Example original display: + example.i(20): Warning(401): Nothing known about base class 'Base'. Ignored. + New display: + example.i(20) : Warning 401: Nothing known about base class 'Base'. Ignored. -2009-08-16: wsfulton - [Octave] Caught exceptions display the type of the C++ exception instead of the - generic "c++-side threw an exception" message. +2010-01-10: wsfulton + Fix a few inconsistencies in reporting of file/line numberings including modifying + the overload warnings 509, 512, 516, 474, 475 to now be two line warnings. -2009-08-16: wsfulton - [Java] When %catches is used, fix so that any classes specified in the "throws" - attribute of the "throws" typemap are generated into the Java method's throws clause. +2010-01-10: wsfulton + Modify -debug-tags output to use standard file name/line reporting so that editors + can easily navigate to the appropriate lines. + Was typically: + . top . include . include (/usr/share/swig/temp/trunk/Lib/swig.swg:312) + . top . include . include . include (/usr/share/swig/temp/trunk/Lib/swigwarnings.swg:39) + now: + /usr/share/swig/temp/trunk/Lib/swig.swg:312: . top . include . include + /usr/share/swig/temp/trunk/Lib/swigwarnings.swg:39: . top . include . include . include -2009-08-16: wsfulton - [C#] Fix exception handling when %catches is used, reported by Juan Manuel Alvarez. +2010-01-03: wsfulton + Fix missing file/line numbers for typemap warnings and in output from the + -debug-tmsearch/-debug-tmused options. -2009-08-15: wsfulton - Fix %template seg fault on some cases of overloading the templated method. - Bug reported by Jan Kupec. +2010-01-03: wsfulton + Add typemaps used debugging option (-debug-tmused). When used each line displays + the typemap used for each type for which code is being generated including the file + and line number related to the type. This is effectively a condensed form of the + -debug-tmsearch option. Documented in Typemaps.html. -2009-08-15: wsfulton - [Ruby] Add numerous missing wrapped methods for std::vector specialization - as reported by Youssef Jones. +2009-12-23: wsfulton + Fix for %javaexception and directors so that all the appropriate throws clauses + are generated. Problem reported by Peter Greenwood. -2009-08-14: wsfulton - [Perl] Add SWIG_ConvertPtrAndOwn() method into the runtime for smart pointer - memory ownership control. shared_ptr support still to be added. Patch from - David Fletcher. +2009-12-20: wsfulton + Add -debug-tmsearch option for debugging the typemap pattern matching rules. + Documented in Typemaps.html. -2009-08-14: olly - [PHP] PHP5 now wraps static member variables as documented. +2009-12-12: wsfulton + [Octave] Remove the -api option and use the new OCTAVE_API_VERSION_NUMBER + macro provided in the octave headers for determining the api version instead. -2009-08-14: olly - [PHP] Update the PHP "class" example to work with PHP5 and use - modern wrapping features. +2009-12-04: olly + [Ruby] Improve support for Ruby 1.9 under GCC. Addresses part of + SF#2859614. -2009-08-13: wsfulton - [PHP] std::vector wrappers overhaul. They no longer require the - specialize_std_vector() macro. Added wrappers for capacity() and reserve(). +2009-12-04: olly + Fix handling of modulo operator (%) in constant expressions + (SF#2818562). -2009-08-13: wsfulton - [PHP] Add const reference typemaps. const reference primitive types are - now passed by value rather than pointer like the other target languages. - Fixes SF#2524029. +2009-12-04: olly + [PHP] "empty" is a reserved word in PHP, so rename empty() method + on STL classes to "is_empty()" (previously this was automatically + renamed to "c_empty()"). + *** POTENTIAL INCOMPATIBILITY *** -2009-08-08: wsfulton - [Python] More user friendly AttributeError is raised when there are - no constructors generated for the proxy class in the event that the - class is abstract - the error message is now - "No constructor defined - class is abstract" whereas if there are no - public constructors for any other reason and the class is not abstract, - the message remains - "No constructor defined". - [tcl] Similarly for tcl when using -itcl. +2009-12-03: olly + [PHP] Add typemaps for long long and unsigned long long, and for + pointer to method. -2009-08-04: olly - [PHP] Fix generated code to work with PHP 5.3. +2009-12-02: olly + [PHP] Fix warning and rename of reserved class name to be case + insensitive. -2009-08-04: vmiklos - [PHP] Various mathematical functions (which would conflict - with the built-in PHP ones) are now automatically handled by - adding a 'c_' prefix. +2009-12-01: wsfulton + Revert support for %extend and memberin typemaps added in swig-1.3.39. The + memberin typemaps are ignored again for member variables within a %extend block. + Documentation inconsistency reported by Torsten Landschoff. -2009-08-03: wsfulton - [C#] The std::vector implementation is improved and now uses $typemap such - that the proxy class for T no longer has to be specified in some macros - for correct C# compilation; the following macros are deprecated, where - CSTYPE was the C# type for the C++ class CTYPE: +2009-11-29: wsfulton + [Java, C#] Fix generated quoting when using %javaconst(1)/%csconst(1) for + static const char member variables. - SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(CSTYPE, CTYPE) - usage should be removed altogether + %javaconst(1) A; + %csconst(1) A; + struct X { + static const char A = 'A'; + }; - SWIG_STD_VECTOR_SPECIALIZE(CSTYPE, CTYPE) - should be replaced with: - SWIG_STD_VECTOR_ENHANCED(CTYPE) +2009-11-26: wsfulton + [Java, C#] Fix %javaconst(1)/%csconst(1) for static const member variables to + use the actual constant value if it is specified, rather than the C++ code to + access the member. - Some more details in csharp/std_vector.i + %javaconst(1) EN; + %csconst(1) EN; + struct X { + static const int EN = 2; + }; + +2009-11-23: wsfulton + C++ nested typedef classes can now be handled too, for example: + struct Outer { + typedef Foo { } FooTypedef1, FooTypedef2; + }; + +2009-11-18: wsfulton + The wrappers for C nested structs are now generated in the same order as declared + in the parsed code. + +2009-11-18: wsfulton + Fix #491476 - multiple declarations of nested structs, for example: + struct Outer { + struct { + int val; + } inner1, inner2, *inner3, inner4[1]; + } outer; + +2009-11-17: wsfulton + Fix parsing of enum declaration and initialization, for example: + + enum ABC { + a, + b, + c + } A = a, *pC = &C, array[3] = {a, b, c}; + +2009-11-17: wsfulton + Fix parsing of struct declaration and initialization, for example: + + struct S { + int x; + } instance = { 10 }; + +2009-11-15: wsfulton + Fix #1960977 - Syntax error parsing derived nested class declaration and member + variable instance. + +2009-11-14: wsfulton + Fix #2310483 - function pointer typedef within extern "C" block. + +2009-11-13: wsfulton + Fix usage of nested template classes within templated classes so that compileable code + is generated. + +2009-11-13: olly + [php] Fix place where class prefix (as specified with -prefix) + wasn't being used. Patch from gverbruggen in SF#2892647. + +2009-11-12: wsfulton + Fix usage of nested template classes so that compileable code is generated - the nested + template class is now treated like a normal nested classes, that is, as an opaque type + unless the nestedworkaround feature is used. + +2009-11-12: wsfulton + Replace SWIGWARN_PARSE_NESTED_CLASS with SWIGWARN_PARSE_NAMED_NESTED_CLASS and + SWIGWARN_PARSE_UNNAMED_NESTED_CLASS for named and unnamed nested classes respectively. + + Named nested class ignored warnings can now be suppressed by name using %warnfilter, eg: + + %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::Inner; + + but clearly unnamed nested classes cannot and the global suppression is still required, eg: + + #pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS + +2009-11-11: wsfulton + Added the nestedworkaround feature as a way to use the full functionality of a nested class + (C++ mode only). It removes the nested class from SWIG's type information so it is as if SWIG + had never parsed the nested class. The documented nested class workarounds using a global + fake class stopped working when SWIG treated the nested class as an opaque pointer, and + this feature reverts this behaviour. The documentation has been updated with details of how + to use and implement it, see the "Nested classes" section in SWIGPlus.html. + +2009-11-11: wsfulton + There were a number of C++ cases where nested classes/structs/unions were being handled + as if C code was being parsed which would oftentimes lead to uncompileable code as an + attempt was made to wrap the nested structs like it is documented for C code. Now all + nested structs/classes/unions are ignored in C++ mode, as was always documented. However, + there is an improvement as usage of nested structs/classes/unions is now always treated + as an opaque type by default, resulting in generated code that should always compile. *** POTENTIAL INCOMPATIBILITY *** -2009-07-31: olly - [Python] Fix indentation so that we give a useful error if the - module can't be loaded. Patch from Gaetan Lehmann in SF#2829853. +2009-11-09: drjoe + Fix R for -fcompact and add std_map.i -2009-07-29: wsfulton - Add $typemap(method, typelist) special variable macro. This allows - the contents of a typemap to be inserted within another typemap. - Fully documented in Typemaps.html. +2009-11-08: wsfulton + Fix inconsistency for nested structs/unions/classes. Uncompileable code was being + generated when inner struct and union declarations were used as types within the + inner struct. The inner struct/union is now treated as a forward declaration making the + behaviour the same as an inner class. (C++ code), eg: -2009-07-29: vmiklos - [PHP] Static member variables are now prefixed with the - class name. This allows static member variables with the - same name in different classes. + struct Outer { + struct InnerStruct { int x; }; + InnerStruct* getInnerStruct(); + }; -2009-07-29: olly - [Python] Add missing locks to std::map wrappers. Patch from - Paul Hampson in SF#2813836. +2009-11-08: wsfulton + Ignored nested class/struct warnings now display the name of the ignored class/struct. -2009-07-29: olly - [PHP] Fix memory leak in PHP OUTPUT typemaps. Reported by Hitoshi - Amano in SF#2826322. +2009-11-07: wsfulton + Bug #1514681 - Fix nested template classes within a namespace generated uncompileable + code and introduced strange side effects to other wrapper code especially code + after the nested template class. Note that nested template classes are still ignored. -2009-07-29: olly - [PHP] Fix memory leak in PHP resource destructor for classes - without a destructor and non-class types. Patch from Hitoshi Amano - in SF#2825303. +2009-11-07: wsfulton + Add new debug options: + -debug-symtabs - Display symbol tables information + -debug-symbols - Display target language symbols in the symbol tables + -debug-csymbols - Display C symbols in the symbol tables -2009-07-28: olly - [PHP] Update warnings about clashes between identifiers and PHP - keywords and automatic renaming to work with the PHP5 class - wrappers. Fixes SF#1613679. +2009-11-03: wsfulton + Fix some usage of global scope operator, for example: -2009-07-28: vmiklos - [PHP] If a member function is not public but it has a base - which is public, then now a warning is issued and the member - function will be public, as PHP requires this. + namespace AA { /* ... */ } + using namespace ::AA; -2009-07-21: vmiklos - [PHP] Director support added. + and bug #1816802 - SwigValueWrapper should be used: -2009-07-15: olly - [Perl] Don't specify Perl prototype "()" for a constructor with a - different name to the class, as such constructors can still take - parameters. + struct CC { + CC(int); // no default constructor + }; + ::CC x(); -2009-07-12: xavier98 - [Octave] Add support for Octave 3.2 API + and in template parameter specializations: -2009-07-05: olly - [PHP] Update the list of PHP keywords - "cfunction" is no longer a - keyword in PHP5 and PHP 5.3 added "goto", "namespace", "__DIR__", - and "__NAMESPACE__". + struct S {}; + template struct X { void a() {}; }; + template <> struct X { void b() {}; }; + %template(MyTConcrete) X< ::S >; -2009-07-03: olly - [Tcl] To complement USE_TCL_STUBS, add support for USE_TK_STUBS - and SWIG_TCL_STUBS_VERSION. Document all three in the Tcl chapter - of the manual. Based on patch from SF#2810380 by Christian - Gollwitzer. + plus probably some other corner case usage of ::. -2009-07-02: vmiklos - [PHP] Added factory.i for PHP, see the li_factory testcase - for more info on how to use it. +2009-11-02: olly + [Python] Fix potential memory leak in initialisation code for the + generated module. -2009-07-02: wsfulton - Fix -Wallkw option as reported by Solomon Gibbs. +2009-10-23: wsfulton + Fix seg fault when using a named nested template instantiation using %template(name) + within a class. A warning that these are not supported is now issued plus processing + continues as if no name was given. -2009-07-02: wsfulton - Fix syntax error when a nested struct contains a comment containing a * followed - eventually by a /. Regression from 1.3.37, reported by Solomon Gibbs. +2009-10-20: wsfulton + [Python] Fix std::vector. This would previously compile, but not run correctly. -2009-07-01: vmiklos - [PHP] Unknown properties are no longer ignored in proxy - classes. +2009-10-20: wsfulton + Fixed previously fairly poor template partial specialization and explicit + specialization support. Numerous bugs in this area have been fixed including: -2009-07-01: vmiklos - [PHP] Fixed %newobject behaviour, previously any method - marked with %newobject was handled as a constructor. + - Template argument deduction implemented for template type arguments, eg this now + works: + template class X {}; + template class X {}; + %template(X1) X; // Chooses T * specialization -2009-06-30: olly - [Ruby] Undefine close and connect macros defined by Ruby API - headers as we don't need them and they can clash with C++ methods - being wrapped. Patch from Vit Ondruch in SF#2814430. + and more complex cases with multiple parameters and a mix of template argument + deduction and explicitly specialised parameters, eg: + template struct TwoParm { void a() {} }; + template struct TwoParm { void e() {} }; + %template(E) TwoParm; -2009-06-26: olly - [Ruby] Fix to handle FIXNUM values greater than MAXINT passed for a - double parameter. - -2009-06-24: wsfulton - Fix wrapping methods with default arguments and the compactdefaultargs feature - where a class is passed by value and is assigned a default value. The SwigValueWrapper - template workaround for a missing default constructor is no longer used as the code - generated does not call the default constructor. - -2009-06-16: wsfulton - [Java,C#] Fix enum marshalling when %ignore is used on one of the enum items. - Incorrect enum values were being passed to the C++ layer or compilation errors resulted. - -2009-06-02: talby - [Perl] Resolved reference.i overload support problem - identified by John Potowsky. - -2009-05-26: wsfulton - [C#] Improved std::map wrappers based on patch from Yuval Baror. The C# proxy - now implements System.Collections.Generic.IDictionary<>. - - These std:map wrappers have a non-backwards compatible overhaul to make them - like a .NET IDictionary. Some method names have changed as following: - set -> setitem (use this[] property now) - get -> getitem (use this[] property now) - has_key -> ContainsKey - del -> Remove - clear -> Clear - - The following macros used for std::map wrappers are deprecated and will no longer work: - specialize_std_map_on_key - specialize_std_map_on_value - specialize_std_map_on_both + Note that the primary template must now be in scope, like in C++, when + an explicit or partial specialization is instantiated with %template. *** POTENTIAL INCOMPATIBILITY *** -2009-05-20: vmiklos - [PHP] Add the 'thisown' member to classes. The usage of it - is the same as the Python thisown one: it's 1 by default and - you can set it to 0 if you want to prevent freeing it. (For - example to prevent a double free.) +2009-09-14: wsfulton + [C#] Add %csattributes for adding C# attributes to enum values, see docs for example. -2009-05-14: bhy - [Python] Fix the wrong pointer value returned by SwigPyObject_repr(). +2009-09-11: wsfulton + Fix memmove regression in cdata.i as reported by Adriaan Renting. -2009-05-13: mutandiz (Mikel Bancroft) - [allegrocl] Minor tweak when wrapping in -nocwrap mode. +2009-09-07: wsfulton + Fix constant expressions containing <= or >=. -2009-05-11: wsfulton - [C#] Improved std::vector wrappers on the C# proxy side from Yuval Baror. These - implement IList<> instead of IEnumerable<> where possible. +2009-09-02: wsfulton + The following operators in constant expressions now result in type bool for C++ + wrappers and remain as type int for C wrappers, as per each standard: -2009-04-29: wsfulton - [Java, C#] Add the 'notderived' attribute to the javabase and csbase typemaps. - When this attribute is set, the typemap will not apply to classes that are derived - from a C++ base class, eg - %typemap(csbase, notderived="1") SWIGTYPE "CommonBase" + && || == != < > <= >= (Actually the last 4 are still broken). For example: -2009-04-29: olly - [Python] Don't attempt to acquire the GIL in situations where we - know that it will already be locked. This avoids some dead-locks - with mod_python (due to mod_python bugs which are apparently - unlikely to ever be fixed), and results in smaller wrappers which - run a little faster (in tests with Xapian on x86-64 Ubuntu 9.04, - the stripped wrapper library was 11% smaller and ran 2.7% faster). + #define A 10 + #define B 10 + #define A_EQ_B A == B // now wrapped as type bool for C++ + #define A_AND_B A && B // now wrapped as type bool for C++ -2009-04-21: wsfulton - [C#] Fix #2753469 - bool &OUTPUT and bool *OUTPUT typemaps initialisation. +2009-09-02: wsfulton + Fix #2845746. true and false are now recognised keywords (only when wrapping C++). + Constants such as the following are now wrapped (as type bool): + #define FOO true + #define BAR FOO && false -2009-04-09: wsfulton - Fix #2746858 - C macro expression using floating point numbers - -2009-03-30: olly - [PHP] The default out typemap for char[ANY] now returns the string up to a - zero byte, or the end of the array if there is no zero byte. This - is the same as Python does, and seems more generally useful than - the previous behaviour of returning the whole contents of the array - including any zero bytes. If you want the old behaviour, you can provide - your own typemap to do this: - - %typemap(out) char [ANY] - %{ - RETVAL_STRINGL($1, $1_dim0, 1); - %} diff --git a/Doc/Devel/internals.html b/Doc/Devel/internals.html index ea36f844d..63a8626ff 100644 --- a/Doc/Devel/internals.html +++ b/Doc/Devel/internals.html @@ -1070,31 +1070,35 @@ With each is the cast that can be used in the debugger to extract the underlying

  • String *s;

  • -(String *)((DohBase *)s)->data +(struct String *)((DohBase *)s)->data
    The underlying char * string can be displayed with
    -((String *)((DohBase *)s)->data)->str +(*(struct String *)(((DohBase *)s)->data)).str

  • SwigType *t;

  • -(String *)((DohBase *)t)->data +(struct String *)((DohBase *)t)->data
    The underlying char * string can be displayed with
    -((String *)((DohBase *)t)->data)->str +(*(struct String *)(((DohBase *)t)->data)).str

    -

  • String_or_char *sc;
  • +
  • const_String_or_char_ptr sc;
  • Either
    -((String *)((DohBase *)sc)->data)->str +(*(struct String *)(((DohBase *)sc)->data)).str
    or
    (char *)sc
    will work depending on whether the underlying type is really a String * or char *. +

    +Please also read the Debugging Functions section in SWIG Parse Tree Handling for the Swig_print_node(), Swig_print_tree() and Swig_print_tags() functions for displaying node contents. It is often easier to place a few calls to these functions in code of interest and recompile than use the debugger. +

    +
    Copyright (C) 1999-2004 SWIG Development Team. diff --git a/Doc/Devel/tree.html b/Doc/Devel/tree.html index 64d9d197d..43ad191f6 100644 --- a/Doc/Devel/tree.html +++ b/Doc/Devel/tree.html @@ -218,10 +218,10 @@ The following functions are used to help debug SWIG parse trees.
    Prints the tag-structure of the parse tree to standard output. node is the top-level parse tree node. prefix is a string prefix thats added to the start of each line. Normally, you would specify the empty string or NIL for prefix. -This function is called by the -dump_tags option to SWIG. +This function is called by the -debug-tags option to SWIG.
    -% swig -dump_tags -python example.i
    +% swig -debug-tags -python example.i
      . top (:1)
      . top . include (/Users/beazley/Projects/share/swig/1.3.31/swig.swg:0)
      . top . include . include (/Users/beazley/Projects/share/swig/1.3.31/swigwarnings.swg:0)
    @@ -243,7 +243,7 @@ Since many language modules include hundreds of typemaps and other information,
     
     
    Prints the contents of a parse tree node, including all children, to standard output. The output includes all attributes -and other details. The command line option -dump_tree produces output generated by this function. +and other details.

    @@ -251,8 +251,8 @@ and other details. The command line option -dump_tree produces output

    Prints the same output as Swig_print_node() except that it also processes all of the siblings of node. This can -be used to dump the entire parse tree to standard output. Use the command line option -dump_tree to get -the output of this function for a SWIG input file. +be used to dump the entire parse tree to standard output. The command line options -debug-module +and -debug-top use this function to display the parse tree for a SWIG input file.
    diff --git a/Doc/Manual/Allegrocl.html b/Doc/Manual/Allegrocl.html index cc950db7c..cf70f6c27 100644 --- a/Doc/Manual/Allegrocl.html +++ b/Doc/Manual/Allegrocl.html @@ -14,7 +14,7 @@ @@ -2471,7 +2473,7 @@ the parsing of command line options, all aspects of code generation are controll different methods of the Language that must be defined by your module.

    -

    35.10.2 Starting out

    +

    35.10.2 Starting out

    @@ -2602,24 +2604,24 @@ void Language::main(int argc, char *argv[]) { } else { Swig_arg_error(); } - } else if (strcmp(argv[i],"-globals") == 0) { - if (argv[i+1]) { - global_name = NewString(argv[i+1]); - Swig_mark_arg(i); - Swig_mark_arg(i+1); - i++; - } else { - Swig_arg_error(); - } - } else if ( (strcmp(argv[i],"-proxy") == 0)) { - proxy_flag = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-keyword") == 0) { - use_kw = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i],"-help") == 0) { - fputs(usage,stderr); - } + } else if (strcmp(argv[i],"-globals") == 0) { + if (argv[i+1]) { + global_name = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if ( (strcmp(argv[i],"-proxy") == 0)) { + proxy_flag = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-keyword") == 0) { + use_kw = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-help") == 0) { + fputs(usage,stderr); + } ... } } @@ -3053,7 +3055,7 @@ but without the typemaps, there is still work to do.

    -At the time of this writing, SWIG supports nearly a dozen languages, +At the time of this writing, SWIG supports nearly twenty languages, which means that for continued sanity in maintaining the configuration files, the language modules need to follow some conventions. These are outlined here along with the admission that, yes it is ok to violate @@ -3225,7 +3227,7 @@ The following are the minimum that are usually supported: Please copy these and modify for any new language.

    -

    35.10.11 Examples and test cases

    +

    35.10.11 User examples

    @@ -3254,7 +3256,226 @@ during this process, see the section on configuration files.

    -

    35.10.12 Documentation

    +

    35.10.12 Test driven development and the test-suite

    + + +

    +A test driven development approach is central to the improvement and development of SWIG. +Most modifications to SWIG are accompanied by additional regression tests and checking all +tests to ensure that no regressions have been introduced. +

    + +

    +The regression testing is carried out by the SWIG test-suite. +The test-suite consists of numerous testcase interface files in the Examples/test-suite directory +as well as target language specific runtime tests in the Examples/test-suite/[lang] directory. +When a testcase is run, it will execute the following steps for each testcase: +

    + +
      +
    1. Execute SWIG passing it the testcase interface file.
    2. +
    3. Compile the resulting generated C/C++ code with either the C or C++ compiler into object files.
    4. +
    5. Link the object files into a dynamic library (dll/shared object).
    6. +
    7. Compile any generated and any runtime test target language code with the target language compiler, if the target language supports compilation. This step thus does not apply to the interpreted languages.
    8. +
    9. Execute a runtime test if one exists.
    10. +
    + +

    +For example, the ret_by_value testcase consists of two components. +The first component is the Examples/test-suite/ret_by_value.i interface file. +The name of the SWIG module must always be the name of the testcase, so the ret_by_value.i interface file thus begins with: +

    + +
    +
    +%module ret_by_value
    +
    +
    + +

    +The testcase code will then follow the module declaration, +usually within a %inline %{ ... %} section for the majority of the tests. +

    + +

    +The second component is the optional runtime tests. +Any runtime tests are named using the following convention: [testcase]_runme.[ext], +where [testcase] is the testcase name and [ext] is the normal extension for the target language file. +In this case, the Java and Python target languages implement a runtime test, so their files are respectively, +Examples/test-suite/java/ret_by_value_runme.java and +Examples/test-suite/python/ret_by_value_runme.py. +

    + +

    +The goal of the test-suite is to test as much as possible in a silent manner. +This way any SWIG or compiler errors or warnings are easily visible. +Should there be any warnings, changes must be made to either fix them (preferably) or suppress them. +Compilation or runtime errors result in a testcase failure and will be immediately visible. +It is therefore essential that the runtime tests are written in a manner that displays nothing to stdout/stderr on success +but error/exception out with an error message on stderr on failure. +

    + +

    35.10.12.1 Running the test-suite

    + + +

    +In order for the test-suite to work for a particular target language, the language must be correctly detected +and configured during the configure stage so that the correct Makefiles are generated. +Most development occurs on Linux, so usually it is a matter of installing the development packages for the target language +and simply configuring as outlined earlier. +

    + +

    +If when running the test-suite commands that follow, you get a message that the test was skipped, it indicates that the +configure stage is missing information in order to compile and run everything for that language. +

    + +

    +The test-suite can be run in a number of ways. +The first group of commands are for running multiple testcases in one run and should be executed in the top level directory. +To run the entire test-suite (can take a long time): +

    + +
    +make -k check-test-suite
    +
    + +

    +To run the test-suite just for target language [lang], replace [lang] with one of csharp, java, perl5, python, ruby, tcl etc: +

    + +
    +make check-[lang]-test-suite
    +
    + +

    +Note that if a runtime test is available, a message "(with run test)" is displayed when run. For example: +

    + +
    +$ make check-python-test-suite
    +checking python test-suite
    +checking testcase argcargvtest (with run test) under python
    +checking testcase python_autodoc under python
    +checking testcase python_append (with run test) under python
    +checking testcase callback (with run test) under python
    +
    + +

    +The files generated on a previous run can be deleted using the clean targets, either the whole test-suite or for a particular language: +

    + +
    +make clean-test-suite
    +make clean-[lang]-test-suite
    +
    + +

    +The test-suite can be run in a partialcheck mode where just SWIG is executed, that is, the compile, +link and running of the testcases is not performed. +Note that the partialcheck does not require the target language to be correctly configured and detected and unlike the other test-suite make targets, is never skipped. Once again, either all the languages can be executed or just a chosen language: +

    + +
    +make partialcheck-test-suite
    +make partialcheck-[lang]-test-suite
    +
    + +

    +If your computer has more than one CPU, you are strongly advised to use parallel make to speed up the execution speed. +This can be done with any of the make targets that execute more than one testcase. +For example, a dual core processor can efficiently use 2 parallel jobs: +

    + +
    +make -j2 check-test-suite
    +make -j2 check-python-test-suite
    +make -j2 partialcheck-java-test-suite
    +
    + +

    +The second group of commands are for running individual testcases and should be executed in the appropriate +target language directory, Examples/test-suite/[lang]. +Testcases can contain either C or C++ code and when one is written, a decision must be made as to which of these input +languages is to be used. +Replace [testcase] in the commands below with the name of the testcase. +

    + +

    +For a C language testcase, add the testcase under the C_TEST_CASES list in Examples/test-suite/common.mk and +execute individually as: +

    +
    +make -s [testcase].ctest
    +
    + +

    +For a C++ language testcase, add the testcase under the CPP_TEST_CASES list in Examples/test-suite/common.mk and +execute individually as: +

    +
    +make -s [testcase].cpptest
    +
    + +

    +A third category of tests are C++ language testcases testing multiple modules (the %import directive). +These require more than one shared library (dll/shared object) to be built and so are separated out from the normal C++ testcases. +Add the testcase under the MULTI_CPP_TEST_CASES list in Examples/test-suite/common.mk and +execute individually as: +

    +
    +make -s [testcase].multicpptest
    +
    + +

    +To delete the generated files, execute: +

    +
    +make -s [testcase].clean
    +
    + +

    +If you would like to see the exact commands being executed, drop the -s option: +

    +
    +make [testcase].ctest
    +make [testcase].cpptest
    +make [testcase].multicpptest
    +
    + +

    +Some real examples of each: +

    +
    +make -s ret_by_value.clean
    +make -s ret_by_value.ctest
    +make -s bools.cpptest
    +make -s imports.multicpptest
    +
    + +

    +Advanced usage of the test-suite facilitates running tools on some of the five stages. +The make variables SWIGTOOL and RUNTOOL are used to specify a tool to respectively, invoke SWIG +and the execution of the runtime test. +You are advised to view the Examples/test-suite/common.mk file for details but for a short summary, +the classic usage is to use Valgrind for memory checking. +For example, checking for memory leaks when running the runtime test in the target language interpreter: +

    + +
    +make ret_by_value.ctest RUNTOOL="valgrind --leak-check=full"
    +
    + +

    +This will probably make more sense if you look at the output of the above as it will show the exact commands being executed. +SWIG can be analyzed for bad memory accesses using: +

    + +
    +make ret_by_value.ctest SWIGTOOL="valgrind --tool=memcheck --trace-children=yes"
    +
    + +

    35.10.13 Documentation

    @@ -3286,7 +3507,7 @@ Some topics that you'll want to be sure to address include: if available. -

    35.10.13 Prerequisites for adding a new language module to the SWIG distribution

    +

    35.10.14 Prerequisites for adding a new language module to the SWIG distribution

    @@ -3343,7 +3564,7 @@ should be added should there be an area not already covered by the existing tests.

    -

    35.10.14 Coding style guidelines

    +

    35.10.15 Coding style guidelines

    @@ -3367,11 +3588,29 @@ The generated C/C++ code should also follow this style as close as possible. How should be avoided as unlike the SWIG developers, users will never have consistent tab settings.

    -

    35.11 Typemaps

    +

    35.11 Debugging Options

    -

    35.11.1 Proxy classes

    +

    +There are various command line options which can aid debugging a SWIG interface as well as debugging the development of a language module. These are as follows: +

    +
    +-debug-classes    - Display information about the classes found in the interface
    +-debug-module <n> - Display module parse tree at stages 1-4, <n> is a csv list of stages
    +-debug-symtabs    - Display symbol tables information
    +-debug-symbols    - Display target language symbols in the symbol tables
    +-debug-csymbols   - Display C symbols in the symbol tables
    +-debug-tags       - Display information about the tags found in the interface
    +-debug-template   - Display information for debugging templates
    +-debug-top <n>    - Display entire parse tree at stages 1-4, <n> is a csv list of stages
    +-debug-typedef    - Display information about the types and typedefs in the interface
    +-debug-typemap    - Display information for debugging typemaps
    +
    + +

    +The complete list of command line options for SWIG are available by running swig -help. +

    35.12 Guide to parse tree nodes

    @@ -3781,6 +4020,13 @@ extern "X" { ... } declaration.
    +

    35.13 Further Development Information

    + + +

    +There is further documentation available on the internals of SWIG, API documentation and debugging information. +This is shipped with SWIG in the Doc/Devel directory. +

    diff --git a/Doc/Manual/Guile.html b/Doc/Manual/Guile.html index cf7e8da2c..61b5ba7d6 100644 --- a/Doc/Manual/Guile.html +++ b/Doc/Manual/Guile.html @@ -814,7 +814,7 @@ Produces the following code at the top of the generated GOOPS guile-module Module-primitive.scm (with primitive replaced with whatever is given with the -primsuffix argument. The code to load the .so library should be located in the %scheme directive, which will then be added to the scmstub file. -Swig will automatically generate the line (use-modules (Package Module-primitive)) +SWIG will automatically generate the line (use-modules (Package Module-primitive)) into the GOOPS guile-module. So if Module-primitive.scm is on the autoload path for guile, the %goops directive can be empty. Otherwise, the %goops directive should contain whatever code is needed to load the Module-primitive.scm file into guile.

    @@ -848,7 +848,7 @@ Produces the following code at the top of the generated GOOPS guile-module
  • Module Linkage: This is very similar to passive linkage with a scmstub file. -Swig will also automatically generate the line (use-modules +SWIG will also automatically generate the line (use-modules (Package Module-primitive)) into the GOOPS guile-module. Again the %goops directive should contain whatever code is needed to get that module loaded into guile.

    diff --git a/Doc/Manual/Introduction.html b/Doc/Manual/Introduction.html index 099454cf0..df8d03fdf 100644 --- a/Doc/Manual/Introduction.html +++ b/Doc/Manual/Introduction.html @@ -334,7 +334,7 @@ major features include:

    Currently, the only major C++ feature not supported is nested classes--a limitation -that will be removed in a future release. +that should be removed in a future release, but has some workarounds for the moment.

    diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index fc5646c10..7ab997a11 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -1772,7 +1772,7 @@ If declarations such as these appear, you will get a warning message like this:

    -example.i:12: Warning(515): Overloaded method spam(unsigned short) ignored.
    +example.i:12: Warning 515: Overloaded method spam(unsigned short) ignored.
     Method spam(int) at example.i:11 used.
     
    diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html index 7293f31fe..833a38393 100644 --- a/Doc/Manual/Library.html +++ b/Doc/Manual/Library.html @@ -667,7 +667,7 @@ in order for this to work.

    -char *cdata(void *ptr, int nbytes) +const char *cdata(void *ptr, size_t nbytes)

    @@ -676,7 +676,7 @@ pointer.

    -void memmove(void *ptr, char *s) +void memmove(void *ptr, const char *s)

    @@ -890,7 +890,10 @@ char *foo();

    -This will release the result. +This will release the result if the appropriate target language support is available. +SWIG provides the appropriate "newfree" typemap for char * so that the memory is released, +however, you may need to provide your own "newfree" typemap for other types. +See Object ownership and %newobject for more details.

    8.3.4 cstring.i

    diff --git a/Doc/Manual/Lua.html b/Doc/Manual/Lua.html index e66c1c7f3..b236ab9f7 100644 --- a/Doc/Manual/Lua.html +++ b/Doc/Manual/Lua.html @@ -684,8 +684,8 @@ void foo(Bar &b); If declarations such as these appear, you will get a warning message like this:

    -example.i:12: Warning(509): Overloaded spam(short) is shadowed by spam(int)
    -at example.i:11.
    +example.i:12: Warning 509: Overloaded method spam(short) effectively ignored,
    +example.i:11: Warning 509: as it is shadowed by spam(int).
     

    To fix this, you either need to ignore or rename one of the methods. For example: diff --git a/Doc/Manual/Modules.html b/Doc/Manual/Modules.html index 1b628f802..406bdeaef 100644 --- a/Doc/Manual/Modules.html +++ b/Doc/Manual/Modules.html @@ -138,7 +138,7 @@ base class's methods. Typically you will get a warning when the module name is m

    -derived_module.i:8: Warning(401): Base class 'base' ignored - unknown module name for base. Either import 
    +derived_module.i:8: Warning 401: Base class 'base' ignored - unknown module name for base. Either import 
     the appropriate module interface file or specify the name of the module in the %import directive.
     
    diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 8f74bd1de..40500dc5a 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -112,7 +112,7 @@ options are found near the end of the chapter.

    -To build a Perl5 module, run Swig using the -perl option as +To build a Perl5 module, run SWIG using the -perl option as follows :

    diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 7bf158918..b9dcb83c5 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -48,10 +48,6 @@ -

    -Caution: This chapter (and module!) is still under construction -

    -

    SWIG supports generating wrappers for PHP5. Support for PHP4 has been removed as of SWIG 1.3.37. The PHP developers are no longer making new PHP4 releases, @@ -105,7 +101,7 @@ also contain PHP5 class wrappers.

    -Swig can generate PHP extensions from C++ libraries as well when +SWIG can generate PHP extensions from C++ libraries as well when given the -c++ option. The support for C++ is discussed in more detail in section 27.2.6.

    diff --git a/Doc/Manual/Preprocessor.html b/Doc/Manual/Preprocessor.html index 5afa59243..2dd79dac5 100644 --- a/Doc/Manual/Preprocessor.html +++ b/Doc/Manual/Preprocessor.html @@ -102,8 +102,6 @@ by SWIG when it is parsing the interface:
     SWIG                            Always defined when SWIG is processing a file
     SWIGIMPORTED                    Defined when SWIG is importing a file with %import
    -SWIGMAC                         Defined when running SWIG on the Macintosh
    -SWIGWIN                         Defined when running SWIG under Windows
     SWIG_VERSION                    Hexadecimal number containing SWIG version,
                                     such as 0x010311 (corresponding to SWIG-1.3.11).
     
    diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html
    index 8b359bda9..b22a7e30e 100644
    --- a/Doc/Manual/Python.html
    +++ b/Doc/Manual/Python.html
    @@ -69,9 +69,6 @@
     
  • Simple pointers
  • Unbounded C Arrays
  • String handling -
  • Arrays -
  • String arrays -
  • STL wrappers
  • Typemaps
      @@ -1137,7 +1134,7 @@ simply represented as opaque values using an especial python container object:
       >>> print f
      -<Swig Object at _08a71808_p_FILE>
      +<Swig Object of type 'FILE *' at 0xb7d6f470>
       

      @@ -1147,7 +1144,7 @@ dereference the pointer from Python. Of course, that isn't much of a concern in

      -In older versions of Swig (1.3.22 or older), pointers were represented +In older versions of SWIG (1.3.22 or older), pointers were represented using a plain string object. If you have an old package that still requires that representation, or you just feel nostalgic, you can always retrieve it by casting the pointer object to a string: @@ -1171,7 +1168,7 @@ integer:

      However, the inverse operation is not possible, i.e., you can't build -a Swig pointer object from a raw integer value. +a SWIG pointer object from a raw integer value.

      @@ -1713,8 +1710,8 @@ If declarations such as these appear, you will get a warning message like this:

      -example.i:12: Warning(509): Overloaded spam(short) is shadowed by spam(int)
      -at example.i:11.
      +example.i:12: Warning 509: Overloaded method spam(short) effectively ignored,
      +example.i:11: Warning 509: as it is shadowed by spam(int).
       
      @@ -3854,15 +3851,6 @@ If you need to return binary data, you might use the also be used to extra binary data from arbitrary pointers.

      -

      31.7.5 Arrays

      - - -

      31.7.6 String arrays

      - - -

      31.7.7 STL wrappers

      - -

      31.8 Typemaps

      diff --git a/Doc/Manual/Ruby.html b/Doc/Manual/Ruby.html index 98fa315d0..3b1e5c45c 100644 --- a/Doc/Manual/Ruby.html +++ b/Doc/Manual/Ruby.html @@ -1559,7 +1559,7 @@ you'll see a warning message like:

      -
      example.i:5: Warning(802): Warning for Derived: Base Base2 ignored.
      Multiple inheritance is not supported in Ruby.
      +
      example.i:5: Warning 802: Warning for Derived: Base Base2 ignored.
      Multiple inheritance is not supported in Ruby.
      @@ -1810,7 +1810,11 @@ message like this:

      -
      example.i:12: Warning(509): Overloaded spam(short) is shadowed by spam(int)
      at example.i:11.
      +
      +example.i:12: Warning 509: Overloaded method spam(short) effectively ignored,
      +example.i:11: Warning 509: as it is shadowed by spam(int).
      +
      +
      @@ -7097,7 +7101,7 @@ being created.
      with Ruby objects. The following functions may prove to be useful. (These functions plus many more can be found in Programming Ruby, by David Thomas and Andrew Hunt.) 

      -

      In addition, we list equivalent functions that Swig defines, which +

      In addition, we list equivalent functions that SWIG defines, which provide a language neutral conversion (these functions are defined for each swig language supported).  If you are trying to create a swig file that will work under multiple languages, it is recommended you @@ -7123,7 +7127,7 @@ across multiple languages.

      RUBY - Swig + SWIG diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index 8705fa182..02d0ca3a4 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -330,10 +330,13 @@ currently supported:

        -
      • Non-conventional type declarations. +
      • +

        +Non-conventional type declarations. For example, SWIG does not support declarations such as the following (even though this is legal C): +

         /* Non-conventional placement of storage specifier (extern) */
        @@ -355,15 +358,19 @@ if you're feeling particularly obfuscated, you can certainly break SWIG (althoug
         

      • -
      • Running SWIG on C++ source files (what would appear in a .C or .cxx file) -is not recommended. Even though SWIG can parse C++ class declarations, -it ignores declarations that are decoupled from their -original class definition (the declarations are parsed, but a lot of warning -messages may be generated). For example: +
      • +

        +Running SWIG on C++ source files (the code in a .C, .cpp or .cxx file) is not recommended. +The usual approach is to feed SWIG header files for parsing C++ definitions and declarations. +The main reason is if SWIG parses a scoped definition or declaration (as is normal for C++ source files), +it is ignored, unless a declaration for the symbol was parsed earlier. +For example +

        -/* Not supported by SWIG */
        +/* bar not wrapped unless foo has been defined and 
        +   the declaration of bar within foo has already been parsed */
         int foo::bar(int) {
             ... whatever ...
         }
        @@ -371,9 +378,12 @@ int foo::bar(int) {
         
      • -
      • Certain advanced features of C++ such as nested classes -are not yet supported. Please see the section on using SWIG -with C++ for more information. +
      • +

        +Certain advanced features of C++ such as nested classes +are not yet fully supported. Please see the C++ Nested classes section +for more information. +

      @@ -787,6 +797,12 @@ In this case, the pointer e can change---it's only the value being pointed to that is read-only.

      +

      +Please note that for const parameters or return types used in a function, SWIG pretty much ignores +the fact that these are const, see the section on const-correctness +for more information. +

      +

      Compatibility Note: One reason for changing SWIG to handle const declarations as read-only variables is that there are @@ -2489,7 +2505,7 @@ instead of a method. To do this, you might write some code like this: // Now supply the implementation of the Vector_magnitude_get function %{ const double Vector_magnitude_get(Vector *v) { - return (const double) return sqrt(v->x*v->x+v->y*v->y+v->z*v->z); + return (const double) sqrt(v->x*v->x+v->y*v->y+v->z*v->z); } %} @@ -2502,41 +2518,53 @@ of the object.

      -A similar technique can also be used to work with problematic data members. +A similar technique can also be used to work with data members that you want to process. For example, consider this interface:

      -struct Person {
      -   char name[50];
      -   ...
      -}
      +typedef struct {
      +  char name[50];
      +  ...
      +} Person;
       

      -By default, the name attribute is read-only because SWIG does not -normally know how to modify arrays. However, you can rewrite the interface -as follows to change this: +Say you wanted to ensure name was always upper case, you can rewrite +the interface as follows to ensure this occurs whenever a name is read or written to:

      -struct Person {
      -    %extend {
      -       char *name;
      -    }
      -...
      +typedef struct {
      +  %extend {
      +    char name[50];
      +  }
      +  ...
      +} Person;
      +
      +%{
      +#include <string.h>
      +#include <ctype.h>
      +
      +void make_upper(char *name) {
      +  char *c;
      +  for (c = name; *c; ++c)
      +    *c = (char)toupper((int)*c);
       }
       
      -// Specific implementation of set/get functions
      -%{
      +/* Specific implementation of set/get functions forcing capitalization */
      +
       char *Person_name_get(Person *p) {
      -   return p->name;
      +  make_upper(p->name);
      +  return p->name;
       }
      +
       void Person_name_set(Person *p, char *val) {
      -   strncpy(p->name,val,50);
      +  strncpy(p->name,val,50);
      +  make_upper(p->name);
       }
       %}
       
      @@ -2546,7 +2574,7 @@ void Person_name_set(Person *p, char *val) { Finally, it should be stressed that even though %extend can be used to add new data members, these new members can not require the allocation of additional storage in the object (e.g., their values must -be entirely synthesized from existing attributes of the structure). +be entirely synthesized from existing attributes of the structure or obtained elsewhere).

      @@ -2629,10 +2657,16 @@ $o->{intRep}->{ivalue} = 7 # Change value of o.intRep.ivalue

  • -If you have a lot nested structure declarations, it is +If you have a lot of nested structure declarations, it is advisable to double-check them after running SWIG. Although, there is a good chance that they will work, you may have to modify the interface file in certain cases. +

    + +

    +Finally, note that nesting is handled differently in C++ mode, +see Nested classes. +

    5.5.8 Other things to note about structure wrapping

    diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index ef7487ff8..bd8a7ab5d 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -56,7 +56,7 @@
  • Smart pointers and operator->()
  • Using declarations and inheritance
  • Nested classes -
  • A brief rant about const-correctness +
  • A brief rant about const-correctness
  • Where to go for more information @@ -1616,7 +1616,7 @@ warning message like this:
    -example.i:18: Warning(401): Nothing known about base class 'Foo'. Ignored.
    +example.i:18: Warning 401: Nothing known about base class 'Foo'. Ignored.
     
    @@ -2031,7 +2031,8 @@ Therefore, when SWIG encounters this situation, it may generate a warning messag
    -example.i:4: Warning(509): Overloaded foo(long) is shadowed by foo(int) at example.i:3.
    +example.i:4: Warning 509: Overloaded method foo(long) effectively ignored,
    +example.i:3: Warning 509: as it is shadowed by foo(int).
     
    @@ -2041,7 +2042,8 @@ or for statically typed languages like Java:
    -example.i:4: Warning(516): Overloaded method foo(long) ignored. Method foo(int)
    +example.i:4: Warning 516: Overloaded method foo(long) ignored,
    +example.i:3: Warning 516: using foo(int) instead.
     at example.i:3 used.
     
    @@ -2091,7 +2093,7 @@ When wrapping an overloaded function, there is a chance that you will get an err
    -example.i:3: Warning(467): Overloaded foo(int) not supported (no type checking
    +example.i:3: Warning 467: Overloaded foo(int) not supported (no type checking
     rule for 'int').
     
    @@ -3246,22 +3248,39 @@ public:

    -SWIG should be able to handle most simple uses of partial specialization. However, it may fail -to match templates properly in more complicated cases. For example, if you have this code, +SWIG supports both template explicit specialization and partial specialization. Consider:

    -template<class T1, class T2> class Foo<T1, T2 *> { };
    +template<class T1, class T2> class Foo { };                     // (1) primary template
    +template<>                   class Foo<double *, int *> { };    // (2) explicit specialization
    +template<class T1, class T2> class Foo<T1, T2 *> { };           // (3) partial specialization
     

    -SWIG isn't able to match it properly for instantiations like Foo<int *, int *>. -This problem is not due to parsing, but due to the fact that SWIG does not currently implement all -of the C++ argument deduction rules. +SWIG is able to properly match explicit instantiations:

    +
    +
    +Foo<double *, int *>     // explicit specialization matching (2)
    +
    +
    + +

    +SWIG implements template argument deduction so that the following partial specialization examples work just like they would with a C++ compiler: +

    + +
    +
    +Foo<int *, int *>        // partial specialization matching (3)
    +Foo<int *, const int *>  // partial specialization matching (3)
    +Foo<int *, int **>       // partial specialization matching (3)
    +
    +
    +

    Member function templates are supported. The underlying principle is the same as for normal templates--SWIG can't create a wrapper unless you provide @@ -3471,7 +3490,7 @@ instead:

    In this case, the default and conversion constructors have the same -name. Hence, Swig will overload them and define an unique visible +name. Hence, SWIG will overload them and define an unique visible constructor, that will dispatch the proper call depending on the argument type.

    @@ -4678,37 +4697,50 @@ public:

    -There is limited support for nested structs and unions when wrapping C code, see Nested structures for further details. -However, there is no nested class/struct/union support when wrapping C++ code (using the -c++ commandline option). -This may be added at a future date, however, until then some of the following workarounds can be applied. +There is some support for nested structs and unions when wrapping C code, +see Nested structures for further details. +The added complexity of C++ compared to C means this approach does not work well for +C++ code (when using the -c++ command line option). +For C++, a nested class is treated much like an opaque pointer, so anything useful within the nested class, such as its +methods and variables, are not accessible from the target language. +True nested class support may be added to SWIG in the future, however, +until then some of the following workarounds can be applied to improve the situation.

    -It might be possible to use partial class information. Since -SWIG does not need the entire class specification to work, conditional -compilation can be used to comment out the problematic nested class definition, you might do this: +It might be possible to use partial class information as often you can accept that the nested class is not needed, +especially if it is not actually used in any methods you need from the target language. +Imagine you are wrapping the following Outer class which contains a nested class Inner. +The easiest thing to do is turn a blind eye to the warning that SWIG generates, or simply suppress it:

    -class Foo {
    +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::Inner;
    +
    +class Outer {
     public:
    -#ifndef SWIG
    -   class Bar {
    -   public:
    -     ...
    -   };
    -#endif
    -   Foo();
    -  ~Foo();
    -   ...
    +  class Inner {
    +    public:
    +      ...
    +  };
    +  Inner getInner();
    +  void useInner(const Inner& inner);
    +  ...
     };
     

    -The next workaround assumes you cannot modify the source code as was done above and it provides a solution for methods that use nested class types. -Imagine we are wrapping the Outer class which contains a nested class Inner: +Note that if Inner can be used as an opaque type, the default wrapping approach suffices. +For example, if the nested class does not need to be created from the target language, but can be obtained via a method +call, such as the getInner() method above, the returned value can then be passed around, such as passed into the +useInner() method. +

    + +

    +With some more effort the above situation can be improved somewhat and a nested class can be constructed and used +from the target language much like any other non-nested class. Assuming we have the Outer class in a header file:

    @@ -4721,14 +4753,18 @@ public: int var; Inner(int v = 0) : var(v) {} }; - void method(Inner inner); + Inner getInner(); + void useInner(const Inner& inner); };

    -The following interface file works around SWIG nested class limitations by redefining the nested class as a global class. -A typedef for the compiler is also required in order for the generated wrappers to compile. +The following interface file works around the nested class limitations by redefining the nested class as a global class. +A typedef for the compiler and the nestedworkaround +feature flag is also required in +order for the generated wrappers to compile. This flag simply removes all the type information from SWIG, so SWIG treats +the nested class as if it had not been parsed at all.

    @@ -4736,9 +4772,6 @@ A typedef for the compiler is also required in order for the generated wrappers // File : example.i %module example -// Suppress SWIG warning -#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_CLASS - // Redefine nested class in global scope in order for SWIG to generate // a proxy class. Only SWIG parses this definition. class Inner { @@ -4747,25 +4780,64 @@ class Inner { Inner(int v = 0) : var(v) {} }; +%nestedworkaround Outer::Inner; + %{ #include "outer.h" %} %include "outer.h" +// We've fooled SWIG into thinking that Inner is a global class, so now we need +// to trick the C++ compiler into understanding this apparent global type. %{ -// SWIG thinks that Inner is a global class, so we need to trick the C++ -// compiler into understanding this so called global type. typedef Outer::Inner Inner; %} -

    -The downside to this approach is having to maintain two definitions of Inner, the real one and the one in the interface file that SWIG parses. +The downside to this approach is a more complex interface file and having to maintain two definitions of Inner, +the real one and the one in the interface file that SWIG parses. +However, the upside is that all the methods/variables in the nested class are available from the target language +as a proxy class is generated instead of treating the nested class as an opaque type. +The proxy class can be constructed from the target language and passed into any methods accepting the nested class. +Also note that the original header file is parsed unmodified.

    -

    6.27 A brief rant about const-correctness

    +

    +Finally, conditional compilation can be used as a workaround to comment out nested class definitions in the actual headers, +assuming you are able to modify them. +

    + +
    +
    +// File outer.h
    +class Outer {
    +public:
    +#ifndef SWIG
    +  class Inner {
    +    public:
    +      ...
    +  };
    +#endif
    +  ...
    +};
    +
    +
    + +

    +This workaround used to be common when SWIG could not deal with nested classes particulary well. +This should just be a last resort for unusual corner cases now as SWIG can parse nested classes and even handle nested template classes fairly well. +

    + +

    +Compatibility Note: SWIG-1.3.40 and earlier versions did not have the nestedworkaround feature +and the generated code resulting from parsing nested classes did not always compile. +Nested class warnings could also not be suppressed using %warnfilter. +

    + + +

    6.27 A brief rant about const-correctness

    diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html index 789efc129..b98661c0d 100644 --- a/Doc/Manual/Sections.html +++ b/Doc/Manual/Sections.html @@ -6,7 +6,7 @@

    SWIG-1.3 Development Documentation

    -Last update : SWIG-1.3.40 (in progress) +Last update : SWIG-1.3.41 (in progress)

    Sections

    diff --git a/Doc/Manual/Tcl.html b/Doc/Manual/Tcl.html index 8b8c74dc0..b37df2853 100644 --- a/Doc/Manual/Tcl.html +++ b/Doc/Manual/Tcl.html @@ -1502,8 +1502,8 @@ If declarations such as these appear, you will get a warning message like this:
    -example.i:12: Warning(509): Overloaded spam(short) is shadowed by spam(int)
    -at example.i:11.
    +example.i:12: Warning 509: Overloaded method spam(short) effectively ignored,
    +example.i:11: Warning 509: as it is shadowed by spam(int).
     
    diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index 226b4ef3e..7fe932828 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -31,10 +31,11 @@
  • Pattern matching rules
  • Code generation rules -
  • Typemaps for multiple languages +
  • Typemaps for multiple target languages
  • Optimal code generation when returning by value
  • Multi-argument typemaps
  • The run-time type checker @@ -88,10 +89,6 @@ -

    -Disclaimer: This chapter is under construction! -

    -

    10.1 Introduction

    @@ -230,14 +227,17 @@ At first glance, this code will look a little confusing. However, there is really not much to it. The first typemap (the "in" typemap) is used to convert a value from the target language to C. The second typemap (the "out" typemap) is used to convert in the other -direction. The content of each typemap is a small fragment of C code -that is inserted directly into the SWIG generated wrapper functions. Within -this code, a number of special variables prefixed with a $ are expanded. These are -really just placeholders for C variables that are generated in the course +direction. The content of each typemap is a small fragment of code +that is inserted directly into the SWIG generated wrapper functions. +The code is usually C or C++ code which will be generated into the C/C++ wrapper functions. +Note that this isn't always the case as some target language modules allow target language +code within the typemaps which gets generated into target language specific files. +Within this code, a number of special variables prefixed with a $ are expanded. These are +really just placeholders for C/C++ variables that are generated in the course of creating the wrapper function. In this case, $input refers to an -input object that needs to be converted to C and $result +input object that needs to be converted to C/C++ and $result refers to an object that is going to be returned by a wrapper -function. $1 refers to a C variable that has the same type as +function. $1 refers to a C/C++ variable that has the same type as specified in the typemap declaration (an int in this example).

    @@ -681,8 +681,9 @@ these methods is described later.

    -modifiers is an optional comma separated list of name="value" values. These -are sometimes to attach extra information to a typemap and is often target-language dependent. +modifiers is an optional comma separated list of name="value" values. +These are sometimes to attach extra information to a typemap and is often target-language dependent. +They are also known as typemap attributes.

    @@ -1091,7 +1092,7 @@ void F(int x[1000]); // int [ANY] rule (typemap 5) -

    10.3.2 Typedef reductions

    +

    10.3.2 Typedef reductions

    @@ -1246,6 +1247,26 @@ is rather esoteric--there's little practical reason to write a typemap quite lik to confuse your coworkers even more.

    +

    +As a point of clarification, it is worth emphasizing that typedef matching is a typedef reduction process only, that is, SWIG does not search for every single possible typedef. +Given a type in a declaration, it will only reduce the type, it won't build it up looking for typedefs. +For example, given the type Struct, the typemap below will not be used for the aStruct parameter, +because Struct is fully reduced: +

    + +
    +
    +struct Struct {...};
    +typedef Struct StructTypedef;
    +
    +%typemap(in) StructTypedef { 
    +  ...
    +}
    +
    +void go(Struct aStruct);
    +
    +
    +

    10.3.3 Default typemaps

    @@ -1383,7 +1404,7 @@ Expect to see them being used more and more within the various libraries in late

    -

    10.3.5 Multi-arguments typemaps

    +

    10.3.5 Multi-arguments typemaps

    @@ -1413,6 +1434,205 @@ but all subsequent arguments must match exactly.

    +

    10.3.6 Debugging typemap pattern matching

    + + +

    +There are two useful debug command line options available for debugging typemaps, -debug-tmsearch and -debug-tmused. +

    + +

    +The -debug-tmsearch option is a verbose option for debugging typemap searches. +This can be very useful for watching the pattern matching process in action and for debugging which typemaps are used. +The option displays all the typemaps and types that are looked for until a successful pattern match is made. +As the display includes searches for each and every type needed for wrapping, the amount of information displayed can be large. +Normally you would manually search through the displayed information for the particular type that you are interested in. +

    + +

    +For example, consider some of the code used in the Typedef reductions section already covered: +

    + +
    +
    +typedef int Integer;
    +typedef Integer Row4[4];
    +void foo(Row4 rows[10]);
    +
    +
    + +

    +A sample of the debugging output is shown below for the "in" typemap: +

    + +
    +
    +swig -perl -debug-tmsearch example.i
    +...
    +example.h:3: Searching for a suitable 'in' typemap for: Row4 rows[10]
    +  Looking for: Row4 rows[10]
    +  Looking for: Row4 [10]
    +  Looking for: Row4 rows[ANY]
    +  Looking for: Row4 [ANY]
    +  Looking for: Integer rows[10][4]
    +  Looking for: Integer [10][4]
    +  Looking for: Integer rows[ANY][ANY]
    +  Looking for: Integer [ANY][ANY]
    +  Looking for: int rows[10][4]
    +  Looking for: int [10][4]
    +  Looking for: int rows[ANY][ANY]
    +  Looking for: int [ANY][ANY]
    +  Looking for: SWIGTYPE rows[ANY][ANY]
    +  Looking for: SWIGTYPE [ANY][ANY]
    +  Looking for: SWIGTYPE rows[ANY][]
    +  Looking for: SWIGTYPE [ANY][]
    +  Looking for: SWIGTYPE *rows[ANY]
    +  Looking for: SWIGTYPE *[ANY]
    +  Looking for: SWIGTYPE rows[ANY]
    +  Looking for: SWIGTYPE [ANY]
    +  Looking for: SWIGTYPE rows[]
    +  Looking for: SWIGTYPE []
    +  Using: %typemap(in) SWIGTYPE []
    +...
    +
    +
    + +

    +showing that the best default match supplied by SWIG is the SWIGTYPE [] typemap. +As the example shows, the successful match displays just the typemap method name and type in this format: %typemap(method) type. +This information might meet your debugging needs, however, you might want to analyze further. +If you next invoke SWIG with the -E option to display the preprocessed output, and search for this particular typemap, +you'll find the full typemap contents (example shown below for Python): +

    + +
    +
    +%typemap(in, noblock=1) SWIGTYPE [] (void *argp = 0, int res = 0) {
    +  res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown |  0 );
    +  if (!SWIG_IsOK(res)) { 
    +    SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "$type""'"); 
    +  } 
    +  $1 = ($ltype)(argp);
    +}
    +
    +
    + +

    +The generated code for the foo wrapper will then contain the snippets of the typemap with the special variables expanded. +The rest of this chapter will need reading though to fully understand all of this, however, the relevant parts of the generated code for the above typemap can be seen below: +

    + +
    +
    +SWIGINTERN PyObject *_wrap_foo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
    +...
    +  void *argp1 = 0 ;
    +  int res1 = 0 ;
    +...
    +  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_a_4__int, 0 |  0 );
    +  if (!SWIG_IsOK(res1)) {
    +    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "foo" "', argument " "1"" of type '" "int [10][4]""'"); 
    +  } 
    +  arg1 = (int (*)[4])(argp1);
    +...
    +}
    +
    +
    + +

    +Searches for multi-argument typemaps are not mentioned unless a matching multi-argument typemap does actually exist. +For example, the output for the code in the previous section is as follows: +

    + +
    +
    +...
    +example.h:39: Searching for a suitable 'in' typemap for: char *buffer
    +  Looking for: char *buffer
    +  Multi-argument typemap found...
    +  Using: %typemap(in) (char *buffer,int len)
    +...
    +
    +
    + +

    +The second option for debugging is -debug-tmused and this displays the typemaps used. +This option is a less verbose version of the -debug-tmsearch option as it only displays each successfully found typemap on a separate single line. +The output displays the type, and name if present, the typemap method in brackets and then the actual typemap used. +Below is the output for the example code at the start of this section on debugging. +

    + +
    +
    +$ swig -perl -debug-tmused example.i
    +example.h:3: Typemap for Row4 rows[10] (in) : %typemap(in) SWIGTYPE []
    +example.h:3: Typemap for Row4 rows[10] (typecheck) : %typemap(typecheck) SWIGTYPE *
    +example.h:3: Typemap for Row4 rows[10] (freearg) : %typemap(freearg) SWIGTYPE []
    +example.h:3: Typemap for void foo (out) : %typemap(out) void
    +
    +
    + +

    +Now, consider the following interface file: +

    + +
    +
    +%module example
    +
    +%{
    +void set_value(const char* val) {}
    +%}
    +
    +%typemap(check) char *NON_NULL {
    +  if (!$1) {
    +    /* ... error handling ... */
    +  }
    +}
    +
    +%apply SWIGTYPE * { const char* val, const char* another_value } // use default pointer handling instead of strings
    +
    +%typemap(check) const char* val = char* NON_NULL;
    +
    +%typemap(arginit, noblock=1) const char* val {
    +   $1 = "";
    +}
    +
    +void set_value(const char* val);
    +
    +
    +
    + +

    +and the output debug: +

    + +
    +
    +swig -perl5 -debug-tmused example.i
    +example.i:21: Typemap for char const *val (arginit) : %typemap(arginit) char const *val
    +example.i:21: Typemap for char const *val (in) : %apply SWIGTYPE * { char const *val }
    +example.i:21: Typemap for char const *val (typecheck) : %apply SWIGTYPE * { char const *val }
    +example.i:21: Typemap for char const *val (check) : %typemap(check) char const *val = char *NON_NULL
    +example.i:21: Typemap for char const *val (freearg) : %apply SWIGTYPE * { char const *val }
    +example.i:21: Typemap for void set_value (out) : %typemap(out) void
    +
    +
    + +

    +The following observations about what is displayed can be noted (the same applies for -debug-tmsearch): +

  • +The relevant typemap is shown, but for typemap copying, the appropriate %typemap or %apply is displayed, for example, the "check" and "in" typemaps. +
  • +
  • +The typemap modifiers are not shown, eg the noblock=1 modifier in the "arginit" typemap. +
  • +
  • +The exact %apply statement might look different to what is in the actual code. For example, the const char* another_value is not shown as it is not relevant here. +Also the types may be displayed slightly differently - char const * and not const char*. +
  • +

    +

    10.4 Code generation rules

    @@ -2686,12 +2906,12 @@ rather than blindly passing values to the underlying C/C++ program.

    Note: A more advanced constraint checking system is in development. Stay tuned.

    -

    10.7 Typemaps for multiple languages

    +

    10.7 Typemaps for multiple target languages

    The code within typemaps is usually language dependent, -however, many languages support the same typemaps. +however, many target languages support the same typemaps. In order to distinguish typemaps across different languages, the preprocessor should be used. For example, the "in" typemap for Perl and Ruby could be written as:

    @@ -2873,8 +3093,8 @@ SWIG can detect when the "optimal" attribute cannot be used and will ignore it a
    -example.i:28: Warning(474): Method XX::create() usage of the optimal attribute in the out 
    -typemap at example.i:14 ignored as the following cannot be used to generate optimal code: 
    +example.i:28: Warning 474: Method XX::create() usage of the optimal attribute ignored
    +example.i:14: Warning 474: in the out typemap as the following cannot be used to generate optimal code: 
     try {
       result = XX::create();
     } catch(const std::exception &e) {
    @@ -2895,8 +3115,8 @@ In fact SWIG attempts to detect this and will issue a warning something like:
     
     
    -example.i:21: Warning(475): Multiple calls to XX::create() might be generated due to 
    -optimal attribute usage in the out typemap at example.i:7.
    +example.i:21: Warning 475: Multiple calls to XX::create() might be generated due to optimal attribute usage in
    +example.i:7: Warning 475: the out typemap.
     
    @@ -3201,7 +3421,7 @@ language modules.

    The run-time type checker is used by many, but not all, of SWIG's supported target languages. The run-time type checker features -are not required and are thus not used for strongly typed languages such as Java and C#. +are not required and are thus not used for statically typed languages such as Java and C#. The scripting and scheme based languages rely on it and it forms a critical part of SWIG's operation for these languages.

    @@ -4060,6 +4280,7 @@ numerous examples. You should look at these files to get a feel for how to define typemaps of your own. Some of the language modules support additional typemaps and further information is available in the individual chapters for each target language. +There you may also find more hands-on practical examples.

    diff --git a/Doc/Manual/Varargs.html b/Doc/Manual/Varargs.html index f40a1ff1f..fb34a3ad9 100644 --- a/Doc/Manual/Varargs.html +++ b/Doc/Manual/Varargs.html @@ -270,21 +270,37 @@ traceprintf(arg1, NULL);

    Arguably, this approach seems to defeat the whole point of variable length arguments. However, -this actually provides enough support for many simple kinds of varargs functions to still be useful. For -instance, you could make function calls like this (in Python): +this actually provides enough support for many simple kinds of varargs functions to still be useful, however it does come with a caveat. +For instance, you could make function calls like this (in Python):

     >>> traceprintf("Hello World")
     >>> traceprintf("Hello %s. Your number is %d\n" % (name, num))
    +>>> traceprintf("Your result is 90%%.")
     

    Notice how string formatting is being done in Python instead of C. +The caveat is the strings passed must be safe to use in C though. +For example if name was to contain a "%" it should be double escaped in order to avoid unpredictable +behaviour:

    +
    +
    +>>> traceprintf("Your result is 90%.\n")  # unpredictable behaviour
    +>>> traceprintf("Your result is 90%%.\n") # good
    +
    +
    + +

    +Read on for further solutions. +

    + +

    13.4 Argument replacement using %varargs

    diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index 95af1ec6b..5409248c9 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -44,8 +44,8 @@ During compilation, SWIG may generate a variety of warning messages. For exampl
    -example.i:16: Warning(501): Overloaded declaration ignored.  bar(double)
    -example.i:15: Warning(501): Previous declaration is bar(int)
    +example.i:16: Warning 501: Overloaded declaration ignored.  bar(double)
    +example.i:15: Warning 501: Previous declaration is bar(int)
     
    @@ -344,7 +344,7 @@ These can be overridden using command line options, for example: $ swig -python -Fstandard example.i example.i:4: Syntax error in input. $ swig -python -Fmicrosoft example.i -example.i(4): Syntax error in input. +example.i(4) : Syntax error in input.

    14.9 Warning number reference

    @@ -399,18 +399,20 @@ example.i(4): Syntax error in input.
  • 308. Namespace alias 'name' not allowed here. Assuming 'name'
  • 309. [private | protected] inheritance ignored.
  • 310. Template 'name' was already wrapped as 'name' (ignored) -
  • 311. Template partial specialization not supported. -
  • 312. Nested classes not currently supported (ignored). +
  • 312. Unnamed nested class not currently supported (ignored).
  • 313. Unrecognized extern type "name" (ignored).
  • 314. 'identifier' is a lang keyword.
  • 315. Nothing known about 'identifier'.
  • 316. Repeated %module directive.
  • 317. Specialization of non-template 'name'. -
  • 318. Instantiation of template name is ambiguous. Using templ at file:line +
  • 318. Instantiation of template 'name' is ambiguous, instantiation templ used, instantiation templ ignored.
  • 319. No access specifier given for base class name (ignored).
  • 320. Explicit template instantiation ignored.
  • 321. identifier conflicts with a built-in name.
  • 322. Redundant redeclaration of 'name'. +
  • 323. Recursive scope inheritance of 'name'. +
  • 324. Named nested template instantiations not supported. Processing as if no name was given to %template(). +
  • 325. Nested class not currently supported (name ignored).
  • 350. operator new ignored.
  • 351. operator delete ignored.
  • 352. operator+ ignored. @@ -482,8 +484,8 @@ example.i(4): Syntax error in input.
  • 469. No or improper directorin typemap defined for type
  • 470. Thread/reentrant unsafe wrapping, consider returning by value instead.
  • 471. Unable to use return type type in director method -
  • 474. Method method usage of the optimal attribute in the out typemap at file:line ignored as the following cannot be used to generate optimal code: code -
  • 475. Multiple calls to method might be generated due to optimal attribute usage in the out typemap at file:line. +
  • 474. Method method usage of the optimal attribute ignored in the out typemap as the following cannot be used to generate optimal code: code +
  • 475. Multiple calls to method might be generated due to optimal attribute usage in the out typemap. @@ -492,22 +494,22 @@ example.i(4): Syntax error in input.
      -
    • 501. Overloaded declaration ignored. decl -
    • 502. Overloaded constructor ignored. decl +
    • 501. Overloaded declaration ignored. decl. Previous declaration is decl. +
    • 502. Overloaded constructor ignored. decl. Previous declaration is decl.
    • 503. Can't wrap 'identifier' unless renamed to a valid identifier.
    • 504. Function name must have a return type.
    • 505. Variable length arguments discarded.
    • 506. Can't wrap varargs with keyword arguments enabled.
    • 507. Adding native function name not supported (ignored). -
    • 508. Declaration of 'name' shadows declaration accessible via operator->() at file:line. -
    • 509. Overloaded declaration is shadowed by declaration at file:line. +
    • 508. Declaration of 'name' shadows declaration accessible via operator->(), previous declaration of'declaration'. +
    • 509. Overloaded method declaration effectively ignored, as it is shadowed by declaration.
    • 510. Friend function 'name' ignored.
    • 511. Can't use keyword arguments with overloaded functions. -
    • 512. Overloaded declaration const ignored. Non-const method at file:line used. +
    • 512. Overloaded method declaration ignored, using non-const method declaration instead.
    • 513. Can't generate wrappers for unnamed struct/class.
    • 514.
    • 515. -
    • 516. Overloaded method declaration ignored. Method declaration at file:line used. +
    • 516. Overloaded method declaration ignored, using declaration instead.
    • 517.
    • 518. Portability warning: File file1 will be overwritten by file2 on case insensitive filesystems such as Windows' FAT32 and NTFS unless the class/module name is renamed.
    • 519. %template() contains no name. Template method ignored: declaration diff --git a/Examples/Makefile.in b/Examples/Makefile.in index af86ddf1a..aa37eef56 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -1124,11 +1124,11 @@ RRSRC = $(INTERFACE:.i=.R) r: $(SRCS) $(SWIG) -r $(SWIGOPT) $(INTERFACEPATH) - +( PKG_LIBS="$(SRCS)" PKG_CPPFLAGS="$(INCLUDES)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(ISRCS) ) + +( PKG_LIBS="$(SRCS)" PKG_CPPFLAGS="$(INCLUDES)" $(COMPILETOOL) $(R) CMD SHLIB -fPIC -o $(LIBPREFIX)$(TARGET)$(SO) $(ISRCS) ) r_cpp: $(CXXSRCS) $(SWIG) -c++ -r $(SWIGOPT) -o $(RCXXSRCS) $(INTERFACEPATH) - +( PKG_LIBS="$(CXXSRCS)" PKG_CPPFLAGS="$(INCLUDES)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(RCXXSRCS) ) + +( PKG_LIBS="$(CXXSRCS)" PKG_CPPFLAGS="$(INCLUDES)" $(COMPILETOOL) $(R) CMD SHLIB -fPIC -o $(LIBPREFIX)$(TARGET)$(SO) $(RCXXSRCS) ) r_clean: rm -f *_wrap* *~ .~* diff --git a/Examples/java/pointer/index.html b/Examples/java/pointer/index.html index e20fe3328..5c93d4d58 100644 --- a/Examples/java/pointer/index.html +++ b/Examples/java/pointer/index.html @@ -143,7 +143,7 @@ extraction. diff --git a/Examples/perl5/pointer/index.html b/Examples/perl5/pointer/index.html index 6f9fd397d..94467bc36 100644 --- a/Examples/perl5/pointer/index.html +++ b/Examples/perl5/pointer/index.html @@ -144,7 +144,7 @@ extraction. diff --git a/Examples/php/cpointer/runme.php b/Examples/php/cpointer/runme.php index f5ef08a3c..48f0ad631 100644 --- a/Examples/php/cpointer/runme.php +++ b/Examples/php/cpointer/runme.php @@ -22,7 +22,7 @@ # Now get the result $r = intp_value($c); - print " 38 + 42 = $r\n"; + print " 37 + 42 = $r\n"; # Clean up the pointers delete_intp($a); diff --git a/Examples/python/class/example.i b/Examples/python/class/example.i index 75700b305..aa28dde80 100644 --- a/Examples/python/class/example.i +++ b/Examples/python/class/example.i @@ -1,10 +1,4 @@ /* File : example.i */ %module example -%{ -#include "example.h" -%} - -/* Let's just grab the original header file here */ -%include "example.h" - +int printf(const char *fmt, ...); diff --git a/Examples/python/class/runme.py b/Examples/python/class/runme.py index f1272ae81..54543be67 100644 --- a/Examples/python/class/runme.py +++ b/Examples/python/class/runme.py @@ -1,51 +1,10 @@ -# file: runme.py -# This file illustrates the proxy class C++ interface generated -# by SWIG. +from example import * -import example - -# ----- Object creation ----- - -print "Creating some objects:" -c = example.Circle(10) -print " Created circle", c -s = example.Square(10) -print " Created square", s - -# ----- Access a static member ----- - -print "\nA total of", example.cvar.Shape_nshapes,"shapes were created" - -# ----- Member data access ----- - -# Set the location of the object - -c.x = 20 -c.y = 30 - -s.x = -10 -s.y = 5 - -print "\nHere is their current position:" -print " Circle = (%f, %f)" % (c.x,c.y) -print " Square = (%f, %f)" % (s.x,s.y) - -# ----- Call some methods ----- - -print "\nHere are some properties of the shapes:" -for o in [c,s]: - print " ", o - print " area = ", o.area() - print " perimeter = ", o.perimeter() - -print "\nGuess I'll clean up now" - -# Note: this invokes the virtual destructor -del c -del s - -s = 3 -print example.cvar.Shape_nshapes,"shapes remain" -print "Goodbye" +printf("hello\n") +name = "%shoot" +num = 22 +printf("Hello %s. Your number is %d\n" % (name, num)) +print("hello there %s." % name); +printf("Your result is 90%.\n") diff --git a/Examples/python/pointer/index.html b/Examples/python/pointer/index.html index ceef30566..b99c8fe4c 100644 --- a/Examples/python/pointer/index.html +++ b/Examples/python/pointer/index.html @@ -144,7 +144,7 @@ extraction. diff --git a/Examples/ruby/pointer/index.html b/Examples/ruby/pointer/index.html index 2b9c40b35..c9d5b9c32 100644 --- a/Examples/ruby/pointer/index.html +++ b/Examples/ruby/pointer/index.html @@ -144,7 +144,7 @@ extraction. diff --git a/Examples/tcl/pointer/index.html b/Examples/tcl/pointer/index.html index 874088a72..407380240 100644 --- a/Examples/tcl/pointer/index.html +++ b/Examples/tcl/pointer/index.html @@ -144,7 +144,7 @@ extraction. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 492378b16..203ea3e72 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -28,12 +28,14 @@ # The 'clean' target cleans up. # # Note that the RUNTOOL, COMPILETOOL and SWIGTOOL variables can be used -# for # invoking tools for the runtime tests and target language +# for invoking tools for the runtime tests and target language # compiler (eg javac) respectively. For example, valgrind can be used # for memory checking of the runtime tests using: -# make RUNTOOL="valgrind --leak-check-full" +# make RUNTOOL="valgrind --leak-check=full" # and valgrind can be used when invoking SWIG using: -# make SWIGTOOL="valgrind --tool=memcheck" +# make SWIGTOOL="valgrind --tool=memcheck --trace-children=yes" +# Note: trace-children needed because of preinst-swig shell wrapper +# to the swig executable. # # The variables below can be overridden after including this makefile ####################################################################### @@ -78,8 +80,6 @@ CPP_TEST_BROKEN += \ exception_partial_info \ extend_variable \ li_std_vector_ptr \ - namespace_union \ - nested_structs \ overload_complicated \ template_default_pointer \ template_expr @@ -189,6 +189,7 @@ CPP_TEST_CASES += \ extend_placement \ extend_template \ extend_template_ns \ + extern_c \ extern_namespace \ extern_throws \ features \ @@ -238,9 +239,12 @@ CPP_TEST_CASES += \ namespace_template \ namespace_typedef_class \ namespace_typemap \ + namespace_union \ namespace_virtual_method \ naturalvar \ + nested_class \ nested_comment \ + nested_workaround \ newobject1 \ null_pointer \ operator_overload \ @@ -255,6 +259,7 @@ CPP_TEST_CASES += \ overload_template \ overload_template_fast \ pointer_reference \ + preproc_constants \ primitive_ref \ private_assign \ protected_rename \ @@ -297,6 +302,7 @@ CPP_TEST_CASES += \ static_array_member \ static_const_member \ static_const_member_2 \ + struct_initialization_cpp \ struct_value \ template \ template_arg_replace \ @@ -327,6 +333,8 @@ CPP_TEST_CASES += \ template_inherit_abstract \ template_int_const \ template_methods \ + template_nested \ + template_nested_typemaps \ template_ns \ template_ns2 \ template_ns3 \ @@ -336,6 +344,8 @@ CPP_TEST_CASES += \ template_ns_inherit \ template_ns_scope \ template_partial_arg \ + template_partial_specialization \ + template_partial_specialization_typedef \ template_qualifier \ template_qualifier \ template_ref_type \ @@ -409,6 +419,7 @@ CPP_STD_TEST_CASES += \ li_std_combinations \ li_std_deque \ li_std_except \ + li_std_map \ li_std_pair \ li_std_string \ li_std_vector \ @@ -430,6 +441,7 @@ C_TEST_CASES += \ arrays \ char_constant \ const_const \ + constant_expr \ empty \ enums \ extern_declaration \ @@ -447,17 +459,21 @@ C_TEST_CASES += \ li_cpointer \ li_math \ long_long \ + memberin_extend_c \ name \ nested \ + nested_structs \ newobject2 \ overload_extend \ overload_extendc \ preproc \ + preproc_constants_c \ ret_by_value \ simple_array \ sizeof_pointer \ sneaky1 \ struct_rename \ + struct_initialization \ typedef_struct \ typemap_subst \ union_parameter \ diff --git a/Examples/test-suite/constant_expr.i b/Examples/test-suite/constant_expr.i new file mode 100644 index 000000000..47db2d026 --- /dev/null +++ b/Examples/test-suite/constant_expr.i @@ -0,0 +1,11 @@ +%module constant_expr; +/* Tests of constant expressions. */ + +%inline %{ + +/* % didn't work in SWIG 1.3.40 and earlier. */ +const int X = 123%7; +#define FOO 12 % 6 +double d_array[12 % 6]; + +%} diff --git a/Examples/test-suite/cpp_broken.i b/Examples/test-suite/cpp_broken.i index fe109ea43..84d6122e5 100644 --- a/Examples/test-suite/cpp_broken.i +++ b/Examples/test-suite/cpp_broken.i @@ -1,36 +1,6 @@ %module cpp_broken -// bug #1060789 -%inline %{ -#define MASK(shift, size) (((1 << (size)) - 1) << (shift)) -#define SOME_MASK_DEF (80*MASK(8, 10)) -%} - -// bug #1060079 -%inline %{ -#define FIELD(name, width) unsigned int name:width -#define SOME_CONST 2 -#define NEXT_CONST (2 * SOME_CONST) - -typedef struct { -FIELD(a, SOME_CONST); -FIELD(b, NEXT_CONST); -} MyStruct_t; -%} - -%{ -#ifdef max -#undef max -#endif -%} - -// bug #994301 -%inline %{ -#define max(a,b) ((a) > (b) ? (a) : (b)) -%} - - // bug #940318 %inline %{ typedef enum { @@ -40,36 +10,3 @@ eZero = 0 %} -// bug #754443 - -%inline %{ -#define MAG_STYLE_BORDER_OFFS 0 -#define MAG_STYLE_BORDER_BITS 3 -#define MAG_STYLE_BORDER_MASK (((1UL< vecStr(std::vector v) { %inline %{ int *makeIntPtr(int v) { return new int(v); } + const short *makeConstShortPtr(int v) { return new short(v); } double *makeDoublePtr(double v) { return new double(v); } int extractInt(int *p) { return *p; } + short extractConstShort(const short *p) { return *p; } %} %template(pyvector) std::vector; namespace std { - %template(ConstShortVector) vector; -// %template(ConstIntVector) vector; // interferes with vector... see new testcase li_std_vector_ptr + %template(ConstShortPtrVector) vector; } %inline %{ diff --git a/Examples/test-suite/li_std_vector_ptr.i b/Examples/test-suite/li_std_vector_ptr.i index 688cbdd54..292c9d700 100644 --- a/Examples/test-suite/li_std_vector_ptr.i +++ b/Examples/test-suite/li_std_vector_ptr.i @@ -1,3 +1,4 @@ +// Bug 2359417 %module li_std_vector_ptr %include "std_vector.i" diff --git a/Examples/test-suite/lua/overload_template_fast_runme.lua b/Examples/test-suite/lua/overload_template_fast_runme.lua index 97078f34d..6663cb0b5 100644 --- a/Examples/test-suite/lua/overload_template_fast_runme.lua +++ b/Examples/test-suite/lua/overload_template_fast_runme.lua @@ -2,12 +2,12 @@ require("import") -- the import fn import("overload_template_fast") -- import code for k,v in pairs(overload_template_fast) do _G[k]=v end -- move to global --- lua has only one numeric type, so max(int,int) and max(double,double) are the same +-- lua has only one numeric type, so maximum(int,int) and maximum(double,double) are the same -- whichever one was wrapper first will be used (which is int) f = foo() -a = max(3,4) +a = maximum(3,4) -- mix 1 assert(mix1("hi") == 101) diff --git a/Examples/test-suite/memberin_extend.i b/Examples/test-suite/memberin_extend.i index f20617b66..c6eb10526 100644 --- a/Examples/test-suite/memberin_extend.i +++ b/Examples/test-suite/memberin_extend.i @@ -1,6 +1,6 @@ %module memberin_extend -// Tests memberin typemap. The default char * memberin typemap will be used. +// Tests memberin typemap is not used for %extend. // The test extends the struct with a pseudo member variable %inline %{ @@ -12,8 +12,19 @@ struct ExtendMe { %{ #include std::map ExtendMeStringMap; -#define ExtendMe_thing_set(self_, val_) ExtendMeStringMap[self_] -#define ExtendMe_thing_get(self_) ExtendMeStringMap[self_] +void ExtendMe_thing_set(ExtendMe *self, const char *val) { + char *old_val = ExtendMeStringMap[self]; + delete [] old_val; + if (val) { + ExtendMeStringMap[self] = new char[strlen(val)+1]; + strcpy(ExtendMeStringMap[self], val); + } else { + ExtendMeStringMap[self] = 0; + } +} +char * ExtendMe_thing_get(ExtendMe *self) { + return ExtendMeStringMap[self]; +} %} %extend ExtendMe { diff --git a/Examples/test-suite/memberin_extend_c.i b/Examples/test-suite/memberin_extend_c.i new file mode 100644 index 000000000..0599e65a0 --- /dev/null +++ b/Examples/test-suite/memberin_extend_c.i @@ -0,0 +1,38 @@ +%module memberin_extend_c + +/* Example from the Manual, section 5.5.6: "Adding member functions to C structures" */ + +%{ +typedef struct { + char name[50]; +} Person; +%} + +typedef struct { + %extend { + char name[50]; + } +} Person; + +%{ +#include +#include + +void make_upper(char *name) { + char *c; + for (c = name; *c; ++c) + *c = (char)toupper((int)*c); +} + +/* Specific implementation of set/get functions forcing capitalization */ + +char *Person_name_get(Person *p) { + make_upper(p->name); + return p->name; +} + +void Person_name_set(Person *p, char *val) { + strncpy(p->name,val,50); + make_upper(p->name); +} +%} diff --git a/Examples/test-suite/namespace_class.i b/Examples/test-suite/namespace_class.i index 5e9545ce6..7dc9139cd 100644 --- a/Examples/test-suite/namespace_class.i +++ b/Examples/test-suite/namespace_class.i @@ -1,5 +1,7 @@ %module namespace_class +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Ala::Ola; + %inline %{ template void foobar(T t) {} namespace test { @@ -210,7 +212,6 @@ namespace a %} -#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_CLASS // %copyctor doesn't work with nested class workaround %nocopyctor; diff --git a/Examples/test-suite/namespace_union.i b/Examples/test-suite/namespace_union.i index edade9640..85885f399 100644 --- a/Examples/test-suite/namespace_union.i +++ b/Examples/test-suite/namespace_union.i @@ -1,4 +1,7 @@ %module namespace_union + +#pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS + %inline %{ namespace SpatialIndex { diff --git a/Examples/test-suite/nested.i b/Examples/test-suite/nested.i index 0b93be46a..004cb4814 100644 --- a/Examples/test-suite/nested.i +++ b/Examples/test-suite/nested.i @@ -12,6 +12,27 @@ struct TestStruct { int a; }; +struct OuterStructNamed { + struct InnerStructNamed { + double dd; + } inner_struct_named; + union InnerUnionNamed { + double ee; + int ff; + } inner_union_named; +}; + +struct OuterStructUnnamed { + struct { + double xx; + } inner_struct_unnamed; + union { + double yy; + int zz; + } inner_union_unnamed; +}; + + typedef struct OuterStruct { union { diff --git a/Examples/test-suite/nested_class.i b/Examples/test-suite/nested_class.i new file mode 100644 index 000000000..71d91f022 --- /dev/null +++ b/Examples/test-suite/nested_class.i @@ -0,0 +1,206 @@ +%module nested_class + +#pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct1; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass1; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion1; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass2; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct2; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion2; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass4Typedef; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct4Typedef; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion4Typedef; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass5; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct5; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion5; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultiple; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultipleDerived; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultipleAnonTypedef1; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultipleNamedTypedef; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerSameName; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer2::IgnoreMe; + +%inline %{ +struct Outer { + typedef int Integer; + /////////////////////////////////////////// + struct InnerStruct1 { + Integer x; + }; + + class InnerClass1 { + public: + Integer x; + }; + + union InnerUnion1 { + Integer x; + double y; + }; + + /////////////////////////////////////////// + class { + public: + Integer a; + }; + + struct { + Integer b; + }; + + union { + Integer c; + double d; + }; + + /////////////////////////////////////////// + class InnerClass2 { + public: + Integer x; + } InnerClass2Instance; + + struct InnerStruct2 { + Integer x; + } InnerStruct2Instance; + + union InnerUnion2 { + Integer x; + double y; + } InnerUnion2Instance; + + /////////////////////////////////////////// + class { + public: + Integer x; + } InnerClass3Instance; + + struct { + Integer x; + } InnerStruct3Instance; + + union { + Integer x; + double y; + } InnerUnion3Instance; + + /////////////////////////////////////////// + typedef class { + public: + Integer x; + } InnerClass4Typedef; + + typedef struct { + Integer x; + } InnerStruct4Typedef; + + typedef union { + Integer x; + double y; + } InnerUnion4Typedef; + + /////////////////////////////////////////// + typedef class InnerClass5 { + public: + Integer x; + } InnerClass5Typedef; + + typedef struct InnerStruct5 { + Integer x; + } InnerStruct5Typedef; + + typedef union InnerUnion5 { + Integer x; + double y; + } InnerUnion5Typedef; + + // bug #909387 - inner declared types are treated as forward declarations + InnerStruct1* makeInnerStruct1() { return 0; } + InnerClass1* makeInnerClass1() { return 0; } + InnerUnion1* makeInnerUnion1() { return 0; } + + InnerStruct2* makeInnerStruct2() { return 0; } + InnerClass2* makeInnerClass2() { return 0; } + InnerUnion2* makeInnerUnion2() { return 0; } + + InnerStruct4Typedef* makeInnerStruct4Typedef() { return 0; } + InnerClass4Typedef* makeInnerClass4Typedef() { return 0; } + InnerUnion4Typedef* makeInnerUnion4Typedef() { return 0; } + + InnerStruct5* makeInnerStruct5() { return 0; } + InnerClass5* makeInnerClass5() { return 0; } + InnerUnion5* makeInnerUnion5() { return 0; } + + InnerStruct5Typedef* makeInnerStruct5Typedef() { return 0; } + InnerClass5Typedef* makeInnerClass5Typedef() { return 0; } + InnerUnion5Typedef* makeInnerUnion5Typedef() { return 0; } + + /////////////////////////////////////////// + struct InnerMultiple { + Integer x; + } MultipleInstance1, MultipleInstance2, *MultipleInstance3, MultipleInstance4[2]; + + struct InnerMultipleDerived : public InnerMultiple { + Integer xx; + } MultipleDerivedInstance1, MultipleDerivedInstance2, *MultipleDerivedInstance3, MultipleDerivedInstance4[2]; + + struct { + Integer x; + } MultipleInstanceAnon1, MultipleInstanceAnon2, *MultipleInstanceAnon3, MultipleInstanceAnon4[2]; + + struct : public InnerMultiple { + Integer xx; + } MultipleInstanceAnonDerived1, MultipleInstanceAnonDerived2, *MultipleInstanceAnonDerived3, MultipleInstanceAnonDerived4[2]; + + struct : public InnerMultiple { + Integer xx; + }; + + class : public InnerMultiple { + public: + Integer yy; + }; + + /////////////////////////////////////////// + typedef struct { + Integer x; + } InnerMultipleAnonTypedef1, InnerMultipleAnonTypedef2, *InnerMultipleAnonTypedef3; + + InnerMultipleAnonTypedef1* makeInnerMultipleAnonTypedef1() { return 0; } + InnerMultipleAnonTypedef2* makeInnerMultipleAnonTypedef2() { return 0; } + InnerMultipleAnonTypedef3* makeInnerMultipleAnonTypedef3() { return 0; } + + typedef struct InnerMultipleNamedTypedef { + Integer x; + } InnerMultipleNamedTypedef1, InnerMultipleNamedTypedef2, *InnerMultipleNamedTypedef3; + + InnerMultipleNamedTypedef* makeInnerMultipleNamedTypedef() { return 0; } + InnerMultipleNamedTypedef1* makeInnerMultipleNamedTypedef1() { return 0; } + InnerMultipleNamedTypedef2* makeInnerMultipleNamedTypedef2() { return 0; } + InnerMultipleNamedTypedef3* makeInnerMultipleNamedTypedef3() { return 0; } + + /////////////////////////////////////////// + typedef struct InnerSameName { + Integer x; + } InnerSameName; + + InnerSameName* makeInnerSameName() { return 0; } +}; +%} + +// Ignore nested struct instance +%ignore Outer2::IgnoreMeInstance; +%{ +struct Outer2 { + struct IgnoreMe { + int xx; + }; +}; +%} + +struct Outer2 { + struct IgnoreMe { + int xx; + } IgnoreMeInstance; +}; + + diff --git a/Examples/test-suite/nested_comment.i b/Examples/test-suite/nested_comment.i index a9948eb0f..99d0ffb43 100644 --- a/Examples/test-suite/nested_comment.i +++ b/Examples/test-suite/nested_comment.i @@ -1,23 +1,25 @@ %module nested_comment +#pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS + // this example shows a problem with 'dump_nested' (parser.y). // bug #949654 %inline %{ -typedef struct s1 { -union { -int fsc; /* genie structure hiding - Conductor -*/ -int fso; /* genie structure hiding - FSOptions -*/ -struct { -double *vals; -int size; -} vector_val; /* matrix values are mainly used -in rlgc models */ -char *name; -} n ; -} s2; + typedef struct s1 { + union { + int fsc; /* genie structure hiding - Conductor + */ + int fso; /* genie structure hiding - FSOptions + */ + struct { + double *vals; + int size; + } vector_val; /* matrix values are mainly used + in rlgc models */ + char *name; + } n ; + } s2; %} // comment in nested struct diff --git a/Examples/test-suite/nested_structs.i b/Examples/test-suite/nested_structs.i index 4b13ff69d..60e34a638 100644 --- a/Examples/test-suite/nested_structs.i +++ b/Examples/test-suite/nested_structs.i @@ -2,21 +2,26 @@ // bug #491476 %inline %{ -struct { -struct { -int a; -} a, b; -} a; +struct Outer { + struct { + int val; + } inner1, inner2, *inner3, inner4[1]; + struct Named { + int val; + } inside1, inside2, *inside3, inside4[1]; +} outer; -%} - -// bug #909387 -%inline %{ -struct foo { - struct happy; // no warning - struct sad { int x; }; // warning - happy *good(); // produces good code - sad *bad(); // produces bad code -}; +void setValues(struct Outer *outer, int val) { + outer->inner1.val = val; + outer->inner2.val = val * 2; + outer->inner3 = &outer->inner2; + outer->inner4[0].val = val * 4; + + val = val * 10; + outer->inside1.val = val; + outer->inside2.val = val * 2; + outer->inside3 = &outer->inside2; + outer->inside4[0].val = val * 4; +} %} diff --git a/Examples/test-suite/nested_workaround.i b/Examples/test-suite/nested_workaround.i new file mode 100644 index 000000000..9727dacee --- /dev/null +++ b/Examples/test-suite/nested_workaround.i @@ -0,0 +1,38 @@ +%module nested_workaround +// Similar to "Nested classes" documentation example. + +class Inner { + int val; + public: + Inner(int v = 0) : val(v) {} + void setValue(int v) { val = v; } + int getValue() const { return val; } +}; +%nestedworkaround Outer::Inner; + +%inline %{ +class Outer { +public: + class Inner { + int val; + public: + Inner(int v = 0) : val(v) {} + void setValue(int v) { val = v; } + int getValue() const { return val; } + }; + Inner createInner(int v) const { return Inner(v); } + int getInnerValue(const Inner& i) const { return i.getValue(); } + Inner doubleInnerValue(Inner inner) { + inner.setValue(inner.getValue() * 2); + return inner; + } +}; +%} + +// We've fooled SWIG into thinking that Inner is a global class, so now we need +// to trick the C++ compiler into understanding this apparent global type. +%{ +typedef Outer::Inner Inner; +%} + + diff --git a/Examples/test-suite/octave/Makefile.in b/Examples/test-suite/octave/Makefile.in index 70de84adc..a9a7649ec 100644 --- a/Examples/test-suite/octave/Makefile.in +++ b/Examples/test-suite/octave/Makefile.in @@ -17,7 +17,6 @@ CPP_TEST_CASES += \ CPP_TEST_BROKEN += \ implicittest \ li_implicit \ - li_std_map \ li_std_set \ li_std_stream diff --git a/Examples/test-suite/octave/enums_runme.m b/Examples/test-suite/octave/enums_runme.m index 91f2ce2bf..789f7c9e4 100644 --- a/Examples/test-suite/octave/enums_runme.m +++ b/Examples/test-suite/octave/enums_runme.m @@ -5,3 +5,19 @@ enums.bar2(1) enums.bar3(1) enums.bar1(1) +if (enums.cvar.enumInstance != 2) + error +endif + +if (enums.cvar.Slap != 10) + error +endif + +if (enums.cvar.My != 11) + error +endif + +if (enums.cvar.Thigh != 12) + error +endif + diff --git a/Examples/test-suite/octave/overload_template_fast_runme.m b/Examples/test-suite/octave/overload_template_fast_runme.m index 346af7242..f99ce8642 100644 --- a/Examples/test-suite/octave/overload_template_fast_runme.m +++ b/Examples/test-suite/octave/overload_template_fast_runme.m @@ -5,8 +5,8 @@ overload_template_fast f = foo(); -a = max(3,4); -b = max(3.4,5.2); +a = maximum(3,4); +b = maximum(3.4,5.2); # mix 1 if (mix1("hi") != 101) diff --git a/Examples/test-suite/php/arrays_global_runme.php b/Examples/test-suite/php/arrays_global_runme.php index 7748786a1..12a7806c9 100644 --- a/Examples/test-suite/php/arrays_global_runme.php +++ b/Examples/test-suite/php/arrays_global_runme.php @@ -5,7 +5,7 @@ require "arrays_global.php"; check::functions(array(test_a,test_b,new_simplestruct,new_material)); check::classes(array(arrays_global,SimpleStruct,Material)); -check::globals(array(array_c,array_sc,array_uc,array_s,array_us,array_i,array_ui,array_l,array_ul,array_ll,array_f,array_d,array_struct,array_structpointers,array_ipointers,array_enum,array_enumpointers,array_const_i,beginstring_fix44a,beginstring_fix44b,beginstring_fix44c,beginstring_fix44d,beginstring_fix44e,beginstring_fix44f,chitmat,hitmat_val,hitmat)); +check::globals(array(array_c,array_sc,array_uc,array_s,array_us,array_i,array_ui,array_l,array_ul,array_ll,array_f,array_d,array_struct,array_structpointers,array_ipointers,array_enum,array_enumpointers,array_const_i,beginstring_fix44a,beginstring_fix44b,beginstring_fix44c,beginstring_fix44d,beginstring_fix44e,beginstring_fix44f,chitmat,hitmat_val,hitmat,simplestruct_double_field)); // The size of array_c is 2, but the last byte is \0, so we can only store a // single byte string in it. check::set(array_c,"Z"); diff --git a/Examples/test-suite/php/arrays_global_twodim_runme.php b/Examples/test-suite/php/arrays_global_twodim_runme.php index 9f16a6cf6..40ecf1719 100644 --- a/Examples/test-suite/php/arrays_global_twodim_runme.php +++ b/Examples/test-suite/php/arrays_global_twodim_runme.php @@ -5,7 +5,7 @@ require "arrays_global_twodim.php"; check::functions(array(fn_taking_arrays,get_2d_array,new_simplestruct,new_material)); check::classes(array(arrays_global_twodim,SimpleStruct,Material)); -check::globals(array(array_c,array_sc,array_uc,array_s,array_us,array_i,array_ui,array_l,array_ul,array_ll,array_f,array_d,array_struct,array_structpointers,array_ipointers,array_enum,array_enumpointers,array_const_i,chitmat,hitmat_val,hitmat)); +check::globals(array(array_c,array_sc,array_uc,array_s,array_us,array_i,array_ui,array_l,array_ul,array_ll,array_f,array_d,array_struct,array_structpointers,array_ipointers,array_enum,array_enumpointers,array_const_i,chitmat,hitmat_val,hitmat,simplestruct_double_field)); $a1=array(10,11,12,13); $a2=array(14,15,16,17); $a=array($a1,$a2); diff --git a/Examples/test-suite/php/arrays_runme.php b/Examples/test-suite/php/arrays_runme.php index 7419504d1..23490e61e 100644 --- a/Examples/test-suite/php/arrays_runme.php +++ b/Examples/test-suite/php/arrays_runme.php @@ -4,15 +4,14 @@ require "arrays.php"; check::functions(array(fn_taking_arrays,newintpointer,setintfrompointer,getintfrompointer,array_pointer_func)); check::classes(array(arrays,SimpleStruct,ArrayStruct,CartPoseData_t)); -// No new vars -check::globals(array()); +check::globals(array(simplestruct_double_field,arraystruct_array_c,arraystruct_array_sc,arraystruct_array_uc,arraystruct_array_s,arraystruct_array_us,arraystruct_array_i,arraystruct_array_ui,arraystruct_array_l,arraystruct_array_ul,arraystruct_array_ll,arraystruct_array_f,arraystruct_array_d,arraystruct_array_struct,arraystruct_array_structpointers,arraystruct_array_ipointers,arraystruct_array_enum,arraystruct_array_enumpointers,arraystruct_array_const_i,cartposedata_t_p)); $ss=new simplestruct(); check::classname(simplestruct,$ss); $as=new arraystruct(); $as->array_c="abc"; -check::equal($as->array_c,"ab",'$as->array_c=="ab"'); +check::equal($as->array_c,"a",'$as->array_c=="a"'); check::done(); ?> diff --git a/Examples/test-suite/php/arrays_scope_runme.php b/Examples/test-suite/php/arrays_scope_runme.php index 6d3eba76d..c208b7518 100644 --- a/Examples/test-suite/php/arrays_scope_runme.php +++ b/Examples/test-suite/php/arrays_scope_runme.php @@ -3,12 +3,12 @@ require "tests.php"; require "arrays_scope.php"; -// No new functions +// New functions check::functions(array(new_bar,bar_blah)); -// No new classes +// New classes check::classes(array(arrays_scope,Bar)); -// now new vars -check::globals(array()); +// New vars +check::globals(array(bar_adata,bar_bdata,bar_cdata)); $bar=new bar(); diff --git a/Examples/test-suite/php/cpp_static_runme.php b/Examples/test-suite/php/cpp_static_runme.php index 9292a63cf..e1cc3e733 100644 --- a/Examples/test-suite/php/cpp_static_runme.php +++ b/Examples/test-suite/php/cpp_static_runme.php @@ -3,12 +3,12 @@ require "tests.php"; require "cpp_static.php"; -// No new functions -check::functions(array()); -// No new classes +// New functions +check::functions(array(staticfunctiontest_static_func,staticfunctiontest_static_func_2,staticfunctiontest_static_func_3)); +// New classes check::classes(array(StaticMemberTest,StaticFunctionTest)); -// now new vars -check::globals(array()); +// New vars +check::globals(array(staticmembertest_static_int)); check::done(); ?> diff --git a/Examples/test-suite/php/director_extend_runme.php b/Examples/test-suite/php/director_extend_runme.php index f282df17d..f283aefbe 100644 --- a/Examples/test-suite/php/director_extend_runme.php +++ b/Examples/test-suite/php/director_extend_runme.php @@ -11,11 +11,6 @@ check::classes(array(SpObject)); check::globals(array()); class MyObject extends SpObject{ - function __construct() { - parent::__construct(); - return; - } - function getFoo() { return 123; } diff --git a/Examples/test-suite/php/enum_scope_template_runme.php b/Examples/test-suite/php/enum_scope_template_runme.php index e152efca6..85ba467b7 100644 --- a/Examples/test-suite/php/enum_scope_template_runme.php +++ b/Examples/test-suite/php/enum_scope_template_runme.php @@ -3,7 +3,7 @@ require "tests.php"; require "enum_scope_template.php"; check::classes(array("enum_scope_template", "TreeInt")); -check::functions("chops"); +check::functions(array("chops","treeint_chops")); check::equal(0,TreeInt_Oak,"0==TreeInt_Oak"); check::equal(1,TreeInt_Fir,"1==TreeInt_Fir"); check::equal(2,TreeInt_Cedar,"2==TreeInt_Cedar"); diff --git a/Examples/test-suite/php/ignore_parameter_runme.php b/Examples/test-suite/php/ignore_parameter_runme.php index d455c39a1..1c8c76ad4 100644 --- a/Examples/test-suite/php/ignore_parameter_runme.php +++ b/Examples/test-suite/php/ignore_parameter_runme.php @@ -3,11 +3,11 @@ require "tests.php"; require "ignore_parameter.php"; -// No new functions -check::functions(array(jaguar,lotus,tvr,ferrari)); -// No new classes -check::classes(array(sportscars,minicooper,morrisminor,fordanglia,austinallegro)); -// now new vars +// New functions +check::functions(array(jaguar,lotus,tvr,ferrari,sportscars_daimler,sportscars_astonmartin,sportscars_bugatti,sportscars_lamborghini)); +// New classes +check::classes(array(ignore_parameter,SportsCars,MiniCooper,MorrisMinor,FordAnglia,AustinAllegro)); +// No new vars check::globals(array()); check::equal(jaguar(2,3.4),"hello",'jaguar(2,3.4)=="hello"'); diff --git a/Examples/test-suite/php/li_carrays_runme.php b/Examples/test-suite/php/li_carrays_runme.php index b6d47e926..fbe5cc793 100644 --- a/Examples/test-suite/php/li_carrays_runme.php +++ b/Examples/test-suite/php/li_carrays_runme.php @@ -3,14 +3,14 @@ require "tests.php"; require "li_carrays.php"; // Check functions. -check::functions(array(new_intarray,delete_intarray,intarray_getitem,intarray_setitem)); +check::functions(array(new_intarray,delete_intarray,intarray_getitem,intarray_setitem,doublearray_getitem,doublearray_setitem,doublearray_cast,doublearray_frompointer,xyarray_getitem,xyarray_setitem,xyarray_cast,xyarray_frompointer,delete_abarray,abarray_getitem,abarray_setitem)); // Check classes. // NB An "li_carrays" class is created as a mock namespace. check::classes(array(li_carrays,doubleArray,AB,XY,XYArray)); -// No new global variables. -check::globals(array()); +// Check global variables. +check::globals(array(xy_x,xy_y,globalxyarray,ab_a,ab_b,globalabarray)); $d = new doubleArray(10); diff --git a/Examples/test-suite/php/primitive_ref_runme.php b/Examples/test-suite/php/primitive_ref_runme.php index 6a5a3f43d..ab23fb1cc 100644 --- a/Examples/test-suite/php/primitive_ref_runme.php +++ b/Examples/test-suite/php/primitive_ref_runme.php @@ -17,9 +17,9 @@ check::equal(ref_bool(true), true, "ref_bool failed"); check::equal(ref_float(3.5), 3.5, "ref_float failed"); check::equal(ref_double(3.5), 3.5, "ref_double failed"); check::equal(ref_char('x'), 'x', "ref_char failed"); -//check::equal(ref_longlong(0x123456789ABCDEF0), 0x123456789ABCDEF0, "ref_longlong failed"); -//check::equal(ref_ulonglong(0xF23456789ABCDEF0), 0xF23456789ABCDEF0, "ref_ulonglong failed"); -printf("TODO: long long and unsigned long long const reference typemaps\n"); +check::equal(ref_longlong(0x123456789ABCDEF0), 0x123456789ABCDEF0, "ref_longlong failed"); +# 0xF23456789ABCDEF0 won't fit in a long, so PHP makes it a double, but SWIG opts to return it as a string. +check::equal((double)ref_ulonglong(0xF23456789ABCDEF0), 0xF23456789ABCDEF0, "ref_ulonglong failed"); check::done(); ?> diff --git a/Examples/test-suite/php_namewarn_rename.i b/Examples/test-suite/php_namewarn_rename.i index cebe93f02..e3447a9c4 100644 --- a/Examples/test-suite/php_namewarn_rename.i +++ b/Examples/test-suite/php_namewarn_rename.i @@ -2,19 +2,25 @@ #ifdef SWIGPHP %warnfilter(SWIGWARN_PARSE_KEYWORD) Empty(); -// FIXME: this doesn't work for me: %warnfilter(SWIGWARN_PARSE_KEYWORD) stdClass; +%warnfilter(SWIGWARN_PARSE_KEYWORD) directory; %warnfilter(SWIGWARN_PARSE_KEYWORD) Hello::empty(); #endif %inline %{ + int Exception() { return 13; } + void Empty() {} class stdClass { }; + class directory + { + }; + struct Hello { void empty() {} diff --git a/Examples/test-suite/preproc_constants.i b/Examples/test-suite/preproc_constants.i new file mode 100644 index 000000000..771f3db1b --- /dev/null +++ b/Examples/test-suite/preproc_constants.i @@ -0,0 +1,82 @@ +%module preproc_constants + +// Note: C types are slightly different to C++ types as (a && b) is int in C and bool in C++ + +// Simple constants +#define CONST_INT1 10 +#define CONST_INT2 0xFF + +#define CONST_UINT1 10u +#define CONST_UINT2 10U +#define CONST_UINT3 0xFFu +#define CONST_UINT4 0xFFU + +#define CONST_LONG1 10l +#define CONST_LONG2 10L +#define CONST_LONG3 0xFFl +#define CONST_LONG4 0xFFL + +#define CONST_LLONG1 10LL +#define CONST_LLONG2 10ll +#define CONST_LLONG3 0xFFll +#define CONST_LLONG4 0xFFLL + +#define CONST_ULLONG1 10ull +#define CONST_ULLONG2 10ULL +#define CONST_ULLONG3 0xFFull +#define CONST_ULLONG4 0xFFULL + +#define CONST_DOUBLE1 10e1 +#define CONST_DOUBLE2 10E1 +#define CONST_DOUBLE3 12.3 +#define CONST_DOUBLE4 12. +#define CONST_DOUBLE5 12.3f +#define CONST_DOUBLE6 12.3F + +#define CONST_BOOL1 true +#define CONST_BOOL2 false + +#define CONST_CHAR 'x' +#define CONST_STRING1 "const string" +#define CONST_STRING2 "const" " string" + +// Expressions - runtime tests check the type for any necessary type promotions of the expressions + +#define INT_AND_BOOL 0xFF & true +//#define INT_AND_CHAR 0xFF & 'A' /* FIXME compile error */ +#define INT_AND_INT 0xFF & 2 +#define INT_AND_UINT 0xFF & 2u +#define INT_AND_LONG 0xFF & 2l +#define INT_AND_ULONG 0xFF & 2ul +#define INT_AND_LLONG 0xFF & 2ll +#define INT_AND_ULLONG 0xFF & 2ull + +#define BOOL_AND_BOOL true & true // Note integral promotion to type int +//#define CHAR_AND_CHAR 'A' & 'B' // Note integral promotion to type int +/* FIXME ABOVE */ + + +#define EXPR_MULTIPLY 0xFF * 2 +#define EXPR_DIVIDE 0xFF / 2 +//FIXME #define EXPR_MOD 0xFF % 2 + +#define EXPR_PLUS 0xFF + 2 +#define EXPR_MINUS 0xFF + 2 + +#define EXPR_LSHIFT 0xFF << 2 +#define EXPR_RSHIFT 0xFF >> 2 +/* FIXME +#define EXPR_LT 0xFF < 255 +#define EXPR_GT 0xFF > 255 +*/ +#define EXPR_LTE 0xFF <= 255 +#define EXPR_GTE 0xFF >= 255 +#define EXPR_INEQUALITY 0xFF != 255 +#define EXPR_EQUALITY 0xFF == 255 +#define EXPR_AND 0xFF & 1 +#define EXPR_XOR 0xFF ^ 1 +#define EXPR_OR 0xFF | 1 +#define EXPR_LAND 0xFF && 1 +#define EXPR_LOR 0xFF || 1 +#define EXPR_CONDITIONAL true ? 2 : 2.2 + diff --git a/Examples/test-suite/preproc_constants_c.i b/Examples/test-suite/preproc_constants_c.i new file mode 100644 index 000000000..e27d1f508 --- /dev/null +++ b/Examples/test-suite/preproc_constants_c.i @@ -0,0 +1,6 @@ +%module preproc_constants_c + +%define true 1 %enddef +%define false 0 %enddef + +%include "preproc_constants.i" diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index 274d53f1d..4938ddc27 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -49,7 +49,6 @@ CPP_TEST_CASES += \ li_implicit \ li_std_vectora \ li_std_vector_extra \ - li_std_map \ li_std_multimap \ li_std_pair_extra \ li_std_set \ diff --git a/Examples/test-suite/python/director_exception_runme.py b/Examples/test-suite/python/director_exception_runme.py index ef7a044f1..82be1289b 100644 --- a/Examples/test-suite/python/director_exception_runme.py +++ b/Examples/test-suite/python/director_exception_runme.py @@ -43,7 +43,7 @@ b = launder(a) try: b.pong() except TypeError, e: - if str(e) == "Swig director type mismatch in output value of type 'std::string'": + if str(e) == "SWIG director type mismatch in output value of type 'std::string'": ok = 1 else: print "Unexpected error message: %s" % str(e) diff --git a/Examples/test-suite/python/enums_runme.py b/Examples/test-suite/python/enums_runme.py index 59a982974..e8dbe6942 100644 --- a/Examples/test-suite/python/enums_runme.py +++ b/Examples/test-suite/python/enums_runme.py @@ -5,3 +5,15 @@ _enums.bar2(1) _enums.bar3(1) _enums.bar1(1) +if _enums.cvar.enumInstance != 2: + raise RuntimeError + +if _enums.cvar.Slap != 10: + raise RuntimeError + +if _enums.cvar.My != 11: + raise RuntimeError + +if _enums.cvar.Thigh != 12: + raise RuntimeError + diff --git a/Examples/test-suite/python/extern_c_runme.py b/Examples/test-suite/python/extern_c_runme.py new file mode 100644 index 000000000..1a6d2aa12 --- /dev/null +++ b/Examples/test-suite/python/extern_c_runme.py @@ -0,0 +1,4 @@ +import extern_c + +extern_c.RealFunction(2) + diff --git a/Examples/test-suite/python/li_cdata_runme.py b/Examples/test-suite/python/li_cdata_runme.py new file mode 100644 index 000000000..061ca6f68 --- /dev/null +++ b/Examples/test-suite/python/li_cdata_runme.py @@ -0,0 +1,10 @@ + +from li_cdata import * + +s = "ABC abc" +m = malloc(256) +memmove(m, s) +ss = cdata(m, 7) +if ss != "ABC abc": + raise "failed" + diff --git a/Examples/test-suite/python/li_std_vector_extra_runme.py b/Examples/test-suite/python/li_std_vector_extra_runme.py index 776eacfb3..8900d7298 100644 --- a/Examples/test-suite/python/li_std_vector_extra_runme.py +++ b/Examples/test-suite/python/li_std_vector_extra_runme.py @@ -154,3 +154,23 @@ if extractInt(vi[0]) != 11: if extractInt(vi[1]) != 22: raise RuntimeError +# vector const pointer checks +csp = makeConstShortPtr(111) + +error = 0 +try: + vcs = ConstShortPtrVector((csp, dp)) # check vector does not accept double * element + error = 1 +except: + pass + +if error: + raise RuntimeError + +vcs = ConstShortPtrVector((csp, makeConstShortPtr(222))) +if extractConstShort(vcs[0]) != 111: + raise RuntimeError + +if extractConstShort(vcs[1]) != 222: + raise RuntimeError + diff --git a/Examples/test-suite/python/memberin_extend_c_runme.py b/Examples/test-suite/python/memberin_extend_c_runme.py new file mode 100644 index 000000000..314761f89 --- /dev/null +++ b/Examples/test-suite/python/memberin_extend_c_runme.py @@ -0,0 +1,6 @@ +import memberin_extend_c + +t = memberin_extend_c.Person() +t.name = "Fred Bloggs" +if t.name != "FRED BLOGGS": + raise RuntimeError("name wrong") diff --git a/Examples/test-suite/python/nested_workaround_runme.py b/Examples/test-suite/python/nested_workaround_runme.py new file mode 100644 index 000000000..a8a75d370 --- /dev/null +++ b/Examples/test-suite/python/nested_workaround_runme.py @@ -0,0 +1,13 @@ +from nested_workaround import * + +inner = Inner(5) +outer = Outer() +newInner = outer.doubleInnerValue(inner) +if newInner.getValue() != 10: + raise RuntimeError + +outer = Outer() +inner = outer.createInner(3) +newInner = outer.doubleInnerValue(inner) +if outer.getInnerValue(newInner) != 6: + raise RuntimeError diff --git a/Examples/test-suite/python/overload_template_fast_runme.py b/Examples/test-suite/python/overload_template_fast_runme.py index a8d271d27..d47f7d14d 100644 --- a/Examples/test-suite/python/overload_template_fast_runme.py +++ b/Examples/test-suite/python/overload_template_fast_runme.py @@ -1,8 +1,8 @@ from overload_template_fast import * f = foo() -a = max(3,4) -b = max(3.4,5.2) +a = maximum(3,4) +b = maximum(3.4,5.2) # mix 1 if (mix1("hi") != 101): diff --git a/Examples/test-suite/python/struct_initialization_runme.py b/Examples/test-suite/python/struct_initialization_runme.py new file mode 100644 index 000000000..fbed6a5e9 --- /dev/null +++ b/Examples/test-suite/python/struct_initialization_runme.py @@ -0,0 +1,20 @@ +from struct_initialization import * + +if cvar.instanceC1.x != 10: + raise RuntimeError + +if cvar.instanceD1.x != 10: + raise RuntimeError + +if cvar.instanceD2.x != 20: + raise RuntimeError + +if cvar.instanceD3.x != 30: + raise RuntimeError + +if cvar.instanceE1.x != 1: + raise RuntimeError + +if cvar.instanceF1.x != 1: + raise RuntimeError + diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index dc8751da1..27996616e 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -14,7 +14,6 @@ CPP_TEST_CASES = \ li_cstring \ li_factory \ li_std_functors \ - li_std_map \ li_std_multimap \ li_std_pair_lang_object \ li_std_queue \ diff --git a/Examples/test-suite/special_variable_macros.i b/Examples/test-suite/special_variable_macros.i index 3f0cd724a..f27bbd619 100644 --- a/Examples/test-suite/special_variable_macros.i +++ b/Examples/test-suite/special_variable_macros.i @@ -88,7 +88,7 @@ const char * testMary(Name *mary) { %{ /*%typemap(in) (Name *multiname, int num) start */ temp_name = $*1_ltype("multiname num"); - temp_count = strlen(temp_name.getNamePtr()->getName()); + temp_count = (int)strlen(temp_name.getNamePtr()->getName()); (void)$input; $1 = temp_name.getNamePtr(); $2 = temp_count + 100; @@ -103,7 +103,7 @@ $typemap(in, (Name *multiname, int num)) %inline %{ const char * testJim(Name *jim, int count) { - if (count != strlen(jim->getNamePtr()->getName()) + 100) + if (count != (int)strlen(jim->getNamePtr()->getName()) + 100) return "size check failed"; else return jim->getName(); diff --git a/Examples/test-suite/static_const_member.i b/Examples/test-suite/static_const_member.i index 99dc89bd1..3db60b4c2 100644 --- a/Examples/test-suite/static_const_member.i +++ b/Examples/test-suite/static_const_member.i @@ -5,6 +5,14 @@ %module static_const_member +#if SWIGJAVA +%javaconst(1) EN; +%javaconst(1) CHARTEST; +#elif SWIGCSHARP +%csconst(1) EN; +%csconst(1) CHARTEST; +#endif + %inline %{ class X { @@ -12,6 +20,7 @@ public: static const int PN = 0; static const int CN = 1; static const int EN = 2; + static const char CHARTEST = 'A'; }; %} diff --git a/Examples/test-suite/struct_initialization.i b/Examples/test-suite/struct_initialization.i new file mode 100644 index 000000000..c378ba31d --- /dev/null +++ b/Examples/test-suite/struct_initialization.i @@ -0,0 +1,31 @@ +// Test declaration and initialization of structs (C code) +%module struct_initialization + +%inline %{ + +// Named types +struct StructA { + int x; +} instanceA1; + +struct StructB { + int x; +} instanceB1, instanceB2, instanceB3; + +struct StructC { + int x; +} instanceC1 = { 10 }; + +struct StructD { + int x; +} instanceD1 = { 10 }, instanceD2 = { 20 }, instanceD3 = { 30 }; + +struct StructE { + int x; +} instanceE1[3] = { { 1 }, { 2 }, { 3} }; + +struct StructF { + int x; +} instanceF1[3] = { { 1 }, { 2 } }, instanceF2[2] = { { -1 }, { -2 } }, instanceF3[2] = { { 11 }, { 22 } }; + +%} diff --git a/Examples/test-suite/struct_initialization_cpp.i b/Examples/test-suite/struct_initialization_cpp.i new file mode 100644 index 000000000..dc47077b5 --- /dev/null +++ b/Examples/test-suite/struct_initialization_cpp.i @@ -0,0 +1,5 @@ +// Test declaration and initialization of structs (C++ code) +%module struct_initialization_cpp + +%include "struct_initialization.i" // C code + diff --git a/Examples/test-suite/template_classes.i b/Examples/test-suite/template_classes.i index a05eb9b58..ebe13bd9f 100644 --- a/Examples/test-suite/template_classes.i +++ b/Examples/test-suite/template_classes.i @@ -3,12 +3,6 @@ %module template_classes - -#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_CLASS - -%{ -%} - %inline %{ template @@ -27,21 +21,16 @@ public: private: Point point; - template struct pair2nd_eq { }; - - - struct Foo : Point { }; Foo foo; - }; %} @@ -49,4 +38,3 @@ private: %template(PointInt) Point; %template(RectangleInt) RectangleTest; - diff --git a/Examples/test-suite/template_nested.i b/Examples/test-suite/template_nested.i new file mode 100644 index 000000000..1bb1c686a --- /dev/null +++ b/Examples/test-suite/template_nested.i @@ -0,0 +1,116 @@ +%module template_nested + +// Test nested templates - that is template classes and template methods within a class. + +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterClass::Inner1; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterClass::Inner2; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterTemplate::NestedInnerTemplate1; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterTemplate::NestedInnerTemplate2; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterTemplate::NestedInnerTemplate3; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterTemplate::NestedStruct; + +namespace ns { +template struct ForwardTemplate; +} +%{ +namespace ns { + template struct ForwardTemplate { + void tmethod(T t) {} + }; +} +%} + +%inline %{ + +namespace ns { + + class NormalClass { + public: + NormalClass() {} + ~NormalClass() {} + }; + + template struct NormalTemplate { + void tmethod(T t) {} + }; + + class OuterClass { + public: + template struct Inner1 { + template struct SuperInner1 { + void method1(U t) {} + }; + template struct SuperInner2 { + void method1(V t) {} + }; + template void tmethod(W w) {} + template void tmethodAgain(X x) {} + template struct SuperBase : public SuperInner1 { + void method1(Y y) {} + }; + }; + Inner1 useInner1(const Inner1& inner) { return inner; } + + template void InnerTMethod(Z z) {} + + template class Inner2 : public NormalTemplate { + public: + template class SuperInner1 { + public: + SuperInner1() {} + void method1(U t) {} + }; + template struct SuperInner2 { + void method1(V t) {} + }; + int embeddedVar; + template void tmethod(X x) {} + template struct SuperBase : public SuperInner1 { + void method1(Y y) {} + }; + }; + Inner2 useInner2(const Inner2& inner) { return inner; } + int iii; + }; + struct ABC { + ABC() {} + ~ABC() {} + }; + + struct TemplateFuncs { + template X templateMethod1(X x) { return x; } + template X templateMethod2(X x) { return x; } + }; + + template struct OuterTemplate { + template struct NestedInnerTemplate1 { + template void NestedInnerInnerTMethod(Z z) {} + void hohum() {} + }; + template void NestedInnerTMethod(UU u, W w) {} + template struct NestedInnerTemplate2 { + void hohum() {} + }; + UU hohum(UU u) { return u; } + template struct NestedInnerTemplate3 : public NestedInnerTemplate2 { + void hohum() {} + }; + struct NestedStruct { + NestedStruct() {} + void hohum() {} + }; + NestedInnerTemplate1 useNestedInnerTemplate1(const NestedInnerTemplate1& inner) { return inner; } + NestedInnerTemplate2 useNestedInnerTemplate2(const NestedInnerTemplate2& inner) { return inner; } + NestedInnerTemplate3 useNestedInnerTemplate3(const NestedInnerTemplate3& inner) { return inner; } + NestedStruct useNestedStruct(const NestedStruct& inner) { return inner; } + }; +} + +%} + +%template(T_NormalTemplateNormalClass) ns::NormalTemplate; +%template(T_OuterTMethodNormalClass) ns::OuterClass::InnerTMethod; +%template(T_TemplateFuncs1Int) ns::TemplateFuncs::templateMethod1; +%template(T_TemplateFuncs2Double) ns::TemplateFuncs::templateMethod2; +%template(T_NestedOuterTemplateDouble) ns::OuterTemplate; + diff --git a/Examples/test-suite/template_nested_typemaps.i b/Examples/test-suite/template_nested_typemaps.i new file mode 100644 index 000000000..54f5bc503 --- /dev/null +++ b/Examples/test-suite/template_nested_typemaps.i @@ -0,0 +1,47 @@ +#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_TEMPLATE + +%module template_nested_typemaps + +// Testing that the typemaps invoked within a class via %template are picked up by appropriate methods + +template struct Typemap { + %typemap(in) T { + $1 = -99; + } +}; +template <> struct Typemap { // Note explicit specialization + %typemap(in) short { + $1 = -77; + } +}; + +%inline %{ +int globalInt1(int s) { return s; } +short globalShort1(short s) { return s; } + +template struct Breeze { + int methodInt1(int s) { return s; } +#if defined(SWIG) + %template() Typemap; +#endif + int methodInt2(int s) { return s; } // should pick up the typemap within Typemap + void takeIt(T t) {} + + short methodShort1(short s) { return s; } +#if defined(SWIG) + %template(TypemapShort) Typemap; // should issue warning SWIGWARN_PARSE_NESTED_TEMPLATE +#endif + short methodShort2(short s) { return s; } // should pick up the typemap within Typemap +}; + +int globalInt2(int s) { return s; } +short globalShort2(short s) { return s; } +%} + +%template(BreezeString) Breeze; + +%inline %{ +int globalInt3(int s) { return s; } // should pick up the typemap within Typemap +short globalShort3(short s) { return s; } // should pick up the typemap within Typemap +%} + diff --git a/Examples/test-suite/template_partial_specialization.i b/Examples/test-suite/template_partial_specialization.i new file mode 100644 index 000000000..8781fbbda --- /dev/null +++ b/Examples/test-suite/template_partial_specialization.i @@ -0,0 +1,150 @@ +%module template_partial_specialization + +%inline %{ +namespace One { + template struct OneParm { void a() {} }; + template struct OneParm { void b() {} }; + template struct OneParm { void c() {} }; + template struct OneParm { void d() {} }; + template struct OneParm { void e() {} }; + + template <> struct OneParm { void f() {} }; + template <> struct OneParm { void g() {} }; + template <> struct OneParm { void h() {} }; + + template <> struct OneParm { void i() {} }; + template <> struct OneParm { void j() {} }; + template <> struct OneParm { void k() {} }; + template <> struct OneParm { void l() {} }; +} +%} + +// partial specializations +%template(A) One::OneParm; +%template(B) One::OneParm; +%template(C) One::OneParm; +%template(D) One::OneParm; +%template(E) One::OneParm; + +// explicit specializations +%template(F) One::OneParm; +%template(G) One::OneParm; +%template(H) One::OneParm; + +// %template scope explicit specializations +namespace ONE { + %template(I) One::OneParm; + %template(J) ::One::OneParm; +} +%template(K) ::One::OneParm; +namespace One { + %template(L) OneParm; +} + +// %template scope partial specializations +namespace ONE { + %template(BB) One::OneParm; + %template(BBB) ::One::OneParm; +} +%template(BBBB) ::One::OneParm; +namespace One { + %template(BBBBB) OneParm; +} + +// non-exact match +%template(B1) One::OneParm; +%template(B2) One::OneParm; +%template(B3) One::OneParm; +%template(B4) One::OneParm; + + +// Two parameter specialization tests +%inline %{ +struct Concrete {}; +namespace Two { + template struct TwoParm { void a() {} }; + template struct TwoParm { void b() {} }; + template struct TwoParm { void c() {} }; + template struct TwoParm { void d() {} }; + template struct TwoParm { void e() {} }; + template struct TwoParm { void f() {} }; + template <> struct TwoParm { void g() {} }; + template <> struct TwoParm { void h() {} }; +} +%} + +namespace Two { + %template(A_) TwoParm; + %template(B_) TwoParm; + %template(C_) TwoParm; + %template(D_) TwoParm; + %template(E_) TwoParm; + %template(F_) TwoParm; + %template(G_) TwoParm; + + %template(C1_) TwoParm; + %template(C2_) TwoParm; +} + +%template(C3_) Two::TwoParm; +%template(C4_) ::Two::TwoParm; +%template(B1_) ::Two::TwoParm; +%template(E1_) Two::TwoParm; +%template(E2_) Two::TwoParm; +%template(H_) Two::TwoParm< ::Concrete, ::Concrete * >; + + +// Many template parameters +%inline %{ +template struct FiveParm { void a() {} }; +template struct FiveParm { void b() {} }; +%} + +%template(FiveParm1) FiveParm; + +%inline %{ +template struct ThreeParm; +template struct ThreeParm { void a1() {} }; +template struct ThreeParm { void a2() {} }; +template struct ThreeParm { void a3() {} }; +%} + +%template(ThreeParmInt) ThreeParm; + +#if 0 +// TODO fix: +%inline %{ +//namespace S { + template struct X { void a() {} }; + template struct X { void b() {} }; +// template<> struct X { void c() {} }; +//} +%} + +namespace AA { // thinks X is in AA namespace + %template(X2) X; +}; +#endif + +#if 0 +namespace Space { +} +template struct Vector { +#ifdef SWIG + %template() Space::VectorHelper; +#endif + void gook(T i) {} + void geeko(double d) {} + void geeky(int d) {} +}; +/* +template struct Vector { +}; +*/ +//} +%} + +%template(VectorIntPtr) Space::Vector; // should fail as Vector is in global namespace +// is this a regression - no fails in 1.3.40 too +// Note problem is removed by removing empty Space namespace!! +#endif diff --git a/Examples/test-suite/template_partial_specialization_typedef.i b/Examples/test-suite/template_partial_specialization_typedef.i new file mode 100644 index 000000000..6fdbf99aa --- /dev/null +++ b/Examples/test-suite/template_partial_specialization_typedef.i @@ -0,0 +1,130 @@ +// This testcase is almost identical to template_partial_specialization but uses typedefs for %template + +%module template_partial_specialization_typedef + +%inline %{ +namespace TypeDef { + typedef double Double; + typedef int * IntPtr; + typedef double * DoublePtr; + typedef double & DoubleRef; + typedef const double & ConstDoubleRef; + typedef double * const & DoublePtrConstRef; + + typedef int Int; + typedef int * const & IntPtrConstRef; + typedef int ** IntPtrPtr; + typedef float Float; + typedef float * FloatPtr; + typedef float ** FloatPtrPtr; + typedef float *** FloatPtrPtrPtr; + + typedef bool * BoolPtr; + typedef char * CharPtr; + typedef short * ShortPtr; + typedef long * LongPtr; + typedef unsigned int ** UnsignedIntPtrPtr; + typedef unsigned int *** UnsignedIntPtrPtrPtr; + typedef const unsigned int ** ConstUnsignedIntPtr; + typedef const unsigned int *** ConstUnsignedIntPtrPtr; +} +namespace One { + template struct OneParm { void a() {} }; + template struct OneParm { void b() {} }; + template struct OneParm { void c() {} }; + template struct OneParm { void d() {} }; + template struct OneParm { void e() {} }; + + template <> struct OneParm { void f() {} }; + template <> struct OneParm { void g() {} }; + template <> struct OneParm { void h() {} }; + + template <> struct OneParm { void i() {} }; + template <> struct OneParm { void j() {} }; + template <> struct OneParm { void k() {} }; + template <> struct OneParm { void l() {} }; +} +%} + +// partial specializations +%template(A) One::OneParm; +%template(B) One::OneParm; +%template(C) One::OneParm; +%template(D) One::OneParm; +%template(E) One::OneParm; + +// explicit specializations +%template(F) One::OneParm; +%template(G) One::OneParm; +%template(H) One::OneParm; + +// %template scope explicit specializations +namespace ONE { + %template(I) One::OneParm; + %template(J) ::One::OneParm; +} +%template(K) ::One::OneParm; +namespace One { + %template(L) OneParm; +} + +// %template scope partial specializations +namespace ONE { + %template(BB) One::OneParm; + %template(BBB) ::One::OneParm; +} +%template(BBBB) ::One::OneParm; +namespace One { + %template(BBBBB) OneParm; +} + +// non-exact match +%template(B1) One::OneParm; +%template(B2) One::OneParm; +%template(B3) One::OneParm; +%template(B4) One::OneParm; + + +// Two parameter specialization tests +%inline %{ +struct Concrete {}; +namespace Two { + template struct TwoParm { void a() {} }; + template struct TwoParm { void b() {} }; + template struct TwoParm { void c() {} }; + template struct TwoParm { void d() {} }; + template struct TwoParm { void e() {} }; + template struct TwoParm { void f() {} }; + template <> struct TwoParm { void g() {} }; +} +%} + +%inline %{ +namespace TypeDef { + typedef const double * ConstDoublePtr; + typedef const int * ConstIntPtr; + typedef int * IntPtr; + typedef Concrete * ConcretePtr; + typedef const Concrete * ConstConcretePtr; + typedef void * VoidPtr; +} +%} +namespace Two { + %template(A_) TwoParm; + %template(B_) TwoParm; + %template(C_) TwoParm; + %template(D_) TwoParm; + %template(E_) TwoParm; + %template(F_) TwoParm; + %template(G_) TwoParm; + + %template(C1_) TwoParm; + %template(C2_) TwoParm; +} + +%template(C3_) Two::TwoParm; +%template(C4_) ::Two::TwoParm; +%template(B1_) ::Two::TwoParm; +%template(E1_) Two::TwoParm; +%template(E2_) Two::TwoParm; + diff --git a/Examples/test-suite/union_scope.i b/Examples/test-suite/union_scope.i index 67093eff6..b7307cb29 100644 --- a/Examples/test-suite/union_scope.i +++ b/Examples/test-suite/union_scope.i @@ -2,6 +2,7 @@ %warnfilter(SWIGWARN_RUBY_WRONG_NAME) nRState; // Ruby, wrong class name %warnfilter(SWIGWARN_RUBY_WRONG_NAME) nRState_rstate; // Ruby, wrong class name +#pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS %inline %{ class nRState { diff --git a/Examples/test-suite/using_namespace.i b/Examples/test-suite/using_namespace.i index 799c7cfb5..ce02e9a87 100644 --- a/Examples/test-suite/using_namespace.i +++ b/Examples/test-suite/using_namespace.i @@ -74,3 +74,14 @@ struct X { }; } + +%inline %{ +namespace SpaceMan { + typedef double SpaceManDouble; +} +using namespace ::SpaceMan; // global namespace prefix + +SpaceManDouble useSpaceMan(SpaceManDouble s) { return s; } + +%} + diff --git a/Examples/test-suite/valuewrapper_const.i b/Examples/test-suite/valuewrapper_const.i index db1c807c8..3091df30e 100644 --- a/Examples/test-suite/valuewrapper_const.i +++ b/Examples/test-suite/valuewrapper_const.i @@ -24,6 +24,12 @@ public: const B GetBconst() const { return b; } + ::B GetBGlobalQualifier() { + return b; + } + const ::B GetBconstGlobalGlobalQualifier() const { + return b; + } }; %} diff --git a/Lib/cdata.i b/Lib/cdata.i index 67601f737..b970b1d5d 100644 --- a/Lib/cdata.i +++ b/Lib/cdata.i @@ -79,5 +79,6 @@ SWIGCDATA cdata_##NAME(TYPE *ptr, int nelements); %cdata(void); -/* Memory move function */ +/* Memory move function. Due to multi-argument typemaps this appears to be wrapped as +void memmove(void *data, const char *s); */ void memmove(void *data, const void *indata, int inlen); diff --git a/Lib/lua/luarun.swg b/Lib/lua/luarun.swg index 32e1b1617..9bb45d577 100644 --- a/Lib/lua/luarun.swg +++ b/Lib/lua/luarun.swg @@ -79,7 +79,7 @@ typedef struct { /* this is the struct for wrapping arbitary packed binary data (currently it is only used for member function pointers) the data ordering is similar to swig_lua_userdata, but it is currently not possible -to tell the two structures apart within Swig, other than by looking at the type +to tell the two structures apart within SWIG, other than by looking at the type */ typedef struct { swig_type_info *type; diff --git a/Lib/octave/octrun.swg b/Lib/octave/octrun.swg index a2bf52070..be2dc9653 100644 --- a/Lib/octave/octrun.swg +++ b/Lib/octave/octrun.swg @@ -1,24 +1,16 @@ -#if OCTAVE_API_VERSION_OPTION>0 -#define USE_OCTAVE_API_VERSION OCTAVE_API_VERSION_OPTION -#else - #include -#ifdef OCTAVE_API_VERSION_N -#define USE_OCTAVE_API_VERSION OCTAVE_API_VERSION_N +#ifndef OCTAVE_API_VERSION_NUMBER -#else // Interim hack to distinguish between Octave 3.2 and earlier versions. - -#define ComplexLU __ignore -#include -#undef ComplexLU -#ifdef octave_Complex_LU_h -#define USE_OCTAVE_API_VERSION 36 -#else -#define USE_OCTAVE_API_VERSION 37 -#endif - -#endif + // Hack to distinguish between Octave 3.2 and earlier versions before OCTAVE_API_VERSION_NUMBER existed + #define ComplexLU __ignore + #include + #undef ComplexLU + #ifdef octave_Complex_LU_h + # define OCTAVE_API_VERSION_NUMBER 36 + #else + # define OCTAVE_API_VERSION_NUMBER 37 + #endif #endif @@ -469,7 +461,7 @@ namespace Swig { install_builtin_function(it->second.first->method, it->first, it->second.first->doc?it->second.first->doc:std::string()); else if (it->second.second.is_defined()) { -#if USE_OCTAVE_API_VERSION<37 +#if OCTAVE_API_VERSION_NUMBER<37 link_to_global_variable(curr_sym_tab->lookup(it->first, true)); #else symbol_table::varref(it->first); @@ -477,7 +469,7 @@ namespace Swig { #endif set_global_value(it->first, it->second.second); -#if USE_OCTAVE_API_VERSION<37 +#if OCTAVE_API_VERSION_NUMBER<37 octave_swig_type *ost = Swig::swig_value_deref(it->second.second); if (ost) { const char* h = ost->help_text(); @@ -1389,7 +1381,7 @@ SWIGRUNTIME swig_module_info *SWIG_Octave_GetModule(void *clientdata) { SWIGRUNTIME void SWIG_Octave_SetModule(void *clientdata, swig_module_info *pointer) { octave_value ov = new octave_swig_packed(0, &pointer, sizeof(swig_module_info *)); const char *module_var = "__SWIG_MODULE__" SWIG_TYPE_TABLE_NAME SWIG_RUNTIME_VERSION; -#if USE_OCTAVE_API_VERSION<37 +#if OCTAVE_API_VERSION_NUMBER<37 link_to_global_variable(curr_sym_tab->lookup(module_var, true)); #else symbol_table::varref(module_var); diff --git a/Lib/octave/octruntime.swg b/Lib/octave/octruntime.swg index 0ab7bd70b..e19b781c2 100644 --- a/Lib/octave/octruntime.swg +++ b/Lib/octave/octruntime.swg @@ -72,7 +72,7 @@ DEFUN_DLD (SWIG_name,args,nargout,SWIG_name_d) { module_ns->install_global(); module_ns->decref(); -#if USE_OCTAVE_API_VERSION<37 +#if OCTAVE_API_VERSION_NUMBER<37 link_to_global_variable(curr_sym_tab->lookup(SWIG_name_d,true)); #else symbol_table::varref(SWIG_name_d); @@ -80,7 +80,7 @@ DEFUN_DLD (SWIG_name,args,nargout,SWIG_name_d) { #endif set_global_value(SWIG_name_d,Swig::swig_value_ref(module_ns)); -#if USE_OCTAVE_API_VERSION>=37 +#if OCTAVE_API_VERSION_NUMBER>=37 mlock(); #endif @@ -89,7 +89,7 @@ DEFUN_DLD (SWIG_name,args,nargout,SWIG_name_d) { // workaround bug in octave where installing global variable of custom type and then // exiting without explicitly clearing the variable causes octave to segfault. -#if USE_OCTAVE_API_VERSION>=37 +#if OCTAVE_API_VERSION_NUMBER>=37 struct oct_file_unload { ~oct_file_unload() { string_vector vars = symbol_table::global_variable_names(); diff --git a/Lib/perl5/perlrun.swg b/Lib/perl5/perlrun.swg index be788f540..ecb1f5cd2 100644 --- a/Lib/perl5/perlrun.swg +++ b/Lib/perl5/perlrun.swg @@ -293,7 +293,7 @@ SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_ int newmemory = 0; *ptr = SWIG_TypeCast(tc,voidptr,&newmemory); if (newmemory == SWIG_CAST_NEW_MEMORY) { - assert(own); + 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; } @@ -311,7 +311,7 @@ SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_ */ SV *obj = sv; HV *stash = SvSTASH(SvRV(obj)); - GV *gv = *(GV**) hv_fetch(stash, "OWNER", 5, TRUE); + GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE); if (isGV(gv)) { HV *hv = GvHVn(gv); /* @@ -342,7 +342,7 @@ SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, i stash=SvSTASH(SvRV(obj)); if (flags & SWIG_POINTER_OWN) { HV *hv; - GV *gv=*(GV**)hv_fetch(stash, "OWNER", 5, TRUE); + GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE); if (!isGV(gv)) gv_init(gv, stash, "OWNER", 5, FALSE); hv=GvHVn(gv); diff --git a/Lib/php/const.i b/Lib/php/const.i index 6ddd403d0..d2d1c75bd 100644 --- a/Lib/php/const.i +++ b/Lib/php/const.i @@ -51,3 +51,6 @@ c.module_number = module_number; zend_register_constant( &c TSRMLS_CC ); } + +/* Handled as a global variable. */ +%typemap(consttab) SWIGTYPE (CLASS::*) ""; diff --git a/Lib/php/director.swg b/Lib/php/director.swg index 6a9d4df3c..b28f6dbd9 100644 --- a/Lib/php/director.swg +++ b/Lib/php/director.swg @@ -168,7 +168,7 @@ namespace Swig { { public: DirectorPureVirtualException(const char* msg) - : DirectorException(E_ERROR, "Swig director pure virtual method called", msg) + : DirectorException(E_ERROR, "SWIG director pure virtual method called", msg) { } @@ -182,7 +182,7 @@ namespace Swig { { public: DirectorMethodException(const char* msg = "") - : DirectorException(E_ERROR, "Swig director method error", msg) + : DirectorException(E_ERROR, "SWIG director method error", msg) { } diff --git a/Lib/php/globalvar.i b/Lib/php/globalvar.i index df8cfade7..be20a96bc 100644 --- a/Lib/php/globalvar.i +++ b/Lib/php/globalvar.i @@ -105,6 +105,16 @@ zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&z_var, sizeof(zval *), NULL); } +%typemap(varinit) SWIGTYPE (CLASS::*) +{ + void * p = emalloc(sizeof($1)); + memcpy(p, &$1, sizeof($1)); + zval * resource; + MAKE_STD_ZVAL(resource); + ZEND_REGISTER_RESOURCE(resource, p, le_member_ptr); + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&resource, sizeof(zval *), NULL); +} + %typemap(varin) int, unsigned int, short, unsigned short, long, unsigned long, signed char, unsigned char, enum SWIGTYPE { zval **z_var; @@ -216,6 +226,15 @@ $1 = ($1_ltype)_temp; } +%typemap(varin) SWIGTYPE (CLASS::*) +{ + zval **z_var; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + void * p = (void*)zend_fetch_resource(*z_var TSRMLS_CC, -1, SWIG_MEMBER_PTR, NULL, 1, le_member_ptr); + memcpy(&$1, p, sizeof($1)); +} + %typemap(varout) int, unsigned int, unsigned short, @@ -328,4 +347,12 @@ deliberate error cos this code looks bogus to me SWIG_SetPointerZval(*z_var, (void*)$1, $1_descriptor, 0); } - +%typemap(varout) SWIGTYPE (CLASS::*) +{ + void * p = emalloc(sizeof($1)); + memcpy(p, &$1, sizeof($1)); + zval * resource; + MAKE_STD_ZVAL(resource); + ZEND_REGISTER_RESOURCE(resource, p, le_member_ptr); + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&resource, sizeof(zval *), NULL); +} diff --git a/Lib/php/php.swg b/Lib/php/php.swg index a604b035b..77985e3c5 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -55,6 +55,10 @@ %pass_by_val(long, CONVERT_INT_IN); %pass_by_val(unsigned long, CONVERT_INT_IN); +%pass_by_val(signed long long, CONVERT_LONG_LONG_IN); +%pass_by_val(long long, CONVERT_LONG_LONG_IN); +%pass_by_val(unsigned long long, CONVERT_UNSIGNED_LONG_LONG_IN); + %pass_by_val(signed char, CONVERT_INT_IN); %pass_by_val(char, CONVERT_CHAR_IN); %pass_by_val(unsigned char, CONVERT_INT_IN); @@ -194,6 +198,29 @@ ZVAL_LONG(return_value,$1); } +%typemap(out) long long +%{ + if ((long long)LONG_MIN <= $1 && $1 <= (long long)LONG_MAX) { + return_value->value.lval = (long)($1); + return_value->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%lld", $1); + ZVAL_STRING(return_value, temp, 1); + } +%} +%typemap(out) unsigned long long +%{ + if ($1 <= (unsigned long long)LONG_MAX) { + return_value->value.lval = (long)($1); + return_value->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%llu", $1); + ZVAL_STRING(return_value, temp, 1); + } +%} + %typemap(out) const int &, const unsigned int &, const short &, @@ -209,6 +236,29 @@ ZVAL_LONG(return_value,*$1); } +%typemap(out) const long long & +%{ + if ((long long)LONG_MIN <= *$1 && *$1 <= (long long)LONG_MAX) { + return_value->value.lval = (long)(*$1); + return_value->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%lld", *$1); + ZVAL_STRING(return_value, temp, 1); + } +%} +%typemap(out) const unsigned long long & +%{ + if (*$1 <= (unsigned long long)LONG_MAX) { + return_value->value.lval = (long)(*$1); + return_value->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%llu", *$1); + ZVAL_STRING(return_value, temp, 1); + } +%} + %typemap(directorin) int, unsigned int, short, @@ -304,6 +354,23 @@ SWIG_SetPointerZval($input, (void *)&$1_name, $1_descriptor, $owner); %} +%typemap(out) SWIGTYPE (CLASS::*) +{ + void * p = emalloc(sizeof($1)); + memcpy(p, &$1, sizeof($1)); + zval * resource; + MAKE_STD_ZVAL(resource); + ZEND_REGISTER_RESOURCE(resource, p, le_member_ptr); + + SWIG_SetPointerZval(return_value, (void *)&$1, $1_descriptor, $owner); +} + +%typemap(in) SWIGTYPE (CLASS::*) +{ + void * p = (void*)zend_fetch_resource($input TSRMLS_CC, -1, SWIG_MEMBER_PTR, NULL, 1, le_member_ptr); + memcpy(&$1, p, sizeof($1)); +} + %typemap(out) SWIGTYPE *DYNAMIC, SWIGTYPE &DYNAMIC { @@ -357,6 +424,8 @@ %php_typecheck(unsigned short,SWIG_TYPECHECK_UINT16,IS_LONG) %php_typecheck(long,SWIG_TYPECHECK_INT64,IS_LONG) %php_typecheck(unsigned long,SWIG_TYPECHECK_UINT64,IS_LONG) +%php_typecheck(long long,SWIG_TYPECHECK_INT64,IS_LONG) +%php_typecheck(unsigned long long,SWIG_TYPECHECK_UINT64,IS_LONG) %php_typecheck(signed char,SWIG_TYPECHECK_INT8,IS_LONG) %php_typecheck(unsigned char,SWIG_TYPECHECK_UINT8,IS_LONG) %php_typecheck(size_t,SWIG_TYPECHECK_INT16,IS_LONG) diff --git a/Lib/php/phpinit.swg b/Lib/php/phpinit.swg index b7a0fc9d4..5d8278ba4 100644 --- a/Lib/php/phpinit.swg +++ b/Lib/php/phpinit.swg @@ -8,5 +8,6 @@ %init %{ SWIG_php_minit { SWIG_InitializeModule(0); + le_member_ptr = zend_register_list_destructors_ex(member_ptr_dtor, NULL, SWIG_MEMBER_PTR, module_number); %} diff --git a/Lib/php/phpkw.swg b/Lib/php/phpkw.swg index a5f410bc5..5e60583cb 100644 --- a/Lib/php/phpkw.swg +++ b/Lib/php/phpkw.swg @@ -5,13 +5,13 @@ * phpkw.swg * ----------------------------------------------------------------------------- */ -#define PHPKW(x) %keywordwarn("'" `x` "' is a PHP keyword, renamed as 'c_" `x` "'",sourcefmt="%(lower)s",$isclass,rename="c_%s") `x` +#define PHPKW(x) %keywordwarn("'" `x` "' is a PHP keyword, renamed as 'c_" `x` "'",sourcefmt="%(lower)s",rename="c_%s") `x` -#define PHPCN(x) %keywordwarn("'" `x` "' is a PHP reserved class name, class renamed as 'c_" `x` "'",%$isclass,rename="c_%s") `x` +#define PHPCN(x) %keywordwarn("'" `x` "' is a PHP reserved class name, class renamed as 'c_" `x` "'",%$isclass,sourcefmt="%(lower)s",rename="c_%s") `x` -#define PHPBN1(x) %builtinwarn("'" `x` "' conflicts with a built-in name in PHP",sourcefmt="%(lower)s") `x` -#define PHPBN2(x) %builtinwarn("'" `x` "' conflicts with a built-in name in PHP") "::" `x` -#define PHPFN(x) %keywordwarn("'" `x` "' is a PHP built-in function, renamed as 'c_" `x` "'",sourcefmt="%(lower)s",%$isfunction,%$not %$ismember,rename="c_%s") `x` +#define PHPBN1(x) %builtinwarn("'" `x` "' conflicts with a built-in name in PHP",sourcefmt="%(lower)s") `x` +#define PHPBN2(x) %builtinwarn("'" `x` "' conflicts with a built-in name in PHP") "::" `x` +#define PHPFN(x) %keywordwarn("'" `x` "' is a PHP built-in function, renamed as 'c_" `x` "'",sourcefmt="%(lower)s",%$isfunction,%$not %$ismember,rename="c_%s") `x` /* From @@ -355,105 +355,105 @@ PHPBN2(E_STRICT); PHPBN2(__COMPILER_HALT_OFFSET__); /* Class names reserved by PHP */ -PHPCN(stdClass); -PHPCN(__PHP_Incomplete_Class); -PHPCN(Directory); - +/* case insensitive */ +PHPCN(stdclass); +PHPCN(__php_incomplete_class); +PHPCN(directory); /* Added in PHP5 (this list apparently depends which extensions you load by default). */ PHPCN(parent); PHPCN(self); -PHPCN(Exception); +PHPCN(exception); PHPCN(php_user_filter); -PHPCN(ErrorException); -PHPCN(XMLWriter); -PHPCN(LibXMLError); -PHPCN(SimpleXMLElement); -PHPCN(SoapClient); -PHPCN(SoapVar); -PHPCN(SoapServer); -PHPCN(SoapFault); -PHPCN(SoapParam); -PHPCN(SoapHeader); -PHPCN(RecursiveIteratorIterator); -PHPCN(FilterIterator); -PHPCN(RecursiveFilterIterator); -PHPCN(ParentIterator); -PHPCN(LimitIterator); -PHPCN(CachingIterator); -PHPCN(RecursiveCachingIterator); -PHPCN(IteratorIterator); -PHPCN(NoRewindIterator); -PHPCN(AppendIterator); -PHPCN(InfiniteIterator); -PHPCN(EmptyIterator); -PHPCN(ArrayObject); -PHPCN(ArrayIterator); -PHPCN(RecursiveArrayIterator); -PHPCN(SplFileInfo); -PHPCN(DirectoryIterator); -PHPCN(RecursiveDirectoryIterator); -PHPCN(SplFileObject); -PHPCN(SplTempFileObject); -PHPCN(SimpleXMLIterator); -PHPCN(LogicException); -PHPCN(BadFunctionCallException); -PHPCN(BadMethodCallException); -PHPCN(DomainException); -PHPCN(InvalidArgumentException); -PHPCN(LengthException); -PHPCN(OutOfRangeException); -PHPCN(RuntimeException); -PHPCN(OutOfBoundsException); -PHPCN(OverflowException); -PHPCN(RangeException); -PHPCN(UnderflowException); -PHPCN(UnexpectedValueException); -PHPCN(SplObjectStorage); -PHPCN(ReflectionException); -PHPCN(Reflection); -PHPCN(ReflectionFunction); -PHPCN(ReflectionParameter); -PHPCN(ReflectionMethod); -PHPCN(ReflectionClass); -PHPCN(ReflectionObject); -PHPCN(ReflectionProperty); -PHPCN(ReflectionExtension); -PHPCN(DOMException); -PHPCN(DOMStringList); -PHPCN(DOMNameList); -PHPCN(DOMImplementationList); -PHPCN(DOMImplementationSource); -PHPCN(DOMImplementation); -PHPCN(DOMNode); -PHPCN(DOMNameSpaceNode); -PHPCN(DOMDocumentFragment); -PHPCN(DOMDocument); -PHPCN(DOMNodeList); -PHPCN(DOMNamedNodeMap); -PHPCN(DOMCharacterData); -PHPCN(DOMAttr); -PHPCN(DOMElement); -PHPCN(DOMText); -PHPCN(DOMComment); -PHPCN(DOMTypeinfo); -PHPCN(DOMUserDataHandler); -PHPCN(DOMDomError); -PHPCN(DOMErrorHandler); -PHPCN(DOMLocator); -PHPCN(DOMConfiguration); -PHPCN(DOMCdataSection); -PHPCN(DOMDocumentType); -PHPCN(DOMNotation); -PHPCN(DOMEntity); -PHPCN(DOMEntityReference); -PHPCN(DOMProcessingInstruction); -PHPCN(DOMStringExtend); -PHPCN(DOMXPath); -PHPCN(XMLReader); -PHPCN(SQLiteDatabase); -PHPCN(SQLiteResult); -PHPCN(SQLiteUnbuffered); -PHPCN(SQLiteException); +PHPCN(errorexception); +PHPCN(xmlwriter); +PHPCN(libxmlerror); +PHPCN(simplexmlelement); +PHPCN(soapclient); +PHPCN(soapvar); +PHPCN(soapserver); +PHPCN(soapfault); +PHPCN(soapparam); +PHPCN(soapheader); +PHPCN(recursiveiteratoriterator); +PHPCN(filteriterator); +PHPCN(recursivefilteriterator); +PHPCN(parentiterator); +PHPCN(limititerator); +PHPCN(cachingiterator); +PHPCN(recursivecachingiterator); +PHPCN(iteratoriterator); +PHPCN(norewinditerator); +PHPCN(appenditerator); +PHPCN(infiniteiterator); +PHPCN(emptyiterator); +PHPCN(arrayobject); +PHPCN(arrayiterator); +PHPCN(recursivearrayiterator); +PHPCN(splfileinfo); +PHPCN(directoryiterator); +PHPCN(recursivedirectoryiterator); +PHPCN(splfileobject); +PHPCN(spltempfileobject); +PHPCN(simplexmliterator); +PHPCN(logicexception); +PHPCN(badfunctioncallexception); +PHPCN(badmethodcallexception); +PHPCN(domainexception); +PHPCN(invalidargumentexception); +PHPCN(lengthexception); +PHPCN(outofrangeexception); +PHPCN(runtimeexception); +PHPCN(outofboundsexception); +PHPCN(overflowexception); +PHPCN(rangeexception); +PHPCN(underflowexception); +PHPCN(unexpectedvalueexception); +PHPCN(splobjectstorage); +PHPCN(reflectionexception); +PHPCN(reflection); +PHPCN(reflectionfunction); +PHPCN(reflectionparameter); +PHPCN(reflectionmethod); +PHPCN(reflectionclass); +PHPCN(reflectionobject); +PHPCN(reflectionproperty); +PHPCN(reflectionextension); +PHPCN(domexception); +PHPCN(domstringlist); +PHPCN(domnamelist); +PHPCN(domimplementationlist); +PHPCN(domimplementationsource); +PHPCN(domimplementation); +PHPCN(domnode); +PHPCN(domnamespacenode); +PHPCN(domdocumentfragment); +PHPCN(domdocument); +PHPCN(domnodelist); +PHPCN(domnamednodemap); +PHPCN(domcharacterdata); +PHPCN(domattr); +PHPCN(domelement); +PHPCN(domtext); +PHPCN(domcomment); +PHPCN(domtypeinfo); +PHPCN(domuserdatahandler); +PHPCN(domdomerror); +PHPCN(domerrorhandler); +PHPCN(domlocator); +PHPCN(domconfiguration); +PHPCN(domcdatasection); +PHPCN(domdocumenttype); +PHPCN(domnotation); +PHPCN(domentity); +PHPCN(domentityreference); +PHPCN(domprocessinginstruction); +PHPCN(domstringextend); +PHPCN(domxpath); +PHPCN(xmlreader); +PHPCN(sqlitedatabase); +PHPCN(sqliteresult); +PHPCN(sqliteunbuffered); +PHPCN(sqliteexception); /* Built-in PHP functions (incomplete). */ PHPFN(cos); diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index f48748914..3aff867b4 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -36,7 +36,7 @@ extern "C" { #define SWIG_LONG_CONSTANT(N, V) zend_register_long_constant((char*)#N, sizeof(#N), V, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) #define SWIG_DOUBLE_CONSTANT(N, V) zend_register_double_constant((char*)#N, sizeof(#N), V, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) -#define SWIG_STRING_CONSTANT(N, V) zend_register_stringl_constant((char*)#N, sizeof(#N), V, strlen(V), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) +#define SWIG_STRING_CONSTANT(N, V) zend_register_stringl_constant((char*)#N, sizeof(#N), (char*)(V), strlen(V), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) #define SWIG_CHAR_CONSTANT(N, V) do {\ static char swig_char = (V);\ zend_register_stringl_constant((char*)#N, sizeof(#N), &swig_char, 1, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);\ @@ -261,3 +261,12 @@ static void SWIG_Php_SetModule(swig_module_info *pointer) { TSRMLS_FETCH(); REGISTER_MAIN_LONG_CONSTANT(const_name, (long) pointer, 0); } + +#define SWIG_MEMBER_PTR ((char*)"CLASS::*") + +static void member_ptr_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) { + efree(rsrc->ptr); +} + +static int le_member_ptr; + diff --git a/Lib/php/std_map.i b/Lib/php/std_map.i index c6721806b..2c9e1fd9a 100644 --- a/Lib/php/std_map.i +++ b/Lib/php/std_map.i @@ -30,8 +30,6 @@ namespace std { map(const map &); unsigned int size() const; - %rename(is_empty) empty; - bool empty() const; void clear(); %extend { T& get(const K& key) throw (std::out_of_range) { @@ -55,6 +53,9 @@ namespace std { std::map::iterator i = self->find(key); return i != self->end(); } + bool is_empty() const { + return self->empty(); + } } }; @@ -70,8 +71,6 @@ namespace std { map(const map &); unsigned int size() const; - %rename(is_empty) empty; - bool empty() const; void clear(); %extend { T& get(K key) throw (std::out_of_range) { @@ -95,6 +94,9 @@ namespace std { std::map::iterator i = self->find(key); return i != self->end(); } + bool is_empty() const { + return self->empty(); + } } }; %enddef @@ -107,8 +109,6 @@ namespace std { map(const map &); unsigned int size() const; - %rename(is_empty) empty; - bool empty() const; void clear(); %extend { T get(const K& key) throw (std::out_of_range) { @@ -132,6 +132,9 @@ namespace std { std::map::iterator i = self->find(key); return i != self->end(); } + bool is_empty() const { + return self->empty(); + } } }; %enddef @@ -145,8 +148,6 @@ namespace std { map(const map &); unsigned int size() const; - %rename(is_empty) empty; - bool empty() const; void clear(); %extend { T get(K key) throw (std::out_of_range) { @@ -170,6 +171,9 @@ namespace std { std::map::iterator i = self->find(key); return i != self->end(); } + bool is_empty() const { + return self->empty(); + } } }; %enddef diff --git a/Lib/php/typemaps.i b/Lib/php/typemaps.i index 7af301d0d..cc2341b19 100644 --- a/Lib/php/typemaps.i +++ b/Lib/php/typemaps.i @@ -112,9 +112,7 @@ int_typemap(long long); } %typemap(in) TYPE *REFERENCE (long long lvalue) %{ - // FIXME won't work for values which don't fit in a long... - convert_to_long_ex($input); - lvalue = (long long) (*$input)->value.lval; + CONVERT_LONG_LONG_IN(lvalue, long long, $input) $1 = &lvalue; %} %typemap(argout) long long *REFERENCE @@ -128,6 +126,17 @@ int_typemap(long long); ZVAL_STRING((*$arg), temp, 1); } %} +%typemap(argout) long long &OUTPUT +%{ + if ((long long)LONG_MIN <= *arg$argnum && *arg$argnum <= (long long)LONG_MAX) { + ($result)->value.lval = (long)(*arg$argnum); + ($result)->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%lld", *arg$argnum); + ZVAL_STRING($result, temp, 1); + } +%} int_typemap(unsigned long long); %typemap(argout,fragment="t_output_helper") unsigned long long *OUTPUT { @@ -144,9 +153,7 @@ int_typemap(unsigned long long); } %typemap(in) TYPE *REFERENCE (unsigned long long lvalue) %{ - // FIXME won't work for values which don't fit in a long... - convert_to_long_ex($input); - lvalue = (unsigned long long) (*$input)->value.lval; + CONVERT_UNSIGNED_LONG_LONG_IN(lvalue, unsigned long long, $input) $1 = &lvalue; %} %typemap(argout) unsigned long long *REFERENCE @@ -160,6 +167,17 @@ int_typemap(unsigned long long); ZVAL_STRING((*$arg), temp, 1); } %} +%typemap(argout) unsigned long long &OUTPUT +%{ + if (*arg$argnum <= (unsigned long long)LONG_MAX) { + ($result)->value.lval = (long)(*arg$argnum); + ($result)->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%llu", *arg$argnum); + ZVAL_STRING($result, temp, 1); + } +%} %typemap(in) float *INOUT = float *INPUT; %typemap(in) double *INOUT = double *INPUT; @@ -181,11 +199,13 @@ int_typemap(unsigned long long); %typemap(in) short &INOUT = short *INPUT; %typemap(in) long &INOUT = long *INPUT; %typemap(in) long long &INOUT = long long *INPUT; +%typemap(in) long long &INPUT = long long *INPUT; %typemap(in) unsigned &INOUT = unsigned *INPUT; %typemap(in) unsigned short &INOUT = unsigned short *INPUT; %typemap(in) unsigned long &INOUT = unsigned long *INPUT; %typemap(in) unsigned char &INOUT = unsigned char *INPUT; %typemap(in) unsigned long long &INOUT = unsigned long long *INPUT; +%typemap(in) unsigned long long &INPUT = unsigned long long *INPUT; %typemap(argout) float *INOUT = float *OUTPUT; %typemap(argout) double *INOUT= double *OUTPUT; diff --git a/Lib/php/utils.i b/Lib/php/utils.i index 166941585..07ac96900 100644 --- a/Lib/php/utils.i +++ b/Lib/php/utils.i @@ -9,6 +9,42 @@ lvar = (t) Z_LVAL_PP(invar); %enddef +%define CONVERT_LONG_LONG_IN(lvar,t,invar) + switch ((*(invar))->type) { + case IS_DOUBLE: + lvar = (t) (*(invar))->value.dval; + break; + case IS_STRING: { + char * endptr; + errno = 0; + lvar = (t) strtoll((*(invar))->value.str.val, &endptr, 10); + if (*endptr && !errno) break; + /* FALL THRU */ + } + default: + convert_to_long_ex(invar); + lvar = (t) (*(invar))->value.lval; + } +%enddef + +%define CONVERT_UNSIGNED_LONG_LONG_IN(lvar,t,invar) + switch ((*(invar))->type) { + case IS_DOUBLE: + lvar = (t) (*(invar))->value.dval; + break; + case IS_STRING: { + char * endptr; + errno = 0; + lvar = (t) strtoull((*(invar))->value.str.val, &endptr, 10); + if (*endptr && !errno) break; + /* FALL THRU */ + } + default: + convert_to_long_ex(invar); + lvar = (t) (*(invar))->value.lval; + } +%enddef + %define CONVERT_INT_OUT(lvar,invar) lvar = (t) Z_LVAL_PP(invar); %enddef diff --git a/Lib/python/director.swg b/Lib/python/director.swg index ba9144539..f3855babe 100644 --- a/Lib/python/director.swg +++ b/Lib/python/director.swg @@ -237,7 +237,7 @@ namespace Swig { try { throw; } catch (DirectorException& e) { - std::cerr << "Swig Director exception caught:" << std::endl + std::cerr << "SWIG Director exception caught:" << std::endl << e.getMessage() << std::endl; } catch (std::exception& e) { std::cerr << "std::exception caught: "<< e.what() << std::endl; @@ -276,12 +276,12 @@ namespace Swig { class DirectorTypeMismatchException : public Swig::DirectorException { public: DirectorTypeMismatchException(PyObject *error, const char* msg="") - : Swig::DirectorException(error, "Swig director type mismatch", msg) + : Swig::DirectorException(error, "SWIG director type mismatch", msg) { } DirectorTypeMismatchException(const char* msg="") - : Swig::DirectorException(PyExc_TypeError, "Swig director type mismatch", msg) + : Swig::DirectorException(PyExc_TypeError, "SWIG director type mismatch", msg) { } @@ -300,7 +300,7 @@ namespace Swig { class DirectorMethodException : public Swig::DirectorException { public: DirectorMethodException(const char* msg = "") - : DirectorException(PyExc_RuntimeError, "Swig director method error.", msg) + : DirectorException(PyExc_RuntimeError, "SWIG director method error.", msg) { } @@ -315,7 +315,7 @@ namespace Swig { { public: DirectorPureVirtualException(const char* msg = "") - : DirectorException(PyExc_RuntimeError, "Swig director pure virtual method called", msg) + : DirectorException(PyExc_RuntimeError, "SWIG director pure virtual method called", msg) { } diff --git a/Lib/python/pyinit.swg b/Lib/python/pyinit.swg index 058934b04..5af8d2491 100644 --- a/Lib/python/pyinit.swg +++ b/Lib/python/pyinit.swg @@ -279,15 +279,15 @@ SWIG_Python_FixMethods(PyMethodDef *methods, } } if (ci) { - size_t shift = (ci->ptype) - types; - swig_type_info *ty = types_initial[shift]; - size_t ldoc = (c - methods[i].ml_doc); - size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; - char *ndoc = (char*)malloc(ldoc + lptr + 10); - if (ndoc) { - char *buff = ndoc; - void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; - if (ptr) { + void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; + if (ptr) { + size_t shift = (ci->ptype) - types; + swig_type_info *ty = types_initial[shift]; + size_t ldoc = (c - methods[i].ml_doc); + size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; + char *ndoc = (char*)malloc(ldoc + lptr + 10); + if (ndoc) { + char *buff = ndoc; strncpy(buff, methods[i].ml_doc, ldoc); buff += ldoc; strncpy(buff, "swig_ptr: ", 10); diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 21fddb610..c0d30ee45 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -1089,7 +1089,7 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int int newmemory = 0; *ptr = SWIG_TypeCast(tc,vptr,&newmemory); if (newmemory == SWIG_CAST_NEW_MEMORY) { - assert(own); + 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; } diff --git a/Lib/r/r.swg b/Lib/r/r.swg index 7fd6d761f..b70d80581 100644 --- a/Lib/r/r.swg +++ b/Lib/r/r.swg @@ -50,7 +50,7 @@ SWIG_InitializeModule(0); %typemap(scheck) SWIGTYPE[ANY] %{ # assert(length($input) > $1_dim0) - assert(all(sapply($input, class) == "$R_class")) + assert(all(sapply($input, class) == "$R_class")); %} %typemap(out) void ""; @@ -122,14 +122,14 @@ SWIG_InitializeModule(0); /* Handling vector case to avoid warnings, although we just use the first one. */ %typemap(scheck) unsigned int %{ - assert(length($input) == 1 && $input >= 0, "All values must be non-negative") + assert(length($input) == 1 && $input >= 0, "All values must be non-negative"); %} %typemap(scheck) int, long %{ if(length($input) > 1) { - warning("using only the first element of $input") - } + warning("using only the first element of $input"); + }; %} diff --git a/Lib/r/rtype.swg b/Lib/r/rtype.swg index d388d1eae..ee01d07d7 100644 --- a/Lib/r/rtype.swg +++ b/Lib/r/rtype.swg @@ -60,11 +60,11 @@ %typemap(scoercein) std::string, std::string *, std::string & %{ $input = as($input, "character"); %} %typemap(scoercein) enum SWIGTYPE - %{ $input = enumToInteger($input, "$R_class") %} + %{ $input = enumToInteger($input, "$R_class"); %} %typemap(scoercein) enum SWIGTYPE & - %{ $input = enumToInteger($input, "$R_class") %} + %{ $input = enumToInteger($input, "$R_class"); %} %typemap(scoercein) enum SWIGTYPE * - %{ $input = enumToInteger($input, "$R_class") %} + %{ $input = enumToInteger($input, "$R_class"); %} %typemap(scoercein) SWIGTYPE, SWIGTYPE *, SWIGTYPE & @@ -84,14 +84,14 @@ %typemap(scoercein) SWIGTYPE[ANY] %{ if(is.list($input)) - assert(all(sapply($input, class) == "$R_class")) + assert(all(sapply($input, class) == "$R_class")); %} /* **************************************************************** */ %typemap(scoercein) bool, bool *, bool & - "$input = as.logical($input) "; + "$input = as.logical($input);"; %typemap(scoercein) int, int *, int &, @@ -100,30 +100,30 @@ long *, long &, long[ANY] - "$input = as.integer($input) "; + "$input = as.integer($input); "; %typemap(scoercein) char *, string, std::string, string &, std::string & -%{ $input = as($input, "character") %} +%{ $input = as($input, "character"); %} %typemap(scoerceout) enum SWIGTYPE - %{ $result = enumFromInteger($result, "$R_class") %} + %{ $result = enumFromInteger($result, "$R_class"); %} %typemap(scoerceout) enum SWIGTYPE & - %{ $result = enumFromInteger($result, "$R_class") %} + %{ $result = enumFromInteger($result, "$R_class"); %} %typemap(scoerceout) enum SWIGTYPE * - %{ $result = enumToInteger($result, "$R_class") %} + %{ $result = enumToInteger($result, "$R_class"); %} %typemap(scoerceout) SWIGTYPE - %{ class($result) <- "$&R_class" %} + %{ class($result) <- "$&R_class"; %} %typemap(scoerceout) SWIGTYPE & - %{ class($result) <- "$R_class" %} + %{ class($result) <- "$R_class"; %} %typemap(scoerceout) SWIGTYPE * - %{ class($result) <- "$R_class" %} + %{ class($result) <- "$R_class"; %} /* Override the SWIGTYPE * above. */ %typemap(scoerceout) char, diff --git a/Lib/r/std_map.i b/Lib/r/std_map.i new file mode 100644 index 000000000..56057514c --- /dev/null +++ b/Lib/r/std_map.i @@ -0,0 +1,5 @@ +%fragment("StdMapTraits","header") +%{ +%} + +%include diff --git a/Lib/r/std_pair.i b/Lib/r/std_pair.i index 3ac795704..e9803449e 100644 --- a/Lib/r/std_pair.i +++ b/Lib/r/std_pair.i @@ -1 +1,5 @@ -%include \ No newline at end of file +%fragment("StdPairTraits","header") +%{ +%} + +%include diff --git a/Lib/ruby/director.swg b/Lib/ruby/director.swg index 9a6371ad9..76969cadc 100644 --- a/Lib/ruby/director.swg +++ b/Lib/ruby/director.swg @@ -176,7 +176,7 @@ namespace Swig { try { throw; } catch (DirectorException& e) { - std::cerr << "Swig Director exception caught:" << std::endl + std::cerr << "SWIG Director exception caught:" << std::endl << e.getMessage() << std::endl; } catch (std::exception& e) { std::cerr << "std::exception caught: "<< e.what() << std::endl; @@ -212,12 +212,12 @@ namespace Swig { class DirectorTypeMismatchException : public Swig::DirectorException { public: DirectorTypeMismatchException(VALUE error, const char *msg="") - : Swig::DirectorException(error, "Swig director type mismatch", msg) + : Swig::DirectorException(error, "SWIG director type mismatch", msg) { } DirectorTypeMismatchException(const char *msg="") - : Swig::DirectorException(rb_eTypeError, "Swig director type mismatch", msg) + : Swig::DirectorException(rb_eTypeError, "SWIG director type mismatch", msg) { } @@ -238,7 +238,7 @@ namespace Swig { } DirectorMethodException(const char* msg = "") - : Swig::DirectorException(rb_eRuntimeError, "Swig director method error.", msg) { + : Swig::DirectorException(rb_eRuntimeError, "SWIG director method error.", msg) { } static void raise(VALUE error) @@ -252,7 +252,7 @@ namespace Swig { { public: DirectorPureVirtualException(const char* msg = "") - : DirectorException(rb_eRuntimeError, "Swig director pure virtual method called", msg) + : DirectorException(rb_eRuntimeError, "SWIG director pure virtual method called", msg) { } diff --git a/Lib/ruby/rubyhead.swg b/Lib/ruby/rubyhead.swg index 4b425dfd8..9960087c6 100644 --- a/Lib/ruby/rubyhead.swg +++ b/Lib/ruby/rubyhead.swg @@ -1,5 +1,14 @@ #include +/* Ruby 1.9.1 has a "memoisation optimisation" when compiling with GCC which + * breaks using rb_intern as an lvalue, as SWIG does. We work around this + * issue for now by disabling this. + * https://sourceforge.net/tracker/?func=detail&aid=2859614&group_id=1645&atid=101645 + */ +#ifdef rb_intern +# undef rb_intern +#endif + /* Remove global macros defined in Ruby's win32.h */ #ifdef write # undef write diff --git a/Lib/ruby/rubyrun.swg b/Lib/ruby/rubyrun.swg index 24d861d5a..177e395d0 100644 --- a/Lib/ruby/rubyrun.swg +++ b/Lib/ruby/rubyrun.swg @@ -45,7 +45,7 @@ /* Error manipulation */ #define SWIG_ErrorType(code) SWIG_Ruby_ErrorType(code) -#define SWIG_Error(code, msg) rb_raise(SWIG_Ruby_ErrorType(code), msg) +#define SWIG_Error(code, msg) rb_raise(SWIG_Ruby_ErrorType(code), "%s", msg) #define SWIG_fail goto fail diff --git a/Lib/std/_std_deque.i b/Lib/std/_std_deque.i index 026f373d6..3d68c385f 100644 --- a/Lib/std/_std_deque.i +++ b/Lib/std/_std_deque.i @@ -27,7 +27,7 @@ }; */ -%define %std_deque_methods(T) +%define %std_deque_methods_noempty(T) typedef T &reference; typedef const T& const_reference; @@ -41,7 +41,6 @@ unsigned int size() const; unsigned int max_size() const; void resize(unsigned int n, T c = T()); - bool empty() const; const_reference front(); const_reference back(); void push_front(const T& x); @@ -69,7 +68,7 @@ throw std::out_of_range("deque index out of range"); } void delitem(int i) throw (std::out_of_range) { - int size = int(self->size()); + int size = int(self->size()); if (i<0) i+= size; if (i>=0 && ierase(self->begin()+i); @@ -77,7 +76,7 @@ throw std::out_of_range("deque index out of range"); } } - std::deque getslice(int i, int j) { + std::deque getslice(int i, int j) { int size = int(self->size()); if (i<0) i = size+i; if (j<0) j = size+j; @@ -112,15 +111,27 @@ self->erase(self->begin()+i,self->begin()+j); } }; - %enddef +#ifdef SWIGPHP +%define %std_deque_methods(T) + %extend { + bool is_empty() const { + return self->empty(); + } + }; + %std_deque_methods_noempty(T) +%enddef +#else +%define %std_deque_methods(T) + bool empty() const; + %std_deque_methods_noempty(T) +%enddef +#endif + namespace std { template class deque { public: %std_deque_methods(T); }; } - - - diff --git a/Lib/std/std_vector.i b/Lib/std/std_vector.i index ab1435b31..b0bb714d4 100644 --- a/Lib/std/std_vector.i +++ b/Lib/std/std_vector.i @@ -134,6 +134,46 @@ namespace std { %std_vector_methods_val(vector); }; + // *** + // const pointer specialization + // *** + template + class vector { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef const _Tp * value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type reference; + typedef value_type const_reference; + typedef _Alloc allocator_type; + + %traits_swigtype(_Tp); + + %fragment(SWIG_Traits_frag(std::vector), "header", + fragment=SWIG_Traits_frag(_Tp), + fragment="StdVectorTraits") { + namespace swig { + template <> struct traits > { + typedef value_category category; + static const char* type_name() { + return "std::vector"; + } + }; + } + } + + %typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector); + +#ifdef %swig_vector_methods_val + // Add swig/language extra methods + %swig_vector_methods_val(std::vector); +#endif + + %std_vector_methods_val(vector); + }; + // *** // *** // bool specialization diff --git a/Lib/swig.swg b/Lib/swig.swg index c0ecad9dd..af7fa6a30 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -136,6 +136,11 @@ #define %nocallback %feature("callback","0") #define %clearcallback %feature("callback","") +/* the %nestedworkaround directive */ +#define %nestedworkaround %feature("nestedworkaround") +#define %nonestedworkaround %feature("nestedworkaround","0") +#define %clearnestedworkaround %feature("nestedworkaround","") + /* the %fastdispatch directive */ #define %fastdispatch %feature("fastdispatch") #define %nofastdispatch %feature("fastdispatch","0") diff --git a/Lib/tcl/typemaps.i b/Lib/tcl/typemaps.i index 7c9e04a8b..2a8f1064a 100644 --- a/Lib/tcl/typemaps.i +++ b/Lib/tcl/typemaps.i @@ -4,8 +4,8 @@ * * typemaps.i * - * Swig typemap library for Tcl8. This file contains various sorts - * of typemaps for modifying Swig's code generation. + * SWIG typemap library for Tcl8. This file contains various sorts + * of typemaps for modifying SWIG's code generation. * ----------------------------------------------------------------------------- */ #if !defined(SWIG_USE_OLD_TYPEMAPS) diff --git a/Lib/typemaps/cdata.swg b/Lib/typemaps/cdata.swg index 32b3f5a77..cab53d31e 100644 --- a/Lib/typemaps/cdata.swg +++ b/Lib/typemaps/cdata.swg @@ -21,7 +21,7 @@ typedef struct SWIGCDATA { %typemap(out,noblock=1,fragment="SWIG_FromCharPtrAndSize") SWIGCDATA { %set_output(SWIG_FromCharPtrAndSize($1.data,$1.len)); } -%typemap(in) (const void *indata, int inlen) = (char *STRING, int SIZE); +%typemap(in) (const void *indata, size_t inlen) = (char *STRING, size_t SIZE); /* ----------------------------------------------------------------------------- @@ -70,7 +70,8 @@ SWIGCDATA cdata_##NAME(TYPE *ptr, size_t nelements = 1); %cdata(void); -/* Memory move function */ +/* Memory move function. Due to multi-argument typemaps this appears to be wrapped as +void memmove(void *data, const char *s); */ void memmove(void *data, const void *indata, size_t inlen); diff --git a/Lib/typemaps/fragments.swg b/Lib/typemaps/fragments.swg index 6d3e20223..ef6a346cc 100644 --- a/Lib/typemaps/fragments.swg +++ b/Lib/typemaps/fragments.swg @@ -444,15 +444,15 @@ SWIG_AsVal_dec(Type)(SWIG_Object obj, Type *val) %define %ensure_fragment(Fragment) %fragment(`Fragment`,"header") { -%#error "Swig language implementation must provide the Fragment fragment" +%#error "SWIG language implementation must provide the Fragment fragment" } %enddef %define %ensure_type_fragments(Type) %fragment(SWIG_From_frag(Type),"header") { -%#error "Swig language implementation must provide a SWIG_From_frag(Type) fragment" +%#error "SWIG language implementation must provide a SWIG_From_frag(Type) fragment" } %fragment(SWIG_AsVal_frag(Type),"header") { -%#error "Swig language implementation must provide a SWIG_AsVal_frag(Type) fragment" +%#error "SWIG language implementation must provide a SWIG_AsVal_frag(Type) fragment" } %enddef diff --git a/Lib/typemaps/swigmacros.swg b/Lib/typemaps/swigmacros.swg index 928f4ec0c..e95e7af92 100644 --- a/Lib/typemaps/swigmacros.swg +++ b/Lib/typemaps/swigmacros.swg @@ -20,7 +20,7 @@ Casting Operations: ------------------- - Swig provides the following casting macros, which implement the + SWIG provides the following casting macros, which implement the corresponding C++ casting operations: %const_cast(a, Type) const_cast(a) @@ -173,7 +173,7 @@ nocppval #endif /* __cplusplus */ /* ----------------------------------------------------------------------------- - * Swig names and mangling + * SWIG names and mangling * ----------------------------------------------------------------------------- */ #define %mangle(Type...) #@Type @@ -210,7 +210,7 @@ nocppval %define %formacro_2(macro,...)%_formacro_2(macro, __VA_ARGS__, __fordone__)%enddef /* ----------------------------------------------------------------------------- - * Swig flags + * SWIG flags * ----------------------------------------------------------------------------- */ /* diff --git a/Makefile.in b/Makefile.in index e9405feca..fe77a5d69 100644 --- a/Makefile.in +++ b/Makefile.in @@ -391,7 +391,7 @@ maintainer-clean: clean-libfiles DISTCLEAN-DEAD = config.status config.log config.cache swig.spec Makefile mkmf.log libtool -distclean: distclean-objects clean-examples clean-gifplot distclean-test-suite clean-docs distclean-dead distclean-ccache +distclean: clean-docs distclean-objects clean-examples clean-gifplot distclean-test-suite distclean-dead distclean-ccache distclean-objects: distclean-source diff --git a/README b/README index e042db755..1e6ac87e7 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ SWIG (Simplified Wrapper and Interface Generator) -Version: 1.3.40 (in progress) +Version: 1.3.41 (in progress) Tagline: SWIG is a compiler that integrates C and C++ with languages including Perl, Python, Tcl, Ruby, PHP, Java, Ocaml, Lua, @@ -68,7 +68,7 @@ Major contributors include: Past contributors include: James Michael DuPont, Clark McGrew, Dustin Mitchell, Ian Cooke, Catalin Dumitrescu, Baran Kovuk, Oleg Tolmatcev, Tal Shalif, Lluis Padro, Chris Seatory, Igor Bely, Robin Dunn - (See CHANGES for a more complete list). + (See CHANGES and CHANGES.current for a more complete list). Portions also copyrighted by companies/corporations; Network Applied Communication Laboratory, Inc @@ -99,6 +99,10 @@ What's New? SWIG-1.3.40 summary: - SWIG now supports directors for PHP. - PHP support improved in general. +- Octave 3.2 support added. +- Various bug fixes/enhancements for Allegrocl, C#, Java, Octave, Perl, + Python, Ruby and Tcl. +- Other generic fixes and minor new features. SWIG-1.3.39 summary: - Some new small feature enhancements. @@ -376,8 +380,10 @@ well advised to read this. Release Notes ============= -Please see the CHANGES files for a detailed list of bug fixes and -new features. A summary of the changes is included in this README file. +Please see the CHANGES.current file for a detailed list of bug fixes and +new features for the current release. The CHANGES file contains bug fixes +and new features for older versions. A summary of the changes is included +in this README file. Windows Installation ==================== diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h index 9be41c60e..a71be786f 100644 --- a/Source/CParse/cparse.h +++ b/Source/CParse/cparse.h @@ -53,7 +53,7 @@ extern "C" { extern void Swig_cparse_replace_descriptor(String *s); extern void cparse_normalize_void(Node *); extern Parm *Swig_cparse_parm(String *s); - extern ParmList *Swig_cparse_parms(String *s); + extern ParmList *Swig_cparse_parms(String *s, Node *file_line_node); /* templ.c */ diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index 8734c7d0e..a98bfb47f 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -135,7 +135,7 @@ static void scanner_locator(String *loc) { break; Putc(c, fn); } - /* Printf(stderr,"location: %s:%d\n",cparse_file,cparse_line); */ + /* Swig_diagnostic(cparse_file, cparse_line, "Scanner_set_location\n"); */ Scanner_set_location(scan,cparse_file,cparse_line); Delete(fn); } @@ -257,7 +257,7 @@ void skip_decl(void) { * Lexical scanner. * ------------------------------------------------------------------------- */ -int yylook(void) { +static int yylook(void) { int tok = 0; @@ -410,6 +410,9 @@ int yylook(void) { case SWIG_TOKEN_FLOAT: return NUM_FLOAT; + case SWIG_TOKEN_BOOL: + return NUM_BOOL; + case SWIG_TOKEN_POUND: Scanner_skip_line(scan); yylval.id = Swig_copy_string(Char(Scanner_text(scan))); @@ -499,7 +502,7 @@ int yylex(void) { l = yylook(); - /* Printf(stdout, "%s:%d:::%d: '%s'\n", cparse_file, cparse_line, l, Scanner_text(scan)); */ + /* Swig_diagnostic(cparse_file, cparse_line, ":::%d: '%s'\n", l, Scanner_text(scan)); */ if (l == NONID) { last_id = 1; @@ -525,6 +528,7 @@ int yylex(void) { case NUM_UNSIGNED: case NUM_LONGLONG: case NUM_ULONGLONG: + case NUM_BOOL: if (l == NUM_INT) yylval.dtype.type = T_INT; if (l == NUM_FLOAT) @@ -539,6 +543,8 @@ int yylex(void) { yylval.dtype.type = T_LONGLONG; if (l == NUM_ULONGLONG) yylval.dtype.type = T_ULONGLONG; + if (l == NUM_BOOL) + yylval.dtype.type = T_BOOL; yylval.dtype.val = NewString(Scanner_text(scan)); yylval.dtype.bitfield = 0; yylval.dtype.throws = 0; diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 7c33e5459..dafecc96f 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -43,6 +43,7 @@ static Node *module_node = 0; static String *Classprefix = 0; static String *Namespaceprefix = 0; static int inclass = 0; +static int nested_template = 0; /* template class/function definition within a class */ static char *last_cpptype = 0; static int inherit_list = 0; static Parm *template_parameters = 0; @@ -272,6 +273,14 @@ static int add_only_one = 0; static void add_symbols(Node *n) { String *decl; String *wrn = 0; + + if (nested_template) { + if (!(n && Equal(nodeType(n), "template"))) { + return; + } + /* continue if template function, but not template class, declared within a class */ + } + if (inclass && n) { cparse_normalize_void(n); } @@ -535,6 +544,8 @@ static void add_symbols_copy(Node *n) { add_oldname = Getattr(n,"sym:name"); if ((add_oldname) || (Getattr(n,"sym:needs_symtab"))) { + int old_inclass = -1; + Node *old_current_class = 0; if (add_oldname) { DohIncref(add_oldname); /* Disable this, it prevents %rename to work with templates */ @@ -564,7 +575,9 @@ static void add_symbols_copy(Node *n) { Namespaceprefix = Swig_symbol_qualifiedscopename(0); } if (strcmp(cnodeType,"class") == 0) { + old_inclass = inclass; inclass = 1; + old_current_class = current_class; current_class = n; if (Strcmp(Getattr(n,"kind"),"class") == 0) { cplus_mode = CPLUS_PRIVATE; @@ -591,8 +604,8 @@ static void add_symbols_copy(Node *n) { add_oldname = 0; } if (strcmp(cnodeType,"class") == 0) { - inclass = 0; - current_class = 0; + inclass = old_inclass; + current_class = old_current_class; } } else { if (strcmp(cnodeType,"extend") == 0) { @@ -813,14 +826,8 @@ static List *make_inherit_list(String *clsname, List *names) { /* If the class name is qualified. We need to create or lookup namespace entries */ -static Symtab *get_global_scope() { - Symtab *symtab = Swig_symbol_current(); - Node *pn = parentNode(symtab); - while (pn) { - symtab = pn; - pn = parentNode(symtab); - if (!pn) break; - } +static Symtab *set_scope_to_global() { + Symtab *symtab = Swig_symbol_global_scope(); Swig_symbol_setscope(symtab); return symtab; } @@ -852,6 +859,12 @@ static String *remove_block(Node *kw, const String *inputcode) { static Node *nscope = 0; static Node *nscope_inner = 0; + +/* Remove the scope prefix from cname and return the base name without the prefix. + * The scopes specified in the prefix are found, or created in the current namespace. + * So ultimately the scope is changed to that required for the base name. + * For example AA::BB::CC as input returns CC and creates the namespace AA then inner + * namespace BB in the current scope. If no scope separator (::) in the input, then nothing happens! */ static String *resolve_node_scope(String *cname) { Symtab *gscope = 0; nscope = 0; @@ -865,11 +878,11 @@ static String *resolve_node_scope(String *cname) { String *nprefix = NewString(Char(prefix)+2); Delete(prefix); prefix= nprefix; - gscope = get_global_scope(); + gscope = set_scope_to_global(); } if (!prefix || (Len(prefix) == 0)) { /* Use the global scope, but we need to add a 'global' namespace. */ - if (!gscope) gscope = get_global_scope(); + if (!gscope) gscope = set_scope_to_global(); /* note that this namespace is not the "unnamed" one, and we don't use Setattr(nscope,"name", ""), because the unnamed namespace is private */ @@ -972,18 +985,16 @@ static String *resolve_node_scope(String *cname) { - - /* Structures for handling code fragments built for nested classes */ typedef struct Nested { String *code; /* Associated code fragment */ int line; /* line number where it starts */ - char *name; /* Name associated with this nested class */ - char *kind; /* Kind of class */ + const char *name; /* Name associated with this nested class */ + const char *kind; /* Kind of class */ int unnamed; /* unnamed class */ SwigType *type; /* Datatype associated with the name */ - struct Nested *next; /* Next code fragment in list */ + struct Nested *next; /* Next code fragment in list */ } Nested; /* Some internal variables for saving nested class information */ @@ -993,15 +1004,157 @@ static Nested *nested_list = 0; /* Add a function to the nested list */ static void add_nested(Nested *n) { - Nested *n1; - if (!nested_list) nested_list = n; - else { - n1 = nested_list; - while (n1->next) n1 = n1->next; + if (!nested_list) { + nested_list = n; + } else { + Nested *n1 = nested_list; + while (n1->next) + n1 = n1->next; n1->next = n; } } +/* ----------------------------------------------------------------------------- + * nested_new_struct() + * + * Nested struct handling for C code only creates a global struct from the nested struct. + * + * Nested structure. This is a sick "hack". If we encounter + * a nested structure, we're going to grab the text of its definition and + * feed it back into the scanner. In the meantime, we need to grab + * variable declaration information and generate the associated wrapper + * code later. Yikes! + * + * This really only works in a limited sense. Since we use the + * code attached to the nested class to generate both C code + * it can't have any SWIG directives in it. It also needs to be parsable + * by SWIG or this whole thing is going to puke. + * ----------------------------------------------------------------------------- */ + +static void nested_new_struct(const char *kind, String *struct_code, Node *cpp_opt_declarators) { + String *name; + String *decl; + + /* Create a new global struct declaration which is just a copy of the nested struct */ + Nested *nested = (Nested *) malloc(sizeof(Nested)); + Nested *n = nested; + + name = Getattr(cpp_opt_declarators, "name"); + decl = Getattr(cpp_opt_declarators, "decl"); + + n->code = NewStringEmpty(); + Printv(n->code, "typedef ", kind, " ", struct_code, " $classname_", name, ";\n", NIL); + n->name = Swig_copy_string(Char(name)); + n->line = cparse_start_line; + n->type = NewStringEmpty(); + n->kind = kind; + n->unnamed = 0; + SwigType_push(n->type, decl); + n->next = 0; + + /* Repeat for any multiple instances of the nested struct */ + { + Node *p = cpp_opt_declarators; + p = nextSibling(p); + while (p) { + Nested *nn = (Nested *) malloc(sizeof(Nested)); + + name = Getattr(p, "name"); + decl = Getattr(p, "decl"); + + nn->code = NewStringEmpty(); + Printv(nn->code, "typedef ", kind, " ", struct_code, " $classname_", name, ";\n", NIL); + nn->name = Swig_copy_string(Char(name)); + nn->line = cparse_start_line; + nn->type = NewStringEmpty(); + nn->kind = kind; + nn->unnamed = 0; + SwigType_push(nn->type, decl); + nn->next = 0; + n->next = nn; + n = nn; + p = nextSibling(p); + } + } + + add_nested(nested); +} + +/* ----------------------------------------------------------------------------- + * nested_forward_declaration() + * + * Nested struct handling for C++ code only. + * + * Treat the nested class/struct/union as a forward declaration until a proper + * nested class solution is implemented. + * ----------------------------------------------------------------------------- */ + +static Node *nested_forward_declaration(const char *storage, const char *kind, String *sname, const char *name, Node *cpp_opt_declarators) { + Node *nn = 0; + int warned = 0; + + if (sname) { + /* Add forward declaration of the nested type */ + Node *n = new_node("classforward"); + Setfile(n, cparse_file); + Setline(n, cparse_line); + Setattr(n, "kind", kind); + Setattr(n, "name", sname); + Setattr(n, "storage", storage); + Setattr(n, "sym:weak", "1"); + add_symbols(n); + nn = n; + } + + /* Add any variable instances. Also add in any further typedefs of the nested type. + Note that anonymous typedefs (eg typedef struct {...} a, b;) are treated as class forward declarations */ + if (cpp_opt_declarators) { + int storage_typedef = (storage && (strcmp(storage, "typedef") == 0)); + int variable_of_anonymous_type = !sname && !storage_typedef; + if (!variable_of_anonymous_type) { + int anonymous_typedef = !sname && (storage && (strcmp(storage, "typedef") == 0)); + Node *n = cpp_opt_declarators; + SwigType *type = NewString(name); + while (n) { + Setattr(n, "type", type); + Setattr(n, "storage", storage); + if (anonymous_typedef) { + Setattr(n, "nodeType", "classforward"); + Setattr(n, "sym:weak", "1"); + } + n = nextSibling(n); + } + Delete(type); + add_symbols(cpp_opt_declarators); + + if (nn) { + set_nextSibling(nn, cpp_opt_declarators); + } else { + nn = cpp_opt_declarators; + } + } + } + + if (nn && Equal(nodeType(nn), "classforward")) { + Node *n = nn; + if (GetFlag(n, "feature:nestedworkaround")) { + Swig_symbol_remove(n); + nn = 0; + warned = 1; + } else { + SWIG_WARN_NODE_BEGIN(n); + Swig_warning(WARN_PARSE_NAMED_NESTED_CLASS, cparse_file, cparse_line,"Nested %s not currently supported (%s ignored)\n", kind, sname ? sname : name); + SWIG_WARN_NODE_END(n); + warned = 1; + } + } + + if (!warned) + Swig_warning(WARN_PARSE_UNNAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", kind); + + return nn; +} + /* Strips C-style and C++-style comments from string in-place. */ static void strip_comments(char *string) { int state = 0; /* @@ -1073,6 +1226,7 @@ static void strip_comments(char *string) { static Node *dump_nested(const char *parent) { Nested *n,*n1; Node *ret = 0; + Node *last = 0; n = nested_list; if (!parent) { nested_list = 0; @@ -1102,20 +1256,12 @@ static Node *dump_nested(const char *parent) { add_symbols(retx); if (ret) { - set_nextSibling(retx,ret); - Delete(ret); + set_nextSibling(last, retx); + Delete(retx); + } else { + ret = retx; } - ret = retx; - - /* Insert a forward class declaration */ - /* Disabled: [ 597599 ] union in class: incorrect scope - retx = new_node("classforward"); - Setattr(retx,"kind",n->kind); - Setattr(retx,"name",Copy(n->type)); - Setattr(retx,"sym:name", make_name(n->type,0)); - set_nextSibling(retx,ret); - ret = retx; - */ + last = retx; /* Strip comments - further code may break in presence of comments. */ strip_comments(Char(n->code)); @@ -1164,17 +1310,18 @@ static Node *dump_nested(const char *parent) { } } { - Node *head = new_node("insert"); - String *code = NewStringf("\n%s\n",n->code); - Setattr(head,"code", code); + Node *newnode = new_node("insert"); + String *code = NewStringEmpty(); + Wrapper_pretty_print(n->code, code); + Setattr(newnode,"code", code); Delete(code); - set_nextSibling(head,ret); - Delete(ret); - ret = head; + set_nextSibling(last, newnode); + Delete(newnode); + last = newnode; } /* Dump the code to the scanner */ - start_inline(Char(n->code),n->line); + start_inline(Char(Getattr(last, "code")),n->line); n1 = n->next; Delete(n->code); @@ -1486,7 +1633,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) { %token STRING %token INCLUDE IMPORT INSERT %token CHARCONST -%token NUM_INT NUM_FLOAT NUM_UNSIGNED NUM_LONG NUM_ULONG NUM_LONGLONG NUM_ULONGLONG +%token NUM_INT NUM_FLOAT NUM_UNSIGNED NUM_LONG NUM_ULONG NUM_LONGLONG NUM_ULONGLONG NUM_BOOL %token TYPEDEF %token TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_WCHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_COMPLEX TYPE_TYPEDEF TYPE_RAW TYPE_NON_ISO_INT8 TYPE_NON_ISO_INT16 TYPE_NON_ISO_INT32 TYPE_NON_ISO_INT64 %token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE PERIOD @@ -1500,7 +1647,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) { %token NATIVE INLINE %token TYPEMAP EXCEPT ECHO APPLY CLEAR SWIGTEMPLATE FRAGMENT %token WARN -%token LESSTHAN GREATERTHAN MODULO DELETE_KW +%token LESSTHAN GREATERTHAN DELETE_KW %token LESSTHANOREQUALTO GREATERTHANOREQUALTO EQUALTO NOTEQUALTO %token QUESTIONMARK %token TYPES PARMS @@ -1521,7 +1668,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) { %left GREATERTHAN LESSTHAN GREATERTHANOREQUALTO LESSTHANOREQUALTO %left LSHIFT RSHIFT %left PLUS MINUS -%left STAR SLASH MODULUS +%left STAR SLASH MODULO %left UMINUS NOT LNOT %left DCOLON @@ -1569,7 +1716,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) { %type pragma_arg; %type includetype; %type pointer primitive_type; -%type declarator direct_declarator notso_direct_declarator parameter_declarator typemap_parameter_declarator nested_decl; +%type declarator direct_declarator notso_direct_declarator parameter_declarator typemap_parameter_declarator; %type abstract_declarator direct_abstract_declarator ctor_end; %type typemap_type; %type idcolon idcolontail idcolonnt idcolontailnt idtemplate stringbrace stringbracesemi; @@ -2577,11 +2724,11 @@ typemap_parm : type typemap_parameter_declarator { Parm *parm; SwigType_push($1,$2.type); $$ = new_node("typemapitem"); - parm = NewParm($1,$2.id); + parm = NewParmWithoutFileLineInfo($1,$2.id); Setattr($$,"pattern",parm); Setattr($$,"parms", $2.parms); Delete(parm); - /* $$ = NewParm($1,$2.id); + /* $$ = NewParmWithoutFileLineInfo($1,$2.id); Setattr($$,"parms",$2.parms); */ } | LPAREN parms RPAREN { @@ -2752,7 +2899,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va } else { Setattr(templnode,"sym:typename","1"); } - if ($3) { + if ($3 && !inclass) { /* Comment this out for 1.3.28. We need to re-enable it later but first we need to @@ -2770,8 +2917,11 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va Swig_cparse_template_expand(templnode,nname,temparms,tscope); Setattr(templnode,"sym:name",nname); Delete(nname); - Setattr(templnode,"feature:onlychildren", - "typemap,typemapitem,typemapcopy,typedef,types,fragment"); + Setattr(templnode,"feature:onlychildren", "typemap,typemapitem,typemapcopy,typedef,types,fragment"); + + if ($3) { + 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"); + } } Delattr(templnode,"templatetype"); Setattr(templnode,"template",nn); @@ -2811,10 +2961,10 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va Swig_symbol_setscope(csyms); } - /* Merge in addmethods for this class */ + /* Merge in %extend methods for this class */ /* !!! This may be broken. We may have to add the - addmethods at the beginning of the class */ + %extend methods at the beginning of the class */ if (extendhash) { String *stmp = 0; @@ -2922,7 +3072,7 @@ c_declaration : c_decl { appendChild($$,n); while (n) { SwigType *decl = Getattr(n,"decl"); - if (SwigType_isfunction(decl)) { + if (SwigType_isfunction(decl) && Strcmp(Getattr(n, "storage"), "typedef") != 0) { Setattr(n,"storage","externc"); } n = nextSibling(n); @@ -3089,7 +3239,7 @@ c_enum_decl : storage_class ENUM ename LBRACE enumlist RBRACE SEMI { add_symbols($$); /* Add to tag space */ add_symbols($5); /* Add enum values to id space */ } - | storage_class ENUM ename LBRACE enumlist RBRACE declarator c_decl_tail { + | storage_class ENUM ename LBRACE enumlist RBRACE declarator initializer c_decl_tail { Node *n; SwigType *ty = 0; String *unnamed = 0; @@ -3127,12 +3277,12 @@ c_enum_decl : storage_class ENUM ename LBRACE enumlist RBRACE SEMI { if (unnamedinstance) { SwigType *cty = NewString("enum "); Setattr($$,"type",cty); - Setattr($$,"unnamedinstance","1"); - Setattr(n,"unnamedinstance","1"); + SetFlag($$,"unnamedinstance"); + SetFlag(n,"unnamedinstance"); Delete(cty); } - if ($8) { - Node *p = $8; + if ($9) { + Node *p = $9; set_nextSibling(n,p); while (p) { SwigType *cty = Copy(ty); @@ -3226,10 +3376,10 @@ cpp_declaration : cpp_class_decl { $$ = $1; } | cpp_catch_decl { $$ = 0; } ; -cpp_class_decl : /* A simple class/struct/union definition */ - storage_class cpptype idcolon inherit LBRACE { +cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { + if (nested_template == 0) { List *bases = 0; Node *scope = 0; $$ = new_node("class"); @@ -3343,120 +3493,129 @@ cpp_class_decl : } class_decl[class_level++] = $$; inclass = 1; + } } cpp_members RBRACE cpp_opt_declarators { - Node *p; - SwigType *ty; - Symtab *cscope = prev_symtab; - Node *am = 0; - String *scpname = 0; - $$ = class_decl[--class_level]; - inclass = 0; - - /* Check for pure-abstract class */ - Setattr($$,"abstract", pure_abstract($7)); - - /* This bit of code merges in a previously defined %extend directive (if any) */ - - if (extendhash) { - String *clsname = Swig_symbol_qualifiedscopename(0); - am = Getattr(extendhash,clsname); - if (am) { - merge_extensions($$,am); - Delattr(extendhash,clsname); + (void) $6; + if (nested_template == 0) { + Node *p; + SwigType *ty; + Symtab *cscope = prev_symtab; + Node *am = 0; + String *scpname = 0; + $$ = class_decl[--class_level]; + inclass = 0; + + /* Check for pure-abstract class */ + Setattr($$,"abstract", pure_abstract($7)); + + /* This bit of code merges in a previously defined %extend directive (if any) */ + + if (extendhash) { + String *clsname = Swig_symbol_qualifiedscopename(0); + am = Getattr(extendhash,clsname); + if (am) { + merge_extensions($$,am); + Delattr(extendhash,clsname); + } + Delete(clsname); } - Delete(clsname); - } - if (!classes) classes = NewHash(); - scpname = Swig_symbol_qualifiedscopename(0); - Setattr(classes,scpname,$$); - Delete(scpname); + if (!classes) classes = NewHash(); + scpname = Swig_symbol_qualifiedscopename(0); + Setattr(classes,scpname,$$); + Delete(scpname); - appendChild($$,$7); - - if (am) append_previous_extension($$,am); + appendChild($$,$7); + + if (am) append_previous_extension($$,am); - p = $9; - if (p) { - set_nextSibling($$,p); - } - - if (cparse_cplusplus && !cparse_externc) { - ty = NewString($3); - } else { - ty = NewStringf("%s %s", $2,$3); - } - while (p) { - Setattr(p,"storage",$1); - Setattr(p,"type",ty); - p = nextSibling(p); - } - /* Dump nested classes */ - { - String *name = $3; - if ($9) { - SwigType *decltype = Getattr($9,"decl"); - if (Cmp($1,"typedef") == 0) { - if (!decltype || !Len(decltype)) { - String *cname; - name = Getattr($9,"name"); - cname = Copy(name); - Setattr($$,"tdname",cname); - Delete(cname); + p = $9; + if (p) { + set_nextSibling($$,p); + } + + if (cparse_cplusplus && !cparse_externc) { + ty = NewString($3); + } else { + ty = NewStringf("%s %s", $2,$3); + } + while (p) { + Setattr(p,"storage",$1); + Setattr(p,"type",ty); + p = nextSibling(p); + } + /* Dump nested classes */ + { + String *name = $3; + if ($9) { + SwigType *decltype = Getattr($9,"decl"); + if (Cmp($1,"typedef") == 0) { + if (!decltype || !Len(decltype)) { + String *cname; + name = Getattr($9,"name"); + cname = Copy(name); + Setattr($$,"tdname",cname); + Delete(cname); - /* Use typedef name as class name */ - if (class_rename && (Strcmp(class_rename,$3) == 0)) { - Delete(class_rename); - class_rename = NewString(name); + /* Use typedef name as class name */ + if (class_rename && (Strcmp(class_rename,$3) == 0)) { + Delete(class_rename); + class_rename = NewString(name); + } + if (!Getattr(classes,name)) { + Setattr(classes,name,$$); + } + Setattr($$,"decl",decltype); } - if (!Getattr(classes,name)) { - Setattr(classes,name,$$); - } - Setattr($$,"decl",decltype); } } + appendChild($$,dump_nested(Char(name))); } - appendChild($$,dump_nested(Char(name))); - } - if (cplus_mode != CPLUS_PUBLIC) { - /* we 'open' the class at the end, to allow %template - to add new members */ - Node *pa = new_node("access"); - Setattr(pa,"kind","public"); - cplus_mode = CPLUS_PUBLIC; - appendChild($$,pa); - Delete(pa); - } + if (cplus_mode != CPLUS_PUBLIC) { + /* we 'open' the class at the end, to allow %template + to add new members */ + Node *pa = new_node("access"); + Setattr(pa,"kind","public"); + cplus_mode = CPLUS_PUBLIC; + appendChild($$,pa); + Delete(pa); + } - Setattr($$,"symtab",Swig_symbol_popscope()); + Setattr($$,"symtab",Swig_symbol_popscope()); - Classprefix = 0; - if (nscope_inner) { - /* this is tricky */ - /* we add the declaration in the original namespace */ - appendChild(nscope_inner,$$); - Swig_symbol_setscope(Getattr(nscope_inner,"symtab")); - Delete(Namespaceprefix); - Namespaceprefix = Swig_symbol_qualifiedscopename(0); - add_symbols($$); - if (nscope) $$ = nscope; - /* but the variable definition in the current scope */ + Classprefix = 0; + if (nscope_inner) { + /* this is tricky */ + /* we add the declaration in the original namespace */ + appendChild(nscope_inner,$$); + Swig_symbol_setscope(Getattr(nscope_inner,"symtab")); + Delete(Namespaceprefix); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + add_symbols($$); + if (nscope) $$ = nscope; + /* but the variable definition in the current scope */ + Swig_symbol_setscope(cscope); + Delete(Namespaceprefix); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + add_symbols($9); + } else { + Delete(yyrename); + yyrename = Copy(class_rename); + Delete(Namespaceprefix); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + + add_symbols($$); + add_symbols($9); + } Swig_symbol_setscope(cscope); Delete(Namespaceprefix); Namespaceprefix = Swig_symbol_qualifiedscopename(0); - add_symbols($9); } else { - Delete(yyrename); - yyrename = Copy(class_rename); - Delete(Namespaceprefix); - Namespaceprefix = Swig_symbol_qualifiedscopename(0); - - add_symbols($$); - add_symbols($9); + $$ = new_node("class"); + Setattr($$,"kind",$2); + Setattr($$,"name",NewString($3)); + SetFlag($$,"nestedtemplateclass"); } - Swig_symbol_setscope(cscope); - Delete(Namespaceprefix); - Namespaceprefix = Swig_symbol_qualifiedscopename(0); } /* An unnamed struct, possibly with a typedef */ @@ -3495,9 +3654,10 @@ cpp_class_decl : Classprefix = NewStringEmpty(); Delete(Namespaceprefix); Namespaceprefix = Swig_symbol_qualifiedscopename(0); - } cpp_members RBRACE declarator c_decl_tail { + } cpp_members RBRACE declarator initializer c_decl_tail { String *unnamed; Node *n; + (void) $4; Classprefix = 0; $$ = class_decl[--class_level]; inclass = 0; @@ -3513,8 +3673,8 @@ cpp_class_decl : Setattr(n,"decl",$7.type); Setattr(n,"parms",$7.parms); Setattr(n,"storage",$1); - if ($8) { - Node *p = $8; + if ($9) { + Node *p = $9; set_nextSibling(n,p); while (p) { String *type = Copy(unnamed); @@ -3584,12 +3744,12 @@ cpp_class_decl : ; cpp_opt_declarators : SEMI { $$ = 0; } - | declarator c_decl_tail { + | declarator initializer c_decl_tail { $$ = new_node("cdecl"); Setattr($$,"name",$1.id); Setattr($$,"decl",$1.type); Setattr($$,"parms",$1.parms); - set_nextSibling($$,$2); + set_nextSibling($$,$3); } ; /* ------------------------------------------------------------ @@ -3616,240 +3776,294 @@ cpp_forward_class_decl : storage_class cpptype idcolon SEMI { template<...> decl ------------------------------------------------------------ */ -cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_parameters = $3; } cpp_temp_possible { - String *tname = 0; - int error = 0; +cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { + template_parameters = $3; + if (inclass) + nested_template++; - /* check if we get a namespace node with a class declaration, and retrieve the class */ - Symtab *cscope = Swig_symbol_current(); - Symtab *sti = 0; - Node *ntop = $6; - Node *ni = ntop; - SwigType *ntype = ni ? nodeType(ni) : 0; - while (ni && Strcmp(ntype,"namespace") == 0) { - sti = Getattr(ni,"symtab"); - ni = firstChild(ni); - ntype = nodeType(ni); - } - if (sti) { - Swig_symbol_setscope(sti); - Delete(Namespaceprefix); - Namespaceprefix = Swig_symbol_qualifiedscopename(0); - $6 = ni; - } + } cpp_temp_possible { - template_parameters = 0; - $$ = $6; - if ($$) tname = Getattr($$,"name"); - - /* Check if the class is a template specialization */ - if (($$) && (Strchr(tname,'<')) && (!is_operator(tname))) { - /* If a specialization. Check if defined. */ - Node *tempn = 0; - { - String *tbase = SwigType_templateprefix(tname); - tempn = Swig_symbol_clookup_local(tbase,0); - if (!tempn || (Strcmp(nodeType(tempn),"template") != 0)) { - SWIG_WARN_NODE_BEGIN(tempn); - Swig_warning(WARN_PARSE_TEMPLATE_SP_UNDEF, Getfile($$),Getline($$),"Specialization of non-template '%s'.\n", tbase); - SWIG_WARN_NODE_END(tempn); - tempn = 0; - error = 1; + /* Don't ignore templated functions declared within a class, unless the templated function is within a nested class */ + if (nested_template <= 1) { + int is_nested_template_class = $6 && GetFlag($6, "nestedtemplateclass"); + if (is_nested_template_class) { + $$ = 0; + /* Nested template classes would probably better be ignored like ordinary nested classes using cpp_nested, but that introduces shift/reduce conflicts */ + if (cplus_mode == CPLUS_PUBLIC) { + /* Treat the nested class/struct/union as a forward declaration until a proper nested class solution is implemented */ + String *kind = Getattr($6, "kind"); + String *name = Getattr($6, "name"); + $$ = new_node("template"); + Setattr($$,"kind",kind); + Setattr($$,"name",name); + Setattr($$,"sym:weak", "1"); + Setattr($$,"templatetype","classforward"); + Setattr($$,"templateparms", $3); + add_symbols($$); + + if (GetFlag($$, "feature:nestedworkaround")) { + Swig_symbol_remove($$); + $$ = 0; + } else { + SWIG_WARN_NODE_BEGIN($$); + Swig_warning(WARN_PARSE_NAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested template %s not currently supported (%s ignored).\n", kind, name); + SWIG_WARN_NODE_END($$); } - Delete(tbase); } - Setattr($$,"specialization","1"); - Setattr($$,"templatetype",nodeType($$)); - set_nodeType($$,"template"); - /* Template partial specialization */ - if (tempn && ($3) && ($6)) { - List *tlist; - String *targs = SwigType_templateargs(tname); - tlist = SwigType_parmlist(targs); - /* Printf(stdout,"targs = '%s' %s\n", targs, tlist); */ + Delete($6); + } else { + String *tname = 0; + int error = 0; + + /* check if we get a namespace node with a class declaration, and retrieve the class */ + Symtab *cscope = Swig_symbol_current(); + Symtab *sti = 0; + Node *ntop = $6; + Node *ni = ntop; + SwigType *ntype = ni ? nodeType(ni) : 0; + while (ni && Strcmp(ntype,"namespace") == 0) { + sti = Getattr(ni,"symtab"); + ni = firstChild(ni); + ntype = nodeType(ni); + } + if (sti) { + Swig_symbol_setscope(sti); + Delete(Namespaceprefix); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + $6 = ni; + } + + $$ = $6; + if ($$) tname = Getattr($$,"name"); + + /* Check if the class is a template specialization */ + if (($$) && (Strchr(tname,'<')) && (!is_operator(tname))) { + /* If a specialization. Check if defined. */ + Node *tempn = 0; + { + String *tbase = SwigType_templateprefix(tname); + tempn = Swig_symbol_clookup_local(tbase,0); + if (!tempn || (Strcmp(nodeType(tempn),"template") != 0)) { + SWIG_WARN_NODE_BEGIN(tempn); + Swig_warning(WARN_PARSE_TEMPLATE_SP_UNDEF, Getfile($$),Getline($$),"Specialization of non-template '%s'.\n", tbase); + SWIG_WARN_NODE_END(tempn); + tempn = 0; + error = 1; + } + Delete(tbase); + } + Setattr($$,"specialization","1"); + Setattr($$,"templatetype",nodeType($$)); + set_nodeType($$,"template"); + /* Template partial specialization */ + if (tempn && ($3) && ($6)) { + List *tlist; + String *targs = SwigType_templateargs(tname); + tlist = SwigType_parmlist(targs); + /* Printf(stdout,"targs = '%s' %s\n", targs, tlist); */ + if (!Getattr($$,"sym:weak")) { + Setattr($$,"sym:typename","1"); + } + + if (Len(tlist) != ParmList_len(Getattr(tempn,"templateparms"))) { + Swig_error(Getfile($$),Getline($$),"Inconsistent argument count in template partial specialization. %d %d\n", Len(tlist), ParmList_len(Getattr(tempn,"templateparms"))); + + } else { + + /* This code builds the argument list for the partial template + specialization. This is a little hairy, but the idea is as + follows: + + $3 contains a list of arguments supplied for the template. + For example template. + + tlist is a list of the specialization arguments--which may be + different. For example class. + + tp is a copy of the arguments in the original template definition. + + The patching algorithm walks through the list of supplied + arguments ($3), finds the position in the specialization arguments + (tlist), and then patches the name in the argument list of the + original template. + */ + + { + String *pn; + Parm *p, *p1; + int i, nargs; + Parm *tp = CopyParmList(Getattr(tempn,"templateparms")); + nargs = Len(tlist); + p = $3; + while (p) { + for (i = 0; i < nargs; i++){ + pn = Getattr(p,"name"); + if (Strcmp(pn,SwigType_base(Getitem(tlist,i))) == 0) { + int j; + Parm *p1 = tp; + for (j = 0; j < i; j++) { + p1 = nextSibling(p1); + } + Setattr(p1,"name",pn); + Setattr(p1,"partialarg","1"); + } + } + p = nextSibling(p); + } + p1 = tp; + i = 0; + while (p1) { + if (!Getattr(p1,"partialarg")) { + Delattr(p1,"name"); + Setattr(p1,"type", Getitem(tlist,i)); + } + i++; + p1 = nextSibling(p1); + } + Setattr($$,"templateparms",tp); + Delete(tp); + } + #if 0 + /* Patch the parameter list */ + if (tempn) { + Parm *p,*p1; + ParmList *tp = CopyParmList(Getattr(tempn,"templateparms")); + p = $3; + p1 = tp; + while (p && p1) { + String *pn = Getattr(p,"name"); + Printf(stdout,"pn = '%s'\n", pn); + if (pn) Setattr(p1,"name",pn); + else Delattr(p1,"name"); + pn = Getattr(p,"type"); + if (pn) Setattr(p1,"type",pn); + p = nextSibling(p); + p1 = nextSibling(p1); + } + Setattr($$,"templateparms",tp); + Delete(tp); + } else { + Setattr($$,"templateparms",$3); + } + #endif + Delattr($$,"specialization"); + Setattr($$,"partialspecialization","1"); + /* Create a specialized name for matching */ + { + Parm *p = $3; + String *fname = NewString(Getattr($$,"name")); + String *ffname = 0; + ParmList *partialparms = 0; + + char tmp[32]; + int i, ilen; + while (p) { + String *n = Getattr(p,"name"); + if (!n) { + p = nextSibling(p); + continue; + } + ilen = Len(tlist); + for (i = 0; i < ilen; i++) { + if (Strstr(Getitem(tlist,i),n)) { + sprintf(tmp,"$%d",i+1); + Replaceid(fname,n,tmp); + } + } + p = nextSibling(p); + } + /* Patch argument names with typedef */ + { + Iterator tt; + Parm *parm_current = 0; + List *tparms = SwigType_parmlist(fname); + ffname = SwigType_templateprefix(fname); + Append(ffname,"<("); + for (tt = First(tparms); tt.item; ) { + SwigType *rtt = Swig_symbol_typedef_reduce(tt.item,0); + SwigType *ttr = Swig_symbol_type_qualify(rtt,0); + + Parm *newp = NewParmWithoutFileLineInfo(ttr, 0); + if (partialparms) + set_nextSibling(parm_current, newp); + else + partialparms = newp; + parm_current = newp; + + Append(ffname,ttr); + tt = Next(tt); + if (tt.item) Putc(',',ffname); + Delete(rtt); + Delete(ttr); + } + Delete(tparms); + Append(ffname,")>"); + } + { + Node *new_partial = NewHash(); + String *partials = Getattr(tempn,"partials"); + if (!partials) { + partials = NewList(); + Setattr(tempn,"partials",partials); + Delete(partials); + } + /* Printf(stdout,"partial: fname = '%s', '%s'\n", fname, Swig_symbol_typedef_reduce(fname,0)); */ + Setattr(new_partial, "partialparms", partialparms); + Setattr(new_partial, "templcsymname", ffname); + Append(partials, new_partial); + } + Setattr($$,"partialargs",ffname); + Swig_symbol_cadd(ffname,$$); + } + } + Delete(tlist); + Delete(targs); + } else { + /* An explicit template specialization */ + /* add default args from primary (unspecialized) template */ + String *ty = Swig_symbol_template_deftype(tname,0); + String *fname = Swig_symbol_type_qualify(ty,0); + Swig_symbol_cadd(fname,$$); + Delete(ty); + Delete(fname); + } + } else if ($$) { + Setattr($$,"templatetype",nodeType($6)); + set_nodeType($$,"template"); + Setattr($$,"templateparms", $3); if (!Getattr($$,"sym:weak")) { Setattr($$,"sym:typename","1"); } - - if (Len(tlist) != ParmList_len(Getattr(tempn,"templateparms"))) { - Swig_error(Getfile($$),Getline($$),"Inconsistent argument count in template partial specialization. %d %d\n", Len(tlist), ParmList_len(Getattr(tempn,"templateparms"))); - - } else { - - /* This code builds the argument list for the partial template - specialization. This is a little hairy, but the idea is as - follows: - - $3 contains a list of arguments supplied for the template. - For example template. - - tlist is a list of the specialization arguments--which may be - different. For example class. - - tp is a copy of the arguments in the original template definition. - - The patching algorithm walks through the list of supplied - arguments ($3), finds the position in the specialization arguments - (tlist), and then patches the name in the argument list of the - original template. - */ - + add_symbols($$); + default_arguments($$); + /* We also place a fully parameterized version in the symbol table */ { - String *pn; - Parm *p, *p1; - int i, nargs; - Parm *tp = CopyParmList(Getattr(tempn,"templateparms")); - nargs = Len(tlist); + Parm *p; + String *fname = NewStringf("%s<(", Getattr($$,"name")); p = $3; - while (p) { - for (i = 0; i < nargs; i++){ - pn = Getattr(p,"name"); - if (Strcmp(pn,SwigType_base(Getitem(tlist,i))) == 0) { - int j; - Parm *p1 = tp; - for (j = 0; j < i; j++) { - p1 = nextSibling(p1); - } - Setattr(p1,"name",pn); - Setattr(p1,"partialarg","1"); - } - } - p = nextSibling(p); - } - p1 = tp; - i = 0; - while (p1) { - if (!Getattr(p1,"partialarg")) { - Delattr(p1,"name"); - Setattr(p1,"type", Getitem(tlist,i)); - } - i++; - p1 = nextSibling(p1); - } - Setattr($$,"templateparms",tp); - Delete(tp); - } -#if 0 - /* Patch the parameter list */ - if (tempn) { - Parm *p,*p1; - ParmList *tp = CopyParmList(Getattr(tempn,"templateparms")); - p = $3; - p1 = tp; - while (p && p1) { - String *pn = Getattr(p,"name"); - Printf(stdout,"pn = '%s'\n", pn); - if (pn) Setattr(p1,"name",pn); - else Delattr(p1,"name"); - pn = Getattr(p,"type"); - if (pn) Setattr(p1,"type",pn); - p = nextSibling(p); - p1 = nextSibling(p1); - } - Setattr($$,"templateparms",tp); - Delete(tp); - } else { - Setattr($$,"templateparms",$3); - } -#endif - Delattr($$,"specialization"); - Setattr($$,"partialspecialization","1"); - /* Create a specialized name for matching */ - { - Parm *p = $3; - String *fname = NewString(Getattr($$,"name")); - String *ffname = 0; - - char tmp[32]; - int i, ilen; while (p) { String *n = Getattr(p,"name"); - if (!n) { - p = nextSibling(p); - continue; - } - ilen = Len(tlist); - for (i = 0; i < ilen; i++) { - if (Strstr(Getitem(tlist,i),n)) { - sprintf(tmp,"$%d",i+1); - Replaceid(fname,n,tmp); - } - } + if (!n) n = Getattr(p,"type"); + Append(fname,n); p = nextSibling(p); + if (p) Putc(',',fname); } - /* Patch argument names with typedef */ - { - Iterator tt; - List *tparms = SwigType_parmlist(fname); - ffname = SwigType_templateprefix(fname); - Append(ffname,"<("); - for (tt = First(tparms); tt.item; ) { - SwigType *rtt = Swig_symbol_typedef_reduce(tt.item,0); - SwigType *ttr = Swig_symbol_type_qualify(rtt,0); - Append(ffname,ttr); - tt = Next(tt); - if (tt.item) Putc(',',ffname); - Delete(rtt); - Delete(ttr); - } - Delete(tparms); - Append(ffname,")>"); - } - { - String *partials = Getattr(tempn,"partials"); - if (!partials) { - partials = NewList(); - Setattr(tempn,"partials",partials); - Delete(partials); - } - /* Printf(stdout,"partial: fname = '%s', '%s'\n", fname, Swig_symbol_typedef_reduce(fname,0)); */ - Append(partials,ffname); - } - Setattr($$,"partialargs",ffname); - Swig_symbol_cadd(ffname,$$); + Append(fname,")>"); + Swig_symbol_cadd(fname,$$); } - } - Delete(tlist); - Delete(targs); - } else { - /* Need to resolve exact specialization name */ - /* add default args from generic template */ - String *ty = Swig_symbol_template_deftype(tname,0); - String *fname = Swig_symbol_type_qualify(ty,0); - Swig_symbol_cadd(fname,$$); - Delete(ty); - Delete(fname); - } - } else if ($$) { - Setattr($$,"templatetype",nodeType($6)); - set_nodeType($$,"template"); - Setattr($$,"templateparms", $3); - if (!Getattr($$,"sym:weak")) { - Setattr($$,"sym:typename","1"); - } - add_symbols($$); - default_arguments($$); - /* We also place a fully parameterized version in the symbol table */ - { - Parm *p; - String *fname = NewStringf("%s<(", Getattr($$,"name")); - p = $3; - while (p) { - String *n = Getattr(p,"name"); - if (!n) n = Getattr(p,"type"); - Append(fname,n); - p = nextSibling(p); - if (p) Putc(',',fname); - } - Append(fname,")>"); - Swig_symbol_cadd(fname,$$); } + $$ = ntop; + Swig_symbol_setscope(cscope); + Delete(Namespaceprefix); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + if (error) $$ = 0; } - $$ = ntop; - Swig_symbol_setscope(cscope); - Delete(Namespaceprefix); - Namespaceprefix = Swig_symbol_qualifiedscopename(0); - if (error) $$ = 0; + } else { + $$ = 0; + } + template_parameters = 0; + if (inclass) + nested_template--; } | TEMPLATE cpptype idcolon { Swig_warning(WARN_PARSE_EXPLICIT_TEMPLATE, cparse_file, cparse_line, "Explicit template instantiation ignored.\n"); @@ -3915,7 +4129,7 @@ templateparameters : templateparameter templateparameterstail { ; templateparameter : templcpptype { - $$ = NewParm(NewString($1), 0); + $$ = NewParmWithoutFileLineInfo(NewString($1), 0); } | parm { $$ = $1; @@ -4307,110 +4521,77 @@ cpp_protection_decl : PUBLIC COLON { ; -/* ---------------------------------------------------------------------- - Nested structure. This is a sick "hack". If we encounter - a nested structure, we're going to grab the text of its definition and - feed it back into the scanner. In the meantime, we need to grab - variable declaration information and generate the associated wrapper - code later. Yikes! +/* ------------------------------------------------------------ + Named nested structs: + struct sname { }; + struct sname { } id; + struct sname : bases { }; + struct sname : bases { } id; + typedef sname struct { } td; + typedef sname struct : bases { } td; - This really only works in a limited sense. Since we use the - code attached to the nested class to generate both C/C++ code, - it can't have any SWIG directives in it. It also needs to be parsable - by SWIG or this whole thing is going to puke. - ---------------------------------------------------------------------- */ + Adding inheritance, ie replacing 'ID' with 'idcolon inherit' + added one shift/reduce + ------------------------------------------------------------ */ -/* A struct sname { } id; declaration */ - -cpp_nested : storage_class cpptype ID LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}'); - } nested_decl SEMI { +cpp_nested : storage_class cpptype idcolon inherit LBRACE { + cparse_start_line = cparse_line; skip_balanced('{','}'); + $$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */ + } cpp_opt_declarators { $$ = 0; if (cplus_mode == CPLUS_PUBLIC) { - if ($6.id && strcmp($2, "class") != 0) { - Nested *n = (Nested *) malloc(sizeof(Nested)); - n->code = NewStringEmpty(); - Printv(n->code, "typedef ", $2, " ", - Char(scanner_ccode), " $classname_", $6.id, ";\n", NIL); + if (cparse_cplusplus) { + $$ = nested_forward_declaration($1, $2, $3, $3, $7); + } else if ($7) { + nested_new_struct($2, $6, $7); + } + } + Delete($6); + } - n->name = Swig_copy_string($6.id); - n->line = cparse_start_line; - n->type = NewStringEmpty(); - n->kind = $2; - n->unnamed = 0; - SwigType_push(n->type, $6.type); - n->next = 0; - add_nested(n); +/* ------------------------------------------------------------ + Unnamed/anonymous nested structs: + struct { }; + struct { } id; + struct : bases { }; + struct : bases { } id; + typedef struct { } td; + typedef struct : bases { } td; + ------------------------------------------------------------ */ + + | storage_class cpptype inherit LBRACE { + cparse_start_line = cparse_line; skip_balanced('{','}'); + $$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */ + } cpp_opt_declarators { + $$ = 0; + if (cplus_mode == CPLUS_PUBLIC) { + if (cparse_cplusplus) { + const char *name = $6 ? Getattr($6, "name") : 0; + $$ = nested_forward_declaration($1, $2, 0, name, $6); } else { - Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2); - if (strcmp($2, "class") == 0) { - /* For now, just treat the nested class as a forward - * declaration (SF bug #909387). */ - $$ = new_node("classforward"); - Setfile($$,cparse_file); - Setline($$,cparse_line); - Setattr($$,"kind",$2); - Setattr($$,"name",$3); - Setattr($$,"sym:weak", "1"); - add_symbols($$); + if ($6) { + nested_new_struct($2, $5, $6); + } else { + Swig_warning(WARN_PARSE_UNNAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2); } } } + Delete($5); } -/* A struct { } id; declaration */ - | storage_class cpptype LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}'); - } nested_decl SEMI { - $$ = 0; - if (cplus_mode == CPLUS_PUBLIC) { - if (strcmp($2,"class") == 0) { - Swig_warning(WARN_PARSE_NESTED_CLASS,cparse_file, cparse_line,"Nested class not currently supported (ignored)\n"); - /* Generate some code for a new class */ - } else if ($5.id) { - /* Generate some code for a new class */ - Nested *n = (Nested *) malloc(sizeof(Nested)); - n->code = NewStringEmpty(); - Printv(n->code, "typedef ", $2, " " , - Char(scanner_ccode), " $classname_", $5.id, ";\n",NIL); - n->name = Swig_copy_string($5.id); - n->line = cparse_start_line; - n->type = NewStringEmpty(); - n->kind = $2; - n->unnamed = 1; - SwigType_push(n->type,$5.type); - n->next = 0; - add_nested(n); - } else { - Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2); - } - } - } -/* A 'class name : base_list { };' declaration, always ignored */ -/***** - This fixes derived_nested.i, but it adds one shift/reduce. Anyway, - we are waiting for the nested class support. - *****/ - | storage_class cpptype idcolon COLON base_list LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}'); - } SEMI { - $$ = 0; - if (cplus_mode == CPLUS_PUBLIC) { - Swig_warning(WARN_PARSE_NESTED_CLASS,cparse_file, cparse_line,"Nested class not currently supported (ignored)\n"); - } - } + + +/* This unfortunately introduces 4 shift/reduce conflicts, so instead the somewhat hacky nested_template is used for ignore nested template classes. */ /* | TEMPLATE LESSTHAN template_parms GREATERTHAN cpptype idcolon LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}'); } SEMI { $$ = 0; if (cplus_mode == CPLUS_PUBLIC) { - Swig_warning(WARN_PARSE_NESTED_CLASS,cparse_file, cparse_line,"Nested class not currently supported (ignored)\n"); + Swig_warning(WARN_PARSE_NAMED_NESTED_CLASS, cparse_file, cparse_line,"Nested %s not currently supported (%s ignored)\n", $5, $6); } } */ ; -nested_decl : declarator { $$ = $1;} - | empty { $$.id = 0; } - ; - - /* These directives can be included inside a class definition */ cpp_swig_directive: pragma_directive { $$ = $1; } @@ -4527,7 +4708,7 @@ ptail : COMMA parm ptail { parm : rawtype parameter_declarator { SwigType_push($1,$2.type); - $$ = NewParm($1,$2.id); + $$ = NewParmWithoutFileLineInfo($1,$2.id); Setfile($$,cparse_file); Setline($$,cparse_line); if ($2.defarg) { @@ -4536,7 +4717,7 @@ parm : rawtype parameter_declarator { } | TEMPLATE LESSTHAN cpptype GREATERTHAN cpptype idcolon def_args { - $$ = NewParm(NewStringf("template %s %s", $5,$6), 0); + $$ = NewParmWithoutFileLineInfo(NewStringf("template %s %s", $5,$6), 0); Setfile($$,cparse_file); Setline($$,cparse_line); if ($7.val) { @@ -4545,7 +4726,7 @@ parm : rawtype parameter_declarator { } | PERIOD PERIOD PERIOD { SwigType *t = NewString("v(...)"); - $$ = NewParm(t, 0); + $$ = NewParmWithoutFileLineInfo(t, 0); Setfile($$,cparse_file); Setline($$,cparse_line); } @@ -4608,7 +4789,7 @@ valparm : parm { } | valexpr { - $$ = NewParm(0,0); + $$ = NewParmWithoutFileLineInfo(0,0); Setfile($$,cparse_file); Setline($$,cparse_line); Setattr($$,"value",$1.val); @@ -5547,6 +5728,7 @@ exprnum : NUM_INT { $$ = $1; } | NUM_ULONG { $$ = $1; } | NUM_LONGLONG { $$ = $1; } | NUM_ULONGLONG { $$ = $1; } + | NUM_BOOL { $$ = $1; } ; exprcompound : expr PLUS expr { @@ -5565,7 +5747,7 @@ exprcompound : expr PLUS expr { $$.val = NewStringf("%s/%s",$1.val,$3.val); $$.type = promote($1.type,$3.type); } - | expr MODULUS expr { + | expr MODULO expr { $$.val = NewStringf("%s%%%s",$1.val,$3.val); $$.type = promote($1.type,$3.type); } @@ -5591,40 +5773,37 @@ exprcompound : expr PLUS expr { } | expr LAND expr { $$.val = NewStringf("%s&&%s",$1.val,$3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr LOR expr { $$.val = NewStringf("%s||%s",$1.val,$3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr EQUALTO expr { $$.val = NewStringf("%s==%s",$1.val,$3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr NOTEQUALTO expr { $$.val = NewStringf("%s!=%s",$1.val,$3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } /* Sadly this causes 2 reduce-reduce conflicts with templates. FIXME resolve these. | expr GREATERTHAN expr { - $$.val = NewStringf("%s SWIG_LT %s", $1.val, $3.val); - $$.type = T_INT; + $$.val = NewStringf("%s < %s", $1.val, $3.val); + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr LESSTHAN expr { - $$.val = NewStringf("%s SWIG_GT %s", $1.val, $3.val); - $$.type = T_INT; + $$.val = NewStringf("%s > %s", $1.val, $3.val); + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } */ | expr GREATERTHANOREQUALTO expr { - /* Putting >= in the expression literally causes an infinite - * loop somewhere in the type system. Just workaround for now - * - SWIG_GE is defined in swiglabels.swg. */ - $$.val = NewStringf("%s SWIG_GE %s", $1.val, $3.val); - $$.type = T_INT; + $$.val = NewStringf("%s >= %s", $1.val, $3.val); + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr LESSTHANOREQUALTO expr { - $$.val = NewStringf("%s SWIG_LE %s", $1.val, $3.val); - $$.type = T_INT; + $$.val = NewStringf("%s <= %s", $1.val, $3.val); + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr QUESTIONMARK expr COLON expr %prec QUESTIONMARK { $$.val = NewStringf("%s?%s:%s", $1.val, $3.val, $5.val); @@ -6047,14 +6226,16 @@ Parm *Swig_cparse_parm(String *s) { } -ParmList *Swig_cparse_parms(String *s) { +ParmList *Swig_cparse_parms(String *s, Node *file_line_node) { String *ns; char *cs = Char(s); if (cs && cs[0] != '(') { ns = NewStringf("(%s);",s); } else { ns = NewStringf("%s;",s); - } + } + Setfile(ns, Getfile(file_line_node)); + Setline(ns, Getline(file_line_node)); Seek(ns,0,SEEK_SET); scanner_file(ns); top = 0; diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index 14886605f..91a1d31ff 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -262,7 +262,7 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab /* Look for partial specialization matching */ if (Getattr(n, "partialargs")) { Parm *p, *tp; - ParmList *ptargs = SwigType_function_parms(Getattr(n, "partialargs")); + ParmList *ptargs = SwigType_function_parms(Getattr(n, "partialargs"), n); p = ptargs; tp = tparms; while (p && tp) { @@ -422,6 +422,70 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab return 0; } +typedef enum { ExactNoMatch = -2, PartiallySpecializedNoMatch = -1, PartiallySpecializedMatch = 1, ExactMatch = 2 } EMatch; + +/* ----------------------------------------------------------------------------- + * does_parm_match() + * + * Template argument deduction - check if a template type matches a partially specialized + * template parameter type. Reduce 'partial_parm_type' to see if it matches 'type'. + * + * type - template parameter type to match against + * partial_parm_type - partially specialized template type - a possible match + * partial_parm_type_base - base type of partial_parm_type + * tscope - template scope + * specialization_priority - (output) contains a value indicating how good the match is + * (higher is better) only set if return is set to PartiallySpecializedMatch or ExactMatch. + * ----------------------------------------------------------------------------- */ + +static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, const char *partial_parm_type_base, Symtab *tscope, int *specialization_priority) { + static const int EXACT_MATCH_PRIORITY = 99999; /* a number bigger than the length of any conceivable type */ + int matches; + int substitutions; + EMatch match; + SwigType *ty = Swig_symbol_typedef_reduce(type, tscope); + String *base = SwigType_base(ty); + SwigType *t = Copy(partial_parm_type); + substitutions = Replaceid(t, partial_parm_type_base, base); /* eg: Replaceid("p.$1", "$1", "int") returns t="p.int" */ + matches = Equal(ty, t); + *specialization_priority = -1; + if (substitutions == 1) { + /* we have a non-explicit specialized parameter (in partial_parm_type) because a substitution for $1, $2... etc has taken place */ + SwigType *tt = Copy(partial_parm_type); + int len; + /* + check for match to partial specialization type, for example, all of the following could match the type in the %template: + template struct XX {}; + template struct XX {}; // r.$1 + template struct XX {}; // r.q(const).$1 + template struct XX {}; // r.q(const).p.$1 + %template(XXX) XX; // r.q(const).p.int + + where type="r.q(const).p.int" will match either of tt="r.", tt="r.q(const)" tt="r.q(const).p" + */ + Replaceid(tt, partial_parm_type_base, ""); /* remove the $1, $2 etc, eg tt="p.$1" => "p." */ + len = Len(tt); + if (Strncmp(tt, ty, len) == 0) { + match = PartiallySpecializedMatch; + *specialization_priority = len; + } else { + match = PartiallySpecializedNoMatch; + } + Delete(tt); + } else { + match = matches ? ExactMatch : ExactNoMatch; + if (matches) + *specialization_priority = EXACT_MATCH_PRIORITY; /* exact matches always take precedence */ + } + /* + Printf(stdout, " does_parm_match %2d %5d [%s] [%s]\n", match, *specialization_priority, type, partial_parm_type); + */ + Delete(t); + Delete(base); + Delete(ty); + return match; +} + /* ----------------------------------------------------------------------------- * template_locate() * @@ -429,175 +493,294 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab * ----------------------------------------------------------------------------- */ static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) { - Node *n; - String *tname, *rname = 0; + Node *n = 0; + String *tname = 0; Node *templ; - List *mpartials = 0; + Symtab *primary_scope = 0; + List *possiblepartials = 0; Parm *p; - Parm *parms; + Parm *parms = 0; Parm *targs; ParmList *expandedparms; + int *priorities_matrix = 0; + int max_possible_partials = 0; + int posslen = 0; - tname = Copy(name); - parms = CopyParmList(tparms); - - /* Search for generic template */ + /* Search for primary (unspecialized) template */ templ = Swig_symbol_clookup(name, 0); - /* Add default values from generic template */ - if (templ) { - Symtab *tsdecl = Getattr(templ, "sym:symtab"); + if (template_debug) { + 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); + Delete(tname); + tname = 0; + } + if (templ) { + tname = Copy(name); + parms = CopyParmList(tparms); + + /* All template specializations must be in the primary template's scope, store the symbol table for this scope for specialization lookups */ + primary_scope = Getattr(templ, "sym:symtab"); + + /* Add default values from primary template */ targs = Getattr(templ, "templateparms"); - expandedparms = Swig_symbol_template_defargs(parms, targs, tscope, tsdecl); - } else { - expandedparms = parms; - } + expandedparms = Swig_symbol_template_defargs(parms, targs, tscope, primary_scope); - - /* reduce the typedef */ - p = expandedparms; - while (p) { - SwigType *ty = Getattr(p, "type"); - if (ty) { - SwigType *nt = Swig_symbol_type_qualify(ty, tscope); - Setattr(p, "type", nt); - Delete(nt); - } - p = nextSibling(p); - } - - SwigType_add_template(tname, expandedparms); - - if (template_debug) { - Printf(stdout, "\n%s:%d: template_debug: Searching for %s\n", cparse_file, cparse_line, tname); - } - - /* Search for an exact specialization. - Example: template<> class name { ... } */ - { - if (template_debug) { - Printf(stdout, " searching: '%s' (exact specialization)\n", tname); - } - n = Swig_symbol_clookup_local(tname, 0); - if (!n) { - SwigType *rname = Swig_symbol_typedef_reduce(tname, tscope); - if (!Equal(rname, tname)) { - if (template_debug) { - Printf(stdout, " searching: '%s' (exact specialization)\n", rname); - } - n = Swig_symbol_clookup_local(rname, 0); + /* reduce the typedef */ + p = expandedparms; + while (p) { + SwigType *ty = Getattr(p, "type"); + if (ty) { + SwigType *nt = Swig_symbol_type_qualify(ty, tscope); + Setattr(p, "type", nt); + Delete(nt); } - Delete(rname); + p = nextSibling(p); } - if (n) { - Node *tn; - String *nodeType = nodeType(n); - if (Equal(nodeType, "template")) - goto success; - tn = Getattr(n, "template"); - if (tn) { - n = tn; - goto success; /* Previously wrapped by a template return that */ + SwigType_add_template(tname, expandedparms); + + /* Search for an explicit (exact) specialization. Example: template<> class name { ... } */ + { + if (template_debug) { + Printf(stdout, " searching for : '%s' (explicit specialization)\n", tname); } - Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n)); - Delete(tname); - Delete(parms); - return 0; /* Found a match, but it's not a template of any kind. */ - } - } - - /* Search for partial specialization. - Example: template class name { ... } */ - - /* Generate reduced template name (stripped of extraneous pointers, etc.) */ - - rname = NewStringf("%s<(", name); - p = parms; - while (p) { - String *t; - t = Getattr(p, "type"); - if (!t) - t = Getattr(p, "value"); - if (t) { - String *ty = Swig_symbol_typedef_reduce(t, tscope); - String *tb = SwigType_base(ty); - String *td = SwigType_default(ty); - Replaceid(td, "enum SWIGTYPE", tb); - Replaceid(td, "SWIGTYPE", tb); - Append(rname, td); - Delete(tb); - Delete(ty); - Delete(td); - } - p = nextSibling(p); - if (p) { - Append(rname, ","); - } - } - Append(rname, ")>"); - - mpartials = NewList(); - if (templ) { - /* First, we search using an exact type prototype */ - Parm *p; - char tmp[32]; - int i; - List *partials; - String *ss; - Iterator pi; - - partials = Getattr(templ, "partials"); - if (partials) { - for (pi = First(partials); pi.item; pi = Next(pi)) { - ss = Copy(pi.item); - p = parms; - i = 1; - while (p) { - String *t, *tn; - sprintf(tmp, "$%d", i); - t = Getattr(p, "type"); - if (!t) - t = Getattr(p, "value"); - if (t) { - String *ty = Swig_symbol_typedef_reduce(t, tscope); - tn = SwigType_base(ty); - Replaceid(ss, tmp, tn); - Delete(tn); - Delete(ty); + n = Swig_symbol_clookup_local(tname, primary_scope); + if (!n) { + SwigType *rname = Swig_symbol_typedef_reduce(tname, tscope); + if (!Equal(rname, tname)) { + if (template_debug) { + Printf(stdout, " searching for : '%s' (explicit specialization with typedef reduction)\n", rname); } - i++; - p = nextSibling(p); + n = Swig_symbol_clookup_local(rname, primary_scope); } - if (template_debug) { - Printf(stdout, " searching: '%s' (partial specialization - %s)\n", ss, pi.item); - } - if ((Equal(ss, tname)) || (Equal(ss, rname))) { - Append(mpartials, pi.item); - } - Delete(ss); + Delete(rname); } - } - } - - if (template_debug) { - Printf(stdout, " Matched partials: %s\n", mpartials); - } - - if (Len(mpartials)) { - String *s = Getitem(mpartials, 0); - n = Swig_symbol_clookup_local(s, 0); - if (Len(mpartials) > 1) { if (n) { - Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, cparse_file, cparse_line, "Instantiation of template '%s' is ambiguous,\n", SwigType_namestr(tname)); - Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, Getfile(n), Getline(n), " instantiation '%s' is used.\n", SwigType_namestr(Getattr(n, "name"))); + Node *tn; + String *nodeType = nodeType(n); + if (Equal(nodeType, "template")) { + if (template_debug) { + Printf(stdout, " explicit specialization found: '%s'\n", Getattr(n, "name")); + } + goto success; + } + tn = Getattr(n, "template"); + if (tn) { + if (template_debug) { + Printf(stdout, " previous instantiation found: '%s'\n", Getattr(n, "name")); + } + n = tn; + goto success; /* Previously wrapped by a template instantiation */ + } + Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n)); + Delete(tname); + Delete(parms); + return 0; /* Found a match, but it's not a template of any kind. */ } } + + /* Search for partial specializations. + * Example: template class name { ... } + + * There are 3 types of template arguments: + * (1) Template type arguments + * (2) Template non type arguments + * (3) Template template arguments + * only (1) is really supported for partial specializations + */ + + /* Rank each template parameter against the desired template parameters then build a matrix of best matches */ + possiblepartials = NewList(); + { + char tmp[32]; + List *partials; + + partials = Getattr(templ, "partials"); /* note that these partial specializations do not include explicit specializations */ + if (partials) { + Iterator pi; + int parms_len = ParmList_len(parms); + int *priorities_row; + max_possible_partials = Len(partials); + priorities_matrix = (int *)malloc(sizeof(int) * max_possible_partials * parms_len); /* slightly wasteful allocation for max possible matches */ + priorities_row = priorities_matrix; + for (pi = First(partials); pi.item; pi = Next(pi)) { + Parm *p = parms; + int all_parameters_match = 1; + int i = 1; + Parm *partialparms = Getattr(pi.item, "partialparms"); + Parm *pp = partialparms; + String *templcsymname = Getattr(pi.item, "templcsymname"); + if (template_debug) { + Printf(stdout, " checking match: '%s' (partial specialization)\n", templcsymname); + } + if (ParmList_len(partialparms) == parms_len) { + while (p && pp) { + SwigType *t; + sprintf(tmp, "$%d", i); + t = Getattr(p, "type"); + if (!t) + t = Getattr(p, "value"); + if (t) { + EMatch match = does_parm_match(t, Getattr(pp, "type"), tmp, tscope, priorities_row + i - 1); + if (match < (int)PartiallySpecializedMatch) { + all_parameters_match = 0; + break; + } + } + i++; + p = nextSibling(p); + pp = nextSibling(pp); + } + if (all_parameters_match) { + Append(possiblepartials, pi.item); + priorities_row += parms_len; + } + } + } + } + } + + posslen = Len(possiblepartials); + if (template_debug) { + int i; + if (posslen == 0) + Printf(stdout, " matched partials: NONE\n"); + else if (posslen == 1) + Printf(stdout, " chosen partial: '%s'\n", Getattr(Getitem(possiblepartials, 0), "templcsymname")); + else { + Printf(stdout, " possibly matched partials:\n"); + for (i = 0; i < posslen; i++) { + Printf(stdout, " '%s'\n", Getattr(Getitem(possiblepartials, i), "templcsymname")); + } + } + } + + if (posslen > 1) { + /* Now go through all the possibly matched partial specialization templates and look for a non-ambiguous match. + * Exact matches rank the highest and deduced parameters are ranked by how much they are reduced, eg looking for + * a match to const int *, the following rank (highest to lowest): + * const int * (exact match) + * const T * + * T * + * T + * + * An ambiguous example when attempting to match as either specialization could match: %template() X; + * template X class {}; // primary template + * template X class {}; // specialization (1) + * template X class {}; // specialization (2) + */ + if (template_debug) { + int row, col; + int parms_len = ParmList_len(parms); + Printf(stdout, " parameter priorities matrix (%d parms):\n", parms_len); + for (row = 0; row < posslen; row++) { + int *priorities_row = priorities_matrix + row*parms_len; + Printf(stdout, " "); + for (col = 0; col < parms_len; col++) { + Printf(stdout, "%5d ", priorities_row[col]); + } + Printf(stdout, "\n"); + } + } + { + int row, col; + int parms_len = ParmList_len(parms); + /* Printf(stdout, " parameter priorities inverse matrix (%d parms):\n", parms_len); */ + for (col = 0; col < parms_len; col++) { + int *priorities_col = priorities_matrix + col; + int maxpriority = -1; + /* + Printf(stdout, "max_possible_partials: %d col:%d\n", max_possible_partials, col); + Printf(stdout, " "); + */ + /* determine the highest rank for this nth parameter */ + for (row = 0; row < posslen; row++) { + int *element_ptr = priorities_col + row*parms_len; + int priority = *element_ptr; + if (priority > maxpriority) + maxpriority = priority; + /* Printf(stdout, "%5d ", priority); */ + } + /* Printf(stdout, "\n"); */ + /* flag all the parameters which equal the highest rank */ + for (row = 0; row < posslen; row++) { + int *element_ptr = priorities_col + row*parms_len; + int priority = *element_ptr; + *element_ptr = (priority >= maxpriority) ? 1 : 0; + } + } + } + { + int row, col; + int parms_len = ParmList_len(parms); + Iterator pi = First(possiblepartials); + Node *chosenpartials = NewList(); + if (template_debug) + Printf(stdout, " priority flags matrix:\n"); + for (row = 0; row < posslen; row++) { + int *priorities_row = priorities_matrix + row*parms_len; + int highest_count = 0; /* count of highest priority parameters */ + for (col = 0; col < parms_len; col++) { + highest_count += priorities_row[col]; + } + if (template_debug) { + Printf(stdout, " "); + for (col = 0; col < parms_len; col++) { + Printf(stdout, "%5d ", priorities_row[col]); + } + Printf(stdout, "\n"); + } + if (highest_count == parms_len) { + Append(chosenpartials, pi.item); + } + pi = Next(pi); + } + if (Len(chosenpartials) > 0) { + /* one or more best match found */ + Delete(possiblepartials); + possiblepartials = chosenpartials; + posslen = Len(possiblepartials); + } else { + /* no best match found */ + Delete(chosenpartials); + } + } + } + + if (posslen > 0) { + String *s = Getattr(Getitem(possiblepartials, 0), "templcsymname"); + n = Swig_symbol_clookup_local(s, primary_scope); + if (posslen > 1) { + int i; + if (n) { + Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, cparse_file, cparse_line, "Instantiation of template '%s' is ambiguous,\n", SwigType_namestr(tname)); + Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, Getfile(n), Getline(n), " instantiation '%s' used,\n", SwigType_namestr(Getattr(n, "name"))); + } + for (i = 1; i < posslen; i++) { + String *templcsymname = Getattr(Getitem(possiblepartials, i), "templcsymname"); + Node *ignored_node = Swig_symbol_clookup_local(templcsymname, primary_scope); + Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, Getfile(ignored_node), Getline(ignored_node), " instantiation '%s' ignored.\n", SwigType_namestr(Getattr(ignored_node, "name"))); + } + } + } + + if (!n) { + if (template_debug) { + Printf(stdout, " chosen primary template: '%s'\n", Getattr(templ, "name")); + } + n = templ; + } + } else { + if (template_debug) { + Printf(stdout, " primary template not found\n"); + } + /* Give up if primary (unspecialized) template not found as specializations will only exist if there is a primary template */ + n = 0; } - if (!n) { - n = templ; - } if (!n) { Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", name); } else if (n) { @@ -609,13 +792,16 @@ static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) { } success: Delete(tname); - Delete(rname); - Delete(mpartials); + Delete(possiblepartials); if ((template_debug) && (n)) { + /* Printf(stdout, "Node: %p\n", n); Swig_print_node(n); + */ + Printf(stdout, " chosen template:'%s'\n", Getattr(n, "name")); } Delete(parms); + free(priorities_matrix); return n; } diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index e8fa159af..b400fbdeb 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -72,7 +72,7 @@ #define WARN_PARSE_PRIVATE_INHERIT 309 #define WARN_PARSE_TEMPLATE_REPEAT 310 #define WARN_PARSE_TEMPLATE_PARTIAL 311 -#define WARN_PARSE_NESTED_CLASS 312 +#define WARN_PARSE_UNNAMED_NESTED_CLASS 312 #define WARN_PARSE_UNDEFINED_EXTERN 313 #define WARN_PARSE_KEYWORD 314 #define WARN_PARSE_USING_UNDEF 315 @@ -84,6 +84,8 @@ #define WARN_PARSE_BUILTIN_NAME 321 #define WARN_PARSE_REDUNDANT 322 #define WARN_PARSE_REC_INHERITANCE 323 +#define WARN_PARSE_NESTED_TEMPLATE 324 +#define WARN_PARSE_NAMED_NESTED_CLASS 325 #define WARN_IGNORE_OPERATOR_NEW 350 /* new */ #define WARN_IGNORE_OPERATOR_DELETE 351 /* delete */ diff --git a/Source/Makefile.am b/Source/Makefile.am index 0afb2bfb4..dea6faecd 100644 --- a/Source/Makefile.am +++ b/Source/Makefile.am @@ -87,7 +87,6 @@ eswig_SOURCES = CParse/cscanner.c \ Swig/typeobj.c \ Swig/typemap.c \ Swig/typesys.c \ - Swig/warn.c \ Swig/wrapfunc.c bin_PROGRAMS = eswig diff --git a/Source/Modules/allegrocl.cxx b/Source/Modules/allegrocl.cxx index 2f1b07296..bb5070a70 100644 --- a/Source/Modules/allegrocl.cxx +++ b/Source/Modules/allegrocl.cxx @@ -1900,14 +1900,15 @@ static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { if (!nodes[j].error) { if (script_lang_wrapping) { Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded %s(%s) const ignored. Non-const method at %s:%d used.\n", - Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms), Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), + "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); } else { if (!Getattr(nodes[j].n, "overload:ignore")) Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s(%s) ignored. Method %s(%s) const at %s:%d used.\n", - Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms), - Getattr(nodes[i].n, "name"), ParmList_errorstr(nodes[i].parms), Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), + "using %s instead.\n", Swig_name_decl(nodes[i].n)); } } nodes[j].error = 1; @@ -1916,14 +1917,15 @@ static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { if (!nodes[j].error) { if (script_lang_wrapping) { Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded %s(%s) const ignored. Non-const method at %s:%d used.\n", - Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms), Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), + "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); } else { if (!Getattr(nodes[j].n, "overload:ignore")) Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s(%s) const ignored. Method %s(%s) at %s:%d used.\n", - Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms), - Getattr(nodes[i].n, "name"), ParmList_errorstr(nodes[i].parms), Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), + "using %s instead.\n", Swig_name_decl(nodes[i].n)); } } nodes[j].error = 1; @@ -1937,15 +1939,15 @@ static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { if (!nodes[j].error) { if (script_lang_wrapping) { Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s is shadowed by %s at %s:%d.\n", - Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), - Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n), + "as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n)); } else { if (!Getattr(nodes[j].n, "overload:ignore")) Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored. Method %s at %s:%d used.\n", - Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), - Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), + "using %s instead.\n", Swig_name_decl(nodes[i].n)); } nodes[j].error = 1; } diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx index d78dd13d7..e37358be6 100644 --- a/Source/Modules/allocate.cxx +++ b/Source/Modules/allocate.cxx @@ -518,7 +518,7 @@ class Allocate:public Dispatcher { */ String *scatchlist = Getattr(n, "feature:catches"); if (scatchlist) { - catchlist = Swig_cparse_parms(scatchlist); + catchlist = Swig_cparse_parms(scatchlist, n); if (catchlist) { Setattr(n, "catchlist", catchlist); mark_exception_classes(catchlist); diff --git a/Source/Modules/cffi.cxx b/Source/Modules/cffi.cxx index 062b9f0ff..09e97f448 100644 --- a/Source/Modules/cffi.cxx +++ b/Source/Modules/cffi.cxx @@ -618,12 +618,12 @@ int CFFI::enumDeclaration(Node *n) { slot_name_keywords = true; //Registering the enum name to the cin and cout typemaps - Parm *pattern = NewParm(name, NULL); + 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); + 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); @@ -688,7 +688,7 @@ void CFFI::emit_class(Node *n) { 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); + Parm *pattern = NewParm(Getattr(n, "name"), NULL, n); Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL); SwigType_add_pointer(Getattr(pattern, "type")); @@ -758,7 +758,7 @@ void CFFI::emit_class(Node *n) { Delete(supers); // Delete(ns_list); - // Parm *pattern = NewParm(name,NULL); + // 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); @@ -787,12 +787,12 @@ void CFFI::emit_struct_union(Node *n, bool un = false) { //Register the struct/union name to the cin and cout typemaps - Parm *pattern = NewParm(name, NULL); + 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); + 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); diff --git a/Source/Modules/clisp.cxx b/Source/Modules/clisp.cxx index 46c5ef84a..2dc30667f 100644 --- a/Source/Modules/clisp.cxx +++ b/Source/Modules/clisp.cxx @@ -452,7 +452,7 @@ String *CLISP::get_ffi_type(Node *n, SwigType *ty) { SwigType *cp = Copy(ty); SwigType *fn = SwigType_pop_function(cp); String *args = NewString(""); - ParmList *pl = SwigType_function_parms(fn); + ParmList *pl = SwigType_function_parms(fn, n); if (ParmList_len(pl) != 0) { Printf(args, "(:arguments "); } diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index b5444d4b4..7fb481271 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -86,13 +86,6 @@ class CSHARP:public Language { enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum }; - static Parm *NewParmFromNode(SwigType *type, const_String_or_char_ptr name, Node *n) { - Parm *p = NewParm(type, name); - Setfile(p, Getfile(n)); - Setline(p, Getline(n)); - return p; - } - public: /* ----------------------------------------------------------------------------- @@ -1211,6 +1204,9 @@ public: String *symname = Getattr(n, "sym:name"); String *value = Getattr(n, "value"); String *name = Getattr(n, "name"); + Node *parent = parentNode(n); + int unnamedinstance = GetFlag(parent, "unnamedinstance"); + String *parent_name = Getattr(parent, "name"); String *tmpValue; // Strange hack from parent method @@ -1222,13 +1218,18 @@ public: Setattr(n, "value", tmpValue); { - EnumFeature enum_feature = decodeEnumFeature(parentNode(n)); + EnumFeature enum_feature = decodeEnumFeature(parent); + const String *csattributes = Getattr(n, "feature:cs:attributes"); - if ((enum_feature == ProperEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) { + if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) { // Wrap (non-anonymous) C/C++ enum with a proper C# enum // Emit the enum item. if (!GetFlag(n, "firstenumitem")) Printf(enum_code, ",\n"); + + if (csattributes) + Printf(enum_code, " %s\n", csattributes); + Printf(enum_code, " %s", symname); // Check for the %csconstvalue feature @@ -1241,21 +1242,19 @@ public: } } else { // Wrap C/C++ enums with constant integers or use the typesafe enum pattern - const String *parent_name = Getattr(parentNode(n), "name"); - String *typemap_lookup_type = parent_name ? Copy(parent_name) : NewString("int"); + String *type = Getattr(n, "type"); /* should be int unless explicitly specified in a C++0x enum class */ + SwigType *typemap_lookup_type = parent_name ? parent_name : type; const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF); + String *return_type = Copy(tm); - Delete(typemap_lookup_type); - typemap_lookup_type = NULL; - - // The %csconst feature determines how the constant value is obtained - int const_feature_flag = GetFlag(n, "feature:cs:const"); - const String *methodmods = Getattr(n, "feature:cs:methodmodifiers"); methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); - if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) { - // Wrap (non-anonymouse) enum using the typesafe enum pattern + if (csattributes) + Printf(enum_code, " %s\n", csattributes); + + if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) { + // Wrap (non-anonymous) enum using the typesafe enum pattern if (Getattr(n, "enumvalue")) { String *value = enumValue(n); Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value); @@ -1267,6 +1266,10 @@ public: // Simple integer constants // Note these are always generated for anonymous enums, no matter what enum_feature is specified // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later + + // The %csconst feature determines how the constant value is obtained + int const_feature_flag = GetFlag(n, "feature:cs:const"); + const char *const_readonly = const_feature_flag ? "const" : "static readonly"; String *value = enumValue(n); Printf(enum_code, " %s %s %s %s = %s;\n", methodmods, const_readonly, return_type, symname, value); @@ -1275,9 +1278,9 @@ public: } // Add the enum value to the comma separated list being constructed in the enum declaration. - String *enumvalues = Getattr(parentNode(n), "enumvalues"); + String *enumvalues = Getattr(parent, "enumvalues"); if (!enumvalues) - Setattr(parentNode(n), "enumvalues", Copy(symname)); + Setattr(parent, "enumvalues", Copy(symname)); else Printv(enumvalues, ", ", symname, NIL); } @@ -1384,7 +1387,14 @@ public: enum_constant_flag = false; } else { // Alternative constant handling will use the C syntax to make a true C# constant and hope that it compiles as C# code - Printf(constants_code, "%s;\n", Getattr(n, "value")); + if (Getattr(n, "wrappedasconstant")) { + if (SwigType_type(t) == T_CHAR) + Printf(constants_code, "\'%s\';\n", Getattr(n, "staticmembervariableHandler:value")); + else + Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value")); + } else { + Printf(constants_code, "%s;\n", Getattr(n, "value")); + } } // Emit the generated code to appropriate place @@ -3314,7 +3324,7 @@ public: } /* Create the intermediate class wrapper */ - Parm *tp = NewParmFromNode(returntype, empty_str, n); + Parm *tp = NewParm(returntype, empty_str, n); tm = Swig_typemap_lookup("imtype", tp, "", 0); if (tm) { @@ -3334,7 +3344,7 @@ public: Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0)); } - Parm *retpm = NewParmFromNode(returntype, empty_str, n); + Parm *retpm = NewParm(returntype, empty_str, n); if ((c_ret_type = Swig_typemap_lookup("ctype", retpm, "", 0))) { @@ -3421,7 +3431,7 @@ public: if (ctypeout) c_param_type = ctypeout; - Parm *tp = NewParmFromNode(c_param_type, empty_str, n); + Parm *tp = NewParm(c_param_type, empty_str, n); String *desc_tm = NULL; /* Add to local variables */ @@ -3576,7 +3586,7 @@ public: String *upcall = NewStringf("%s(%s)", symname, imcall_args); if (!is_void) { - Parm *tp = NewParmFromNode(returntype, empty_str, n); + Parm *tp = NewParm(returntype, empty_str, n); if ((tm = Swig_typemap_lookup("csdirectorout", tp, "", 0))) { substituteClassname(returntype, tm); @@ -3602,7 +3612,7 @@ public: if (!is_void) { String *jresult_str = NewString("jresult"); String *result_str = NewString("c_result"); - Parm *tp = NewParmFromNode(returntype, result_str, n); + Parm *tp = NewParm(returntype, result_str, n); /* Copy jresult into c_result... */ if ((tm = Swig_typemap_lookup("directorout", tp, result_str, w))) { diff --git a/Source/Modules/guile.cxx b/Source/Modules/guile.cxx index 0c72de8d0..38ee7b9f5 100644 --- a/Source/Modules/guile.cxx +++ b/Source/Modules/guile.cxx @@ -1407,16 +1407,18 @@ public: } { /* Hack alert: will cleanup later -- Dave */ - Node *n = NewHash(); - Setattr(n, "name", var_name); - Setattr(n, "sym:name", iname); - Setattr(n, "type", nctype); - SetFlag(n, "feature:immutable"); + Node *nn = NewHash(); + Setfile(nn, Getfile(n)); + Setline(nn, Getline(n)); + Setattr(nn, "name", var_name); + Setattr(nn, "sym:name", iname); + Setattr(nn, "type", nctype); + SetFlag(nn, "feature:immutable"); if (constasvar) { - SetFlag(n, "feature:constasvar"); + SetFlag(nn, "feature:constasvar"); } - variableWrapper(n); - Delete(n); + variableWrapper(nn); + Delete(nn); } Delete(var_name); Delete(nctype); diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 9af6fc214..5eb6dcae9 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -83,13 +83,6 @@ class JAVA:public Language { enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum }; - static Parm *NewParmFromNode(SwigType *type, const_String_or_char_ptr name, Node *n) { - Parm *p = NewParm(type, name); - Setfile(p, Getfile(n)); - Setline(p, Getline(n)); - return p; - } - public: /* ----------------------------------------------------------------------------- @@ -1267,6 +1260,9 @@ public: String *symname = Getattr(n, "sym:name"); String *value = Getattr(n, "value"); String *name = Getattr(n, "name"); + Node *parent = parentNode(n); + int unnamedinstance = GetFlag(parent, "unnamedinstance"); + String *parent_name = Getattr(parent, "name"); String *tmpValue; // Strange hack from parent method @@ -1278,9 +1274,9 @@ public: Setattr(n, "value", tmpValue); { - EnumFeature enum_feature = decodeEnumFeature(parentNode(n)); + EnumFeature enum_feature = decodeEnumFeature(parent); - if ((enum_feature == ProperEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) { + if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) { // Wrap (non-anonymous) C/C++ enum with a proper Java enum // Emit the enum item. if (!GetFlag(n, "firstenumitem")) @@ -1293,18 +1289,16 @@ public: } } else { // Wrap C/C++ enums with constant integers or use the typesafe enum pattern - const String *parent_name = Getattr(parentNode(n), "name"); - String *typemap_lookup_type = parent_name ? Copy(parent_name) : NewString("int"); + String *type = Getattr(n, "type"); /* should be int unless explicitly specified in a C++0x enum class */ + SwigType *typemap_lookup_type = parent_name ? parent_name : type; const String *tm = typemapLookup(n, "jstype", typemap_lookup_type, WARN_JAVA_TYPEMAP_JSTYPE_UNDEF); - String *return_type = Copy(tm); - Delete(typemap_lookup_type); - typemap_lookup_type = NULL; + String *return_type = Copy(tm); const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); - if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) { - // Wrap (non-anonymouse) enum using the typesafe enum pattern + if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) { + // Wrap (non-anonymous) enum using the typesafe enum pattern if (Getattr(n, "enumvalue")) { String *value = enumValue(n); Printf(enum_code, " %s final static %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value); @@ -1323,9 +1317,9 @@ public: } // Add the enum value to the comma separated list being constructed in the enum declaration. - String *enumvalues = Getattr(parentNode(n), "enumvalues"); + String *enumvalues = Getattr(parent, "enumvalues"); if (!enumvalues) - Setattr(parentNode(n), "enumvalues", Copy(symname)); + Setattr(parent, "enumvalues", Copy(symname)); else Printv(enumvalues, ", ", symname, NIL); } @@ -1425,7 +1419,14 @@ public: enum_constant_flag = false; } else { // Alternative constant handling will use the C syntax to make a true Java constant and hope that it compiles as Java code - Printf(constants_code, "%s;\n", Getattr(n, "value")); + if (Getattr(n, "wrappedasconstant")) { + if (SwigType_type(t) == T_CHAR) + Printf(constants_code, "\'%s\';\n", Getattr(n, "staticmembervariableHandler:value")); + else + Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value")); + } else { + Printf(constants_code, "%s;\n", Getattr(n, "value")); + } } // Emit the generated code to appropriate place @@ -1973,7 +1974,7 @@ public: if (qualifier) SwigType_push(this_type, qualifier); SwigType_add_pointer(this_type); - Parm *this_parm = NewParm(this_type, name); + Parm *this_parm = NewParm(this_type, name, n); Swig_typemap_attach_parms("jtype", this_parm, NULL); Swig_typemap_attach_parms("jstype", this_parm, NULL); @@ -3381,7 +3382,7 @@ public: } /* Create the intermediate class wrapper */ - Parm *tp = NewParmFromNode(returntype, empty_str, n); + Parm *tp = NewParm(returntype, empty_str, n); tm = Swig_typemap_lookup("jtype", tp, "", 0); if (tm) { @@ -3393,7 +3394,7 @@ public: String *cdesc = NULL; SwigType *covariant = Getattr(n, "covariant"); SwigType *adjustedreturntype = covariant ? covariant : returntype; - Parm *adjustedreturntypeparm = NewParmFromNode(adjustedreturntype, empty_str, n); + Parm *adjustedreturntypeparm = NewParm(adjustedreturntype, empty_str, n); if ((tm = Swig_typemap_lookup("directorin", adjustedreturntypeparm, "", 0)) && (cdesc = Getattr(adjustedreturntypeparm, "tmap:directorin:descriptor"))) { @@ -3413,10 +3414,10 @@ public: /* Get the JNI field descriptor for this return type, add the JNI field descriptor to jniret_desc */ - Parm *retpm = NewParmFromNode(returntype, empty_str, n); + Parm *retpm = NewParm(returntype, empty_str, n); if ((c_ret_type = Swig_typemap_lookup("jni", retpm, "", 0))) { - Parm *tp = NewParmFromNode(c_ret_type, empty_str, n); + Parm *tp = NewParm(c_ret_type, empty_str, n); if (!is_void && !ignored_method) { String *jretval_decl = NewStringf("%s jresult", c_ret_type); @@ -3518,7 +3519,7 @@ public: } /* Start the Java field descriptor for the intermediate class's upcall (insert self object) */ - Parm *tp = NewParmFromNode(c_classname, empty_str, n); + Parm *tp = NewParm(c_classname, empty_str, n); String *jdesc; if ((tm = Swig_typemap_lookup("directorin", tp, "", 0)) @@ -3560,7 +3561,7 @@ public: /* Get parameter's intermediary C type */ if ((c_param_type = Getattr(p, "tmap:jni"))) { - Parm *tp = NewParmFromNode(c_param_type, empty_str, n); + Parm *tp = NewParm(c_param_type, empty_str, n); String *desc_tm = NULL, *jdesc = NULL, *cdesc = NULL; /* Add to local variables */ @@ -3716,8 +3717,11 @@ public: String *upcall = NewStringf("self.%s(%s)", symname, imcall_args); + // Handle exception classes specified in the "except" feature's "throws" attribute + addThrows(n, "feature:except", n); + if (!is_void) { - Parm *tp = NewParmFromNode(returntype, empty_str, n); + Parm *tp = NewParm(returntype, empty_str, n); if ((tm = Swig_typemap_lookup("javadirectorout", tp, "", 0))) { addThrows(n, "tmap:javadirectorout", tp); @@ -3761,7 +3765,7 @@ public: if (!is_void) { String *jresult_str = NewString("jresult"); String *result_str = NewString("c_result"); - Parm *tp = NewParmFromNode(returntype, result_str, n); + Parm *tp = NewParm(returntype, result_str, n); /* Copy jresult into c_result... */ if ((tm = Swig_typemap_lookup("directorout", tp, result_str, w))) { @@ -3854,7 +3858,7 @@ public: SwigType_add_pointer(jenv_type); - p = NewParmFromNode(jenv_type, NewString("jenv"), n); + p = NewParm(jenv_type, NewString("jenv"), n); Setattr(p, "arg:byname", "1"); set_nextSibling(p, NULL); @@ -3891,7 +3895,7 @@ public: String *jenv_type = NewString("JNIEnv"); SwigType_add_pointer(jenv_type); - p = NewParmFromNode(jenv_type, NewString("jenv"), n); + p = NewParm(jenv_type, NewString("jenv"), n); set_nextSibling(p, parms); parms = p; diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index e58f2b022..3228a2cc1 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -175,7 +175,7 @@ int Dispatcher::emit_one(Node *n) { } else if (strcmp(tag, "types") == 0) { ret = typesDirective(n); } else { - Printf(stderr, "%s:%d. Unrecognized parse tree node type '%s'\n", input_file, line_number, tag); + Swig_error(input_file, line_number, "Unrecognized parse tree node type '%s'\n", tag); ret = SWIG_ERROR; } if (wrn) { @@ -900,7 +900,7 @@ int Language::cDeclaration(Node *n) { Delete(ty); ty = fullty; fullty = 0; - ParmList *parms = SwigType_function_parms(ty); + ParmList *parms = SwigType_function_parms(ty, n); Setattr(n, "parms", parms); } /* Transform the node into a 'function' node and emit */ @@ -1188,6 +1188,8 @@ int Language::memberfunctionHandler(Node *n) { Setattr(cbn, "type", cbty); Setattr(cbn, "value", cbvalue); Setattr(cbn, "name", name); + Setfile(cbn, Getfile(n)); + Setline(cbn, Getline(n)); memberconstantHandler(cbn); Setattr(n, "feature:callback:name", Swig_name_member(ClassPrefix, cbname)); @@ -1407,39 +1409,36 @@ int Language::membervariableHandler(Node *n) { target = NewStringf("%s->%s", pname, name); Delete(pname); } - } else { - target = NewStringf("$extendgetcall"); // member variable access expanded later + tm = Swig_typemap_lookup("memberin", n, target, 0); } - tm = Swig_typemap_lookup("memberin", n, target, 0); int flags = Extend | SmartPointer | use_naturalvar_mode(n); if (is_non_virtual_protected_access(n)) flags = flags | CWRAP_ALL_PROTECTED_ACCESS; - String *call = 0; - Swig_MembersetToFunction(n, ClassType, flags, &call); + Swig_MembersetToFunction(n, ClassType, flags); Setattr(n, "memberset", "1"); + if (!Extend) { + /* Check for a member in typemap here */ - if (!tm) { - if (SwigType_isarray(type)) { - Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(type, 0)); - make_set_wrapper = 0; + if (!tm) { + if (SwigType_isarray(type)) { + Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(type, 0)); + make_set_wrapper = 0; + } + } else { + String *pname0 = Swig_cparm_name(0, 0); + String *pname1 = Swig_cparm_name(0, 1); + Replace(tm, "$source", pname1, DOH_REPLACE_ANY); + Replace(tm, "$target", target, DOH_REPLACE_ANY); + Replace(tm, "$input", pname1, DOH_REPLACE_ANY); + Replace(tm, "$self", pname0, DOH_REPLACE_ANY); + Setattr(n, "wrap:action", tm); + Delete(tm); + Delete(pname0); + Delete(pname1); } - } else { - String *pname0 = Swig_cparm_name(0, 0); - String *pname1 = Swig_cparm_name(0, 1); - Replace(tm, "$source", pname1, DOH_REPLACE_ANY); - Replace(tm, "$target", target, DOH_REPLACE_ANY); - Replace(tm, "$input", pname1, DOH_REPLACE_ANY); - Replace(tm, "$self", pname0, DOH_REPLACE_ANY); - Replace(tm, "$extendgetcall", call, DOH_REPLACE_ANY); - Setattr(n, "wrap:action", tm); - Delete(tm); - Delete(pname0); - Delete(pname1); + Delete(target); } - Delete(call); - Delete(target); - if (make_set_wrapper) { Setattr(n, "sym:name", mrename_set); functionWrapper(n); @@ -1481,7 +1480,7 @@ int Language::membervariableHandler(Node *n) { Parm *p; String *gname; SwigType *vty; - p = NewParm(type, 0); + p = NewParm(type, 0, n); gname = NewStringf(AttributeFunctionGet, symname); if (!Extend) { ActionFunc = Copy(Swig_cmemberget_call(name, type)); @@ -1907,12 +1906,14 @@ int Language::classDirectorDisown(Node *n) { String *type = NewString(ClassType); String *name = NewString("self"); SwigType_add_pointer(type); - Parm *p = NewParm(type, name); + Parm *p = NewParm(type, name, n); Delete(name); Delete(type); type = NewString("void"); String *action = NewString(""); Printv(action, "{\n", "Swig::Director *director = dynamic_cast(arg1);\n", "if (director) director->swig_disown();\n", "}\n", NULL); + Setfile(disown, Getfile(n)); + Setline(disown, Getline(n)); Setattr(disown, "wrap:action", action); Setattr(disown, "name", mrename); Setattr(disown, "sym:name", mrename); @@ -2165,7 +2166,7 @@ static void addCopyConstructor(Node *n) { if (!symname) { symname = Copy(csymname); } - Parm *p = NewParm(cc, "other"); + Parm *p = NewParm(cc, "other", n); Setattr(cn, "name", name); Setattr(cn, "sym:name", symname); diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index c824db6f9..34914efa3 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -62,11 +62,16 @@ static const char *usage1 = (const char *) "\ -copyright - Display copyright notices\n\ -debug-classes - Display information about the classes found in the interface\n\ -debug-module - Display module parse tree at stages 1-4, is a csv list of stages\n\ + -debug-symtabs - Display symbol tables information\n\ + -debug-symbols - Display target language symbols in the symbol tables\n\ + -debug-csymbols - Display C symbols in the symbol tables\n\ -debug-tags - Display information about the tags found in the interface\n\ -debug-template - Display information for debugging templates\n\ -debug-top - Display entire parse tree at stages 1-4, is a csv list of stages\n\ -debug-typedef - Display information about the types and typedefs in the interface\n\ - -debug-typemap - Display information for debugging typemaps\n\ + -debug-typemap - Display typemap debugging information\n\ + -debug-tmsearch - Display typemap search debugging information\n\ + -debug-tmused - Display typemaps used debugging information\n\ -directors - Turn on director mode for all the classes, mainly for testing\n\ -dirprot - Turn on wrapping of protected members for director classes (default)\n\ -D - Define a symbol (for conditional compilation)\n\ @@ -162,6 +167,9 @@ static int no_cpp = 0; static char *outfile_name = 0; static char *outfile_name_h = 0; static int tm_debug = 0; +static int dump_symtabs = 0; +static int dump_symbols = 0; +static int dump_csymbols = 0; static int dump_tags = 0; static int dump_module = 0; static int dump_top = 0; @@ -649,6 +657,12 @@ void SWIG_getoptions(int argc, char *argv[]) { } else if ((strcmp(argv[i], "-debug-typemap") == 0) || (strcmp(argv[i], "-debug_typemap") == 0) || (strcmp(argv[i], "-tm_debug") == 0)) { tm_debug = 1; Swig_mark_arg(i); + } else if (strcmp(argv[i], "-debug-tmsearch") == 0) { + Swig_typemap_search_debug_set(); + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-debug-tmused") == 0) { + Swig_typemap_used_debug_set(); + Swig_mark_arg(i); } else if (strcmp(argv[i], "-module") == 0) { Swig_mark_arg(i); if (argv[i + 1]) { @@ -716,6 +730,15 @@ void SWIG_getoptions(int argc, char *argv[]) { } else if (strncmp(argv[i], "-w", 2) == 0) { Swig_mark_arg(i); Swig_warnfilter(argv[i] + 2, 1); + } else if (strcmp(argv[i], "-debug-symtabs") == 0) { + dump_symtabs = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-debug-symbols") == 0) { + dump_symbols = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-debug-csymbols") == 0) { + dump_csymbols = 1; + Swig_mark_arg(i); } else if ((strcmp(argv[i], "-debug-tags") == 0) || (strcmp(argv[i], "-dump_tags") == 0)) { dump_tags = 1; Swig_mark_arg(i); @@ -829,12 +852,6 @@ int SWIG_main(int argc, char *argv[], Language *l) { Preprocessor_define((DOH *) "SWIG 1", 0); Preprocessor_define((DOH *) "__STDC__", 0); -#ifdef MACSWIG - Preprocessor_define((DOH *) "SWIGMAC 1", 0); -#endif -#ifdef SWIGWIN32 - Preprocessor_define((DOH *) "SWIGWIN32 1", 0); -#endif // 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 */ @@ -1145,6 +1162,19 @@ int SWIG_main(int argc, char *argv[], Language *l) { SwigType_print_scope(0); } + if (dump_symtabs) { + Swig_symbol_print_tables(Swig_symbol_global_scope()); + Swig_symbol_print_tables_summary(); + } + + if (dump_symbols) { + Swig_symbol_print_symbols(); + } + + if (dump_csymbols) { + Swig_symbol_print_csymbols(); + } + if (dump_tags) { Swig_print_tags(top, 0); } diff --git a/Source/Modules/modula3.cxx b/Source/Modules/modula3.cxx index b14dddd22..7440d906a 100644 --- a/Source/Modules/modula3.cxx +++ b/Source/Modules/modula3.cxx @@ -81,7 +81,7 @@ char cvsroot_modula3_cxx[] = "$Id$"; that assign special purposes to the array types. - Can one interpret $n_basetype as the identifier matched with SWIGTYPE ? - Swig's odds: + SWIG's odds: - arguments of type (Node *) for SWIG functions should be most often better (const Node *): Swig_symbol_qualified, Getattr, nodeType, parentNode diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx index 28dd8ecd2..1641b719a 100644 --- a/Source/Modules/mzscheme.cxx +++ b/Source/Modules/mzscheme.cxx @@ -647,13 +647,15 @@ public: { /* Hack alert: will cleanup later -- Dave */ - Node *n = NewHash(); - Setattr(n, "name", var_name); - Setattr(n, "sym:name", iname); - Setattr(n, "type", type); - SetFlag(n, "feature:immutable"); - variableWrapper(n); - Delete(n); + Node *nn = NewHash(); + Setfile(nn, Getfile(n)); + Setline(nn, Getline(n)); + Setattr(nn, "name", var_name); + Setattr(nn, "sym:name", iname); + Setattr(nn, "type", type); + SetFlag(nn, "feature:immutable"); + variableWrapper(nn); + Delete(nn); } } Delete(proc_name); @@ -762,7 +764,7 @@ public: Printv(access_mem, "(ptr)->", name, NIL); if ((SwigType_type(type) == T_USER) && (!is_a_pointer(type))) { Printv(convert_tab, tab4, "fields[i++] = ", NIL); - Printv(convert_tab, "_swig_convert_struct_", swigtype, "((", SwigType_str(ctype_ptr, ""), ")&((ptr)->", name, "));\n", NIL); + Printv(convert_tab, "_swig_convert_struct_", swigtype, "((", SwigType_str(ctype_ptr, 0), ")&((ptr)->", name, "));\n", NIL); } else if ((tm = Swig_typemap_lookup("varout", n, access_mem, 0))) { Replaceall(tm, "$result", "fields[i++]"); Printv(convert_tab, tm, "\n", NIL); diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx index 8a797759c..cfd4fc682 100644 --- a/Source/Modules/ocaml.cxx +++ b/Source/Modules/ocaml.cxx @@ -1727,7 +1727,7 @@ public: ParmList *superparms = Getattr(n, "parms"); ParmList *parms = CopyParmList(superparms); String *type = NewString("CAML_VALUE"); - p = NewParm(type, NewString("self")); + p = NewParm(type, NewString("self"), n); q = Copy(p); set_nextSibling(q, superparms); set_nextSibling(p, parms); @@ -1780,7 +1780,7 @@ public: ParmList *superparms = Getattr(n, "parms"); ParmList *parms = CopyParmList(superparms); String *type = NewString("CAML_VALUE"); - p = NewParm(type, NewString("self")); + p = NewParm(type, NewString("self"), n); q = Copy(p); set_nextSibling(p, parms); parms = p; diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index aeb72f77a..ff880fc5a 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -13,7 +13,7 @@ char cvsroot_octave_cxx[] = "$Id$"; static const char *usage = (char *) "\ Octave Options (available with -octave)\n\ - -api - Generate code that assumes Octave API N [default: 37]\n\ + [no additional options]\n\ \n"; @@ -36,8 +36,6 @@ private: int have_destructor; String *constructor_name; - int api_version; - Hash *docs; public: @@ -56,7 +54,6 @@ public: director_multiple_inheritance = 1; director_language = 1; docs = NewHash(); - api_version = 0; } virtual void main(int argc, char *argv[]) { @@ -64,15 +61,6 @@ public: if (argv[i]) { if (strcmp(argv[i], "-help") == 0) { fputs(usage, stderr); - } else if (strcmp(argv[i], "-api") == 0) { - if (argv[i + 1]) { - api_version = atoi(argv[i + 1]); - Swig_mark_arg(i); - Swig_mark_arg(i + 1); - i++; - } else { - Swig_arg_error(); - } } } } @@ -138,7 +126,6 @@ public: Printf(f_runtime, "#define SWIGOCTAVE\n"); Printf(f_runtime, "#define SWIG_name_d \"%s\"\n", module); Printf(f_runtime, "#define SWIG_name %s\n", module); - Printf(f_runtime, "#define OCTAVE_API_VERSION_OPTION %i\n", api_version); if (directorsEnabled()) { Printf(f_runtime, "#define SWIG_DIRECTORS\n"); @@ -969,7 +956,7 @@ public: String *name = NewString("self"); String *type = NewString("void"); SwigType_add_pointer(type); - self = NewParm(type, name); + self = NewParm(type, name, n); Delete(type); Delete(name); Setattr(self, "lname", "self_obj"); @@ -1064,7 +1051,7 @@ public: ParmList *parms = CopyParmList(superparms); String *type = NewString("void"); SwigType_add_pointer(type); - p = NewParm(type, NewString("self")); + p = NewParm(type, NewString("self"), n); set_nextSibling(p, parms); parms = p; diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx index 79656517a..14c677783 100644 --- a/Source/Modules/overload.cxx +++ b/Source/Modules/overload.cxx @@ -223,13 +223,15 @@ static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { if (!nodes[j].error) { if (script_lang_wrapping) { Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored. Non-const method %s at %s:%d used.\n", - Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), + "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); } else { if (!Getattr(nodes[j].n, "overload:ignore")) Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored. Method %s at %s:%d used.\n", - Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), + "using %s instead.\n", Swig_name_decl(nodes[i].n)); } } nodes[j].error = 1; @@ -238,13 +240,15 @@ static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { if (!nodes[j].error) { if (script_lang_wrapping) { Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored. Non-const method %s at %s:%d used.\n", - Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), + "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); } else { if (!Getattr(nodes[j].n, "overload:ignore")) Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored. Method %s at %s:%d used.\n", - Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), + "using %s instead.\n", Swig_name_decl(nodes[i].n)); } } nodes[j].error = 1; @@ -258,15 +262,15 @@ static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { if (!nodes[j].error) { if (script_lang_wrapping) { Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s is shadowed by %s at %s:%d.\n", - Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), - Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n), + "as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n)); } else { if (!Getattr(nodes[j].n, "overload:ignore")) Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored. Method %s at %s:%d used.\n", - Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), - Getfile(nodes[i].n), Getline(nodes[i].n)); + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), + "using %s instead.\n", Swig_name_decl(nodes[i].n)); } nodes[j].error = 1; } diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index bae922e90..e98a16f7d 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1636,7 +1636,7 @@ public: } else { Node *parent = Swig_methodclass(n); String *classname = Swig_class_name(parent); - Printf(output, "\t\tif (get_class($this) === '%s') {\n", classname); + Printf(output, "\t\tif (get_class($this) === '%s%s') {\n", prefix, classname); Printf(output, "\t\t\t$_this = null;\n"); Printf(output, "\t\t} else {\n"); Printf(output, "\t\t\t$_this = $this;\n"); @@ -1684,7 +1684,7 @@ public: Printf(output, "\t\t\t$c='%s'.substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n", prefix); } Printf(output, "\t\t\tif (!class_exists($c)) {\n"); - Printf(output, "\t\t\t\treturn new %s($r);\n", Getattr(classLookup(d), "sym:name")); + Printf(output, "\t\t\t\treturn new %s%s($r);\n", prefix, Getattr(classLookup(d), "sym:name")); Printf(output, "\t\t\t}\n"); Printf(output, "\t\t\treturn new $c($r);\n"); } else { @@ -1929,9 +1929,7 @@ done: virtual int classHandler(Node *n) { constructors = 0; - //SwigType *t = Getattr(n, "classtype"); current_class = n; - // String *use_class_name=SwigType_manglestr(SwigType_ltype(t)); if (shadow) { char *rename = GetChar(n, "sym:name"); @@ -2325,7 +2323,7 @@ done: ParmList *parms = CopyParmList(superparms); String *type = NewString("zval"); SwigType_add_pointer(type); - p = NewParm(type, NewString("self")); + p = NewParm(type, NewString("self"), n); set_nextSibling(p, parms); parms = p; @@ -2538,7 +2536,24 @@ done: } p = nextSibling(p); } - Append(w->code, "int error;\n"); + + /* exception handling */ + tm = Swig_typemap_lookup("director:except", n, "result", 0); + if (!tm) { + tm = Getattr(n, "feature:director:except"); + if (tm) + tm = Copy(tm); + } + if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) { + if (Replaceall(tm, "$error", "error")) { + /* Only declare error if it is used by the typemap. */ + Append(w->code, "int error;\n"); + } + } else { + Delete(tm); + tm = NULL; + } + if (!idx) { Printf(w->code, "zval **args = NULL;\n", idx); } else { @@ -2557,18 +2572,10 @@ done: Append(w->code, "call_user_function(EG(function_table), (zval**)&swig_self, &funcname,\n"); Printf(w->code, " result, %d, args TSRMLS_CC);\n", idx); - /* exception handling */ - tm = Swig_typemap_lookup("director:except", n, "result", 0); - if (!tm) { - tm = Getattr(n, "feature:director:except"); - if (tm) - tm = Copy(tm); - } - if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) { - Replaceall(tm, "$error", "error"); + if (tm) { Printv(w->code, Str(tm), "\n", NIL); + Delete(tm); } - Delete(tm); /* marshal return value from PHP to C/C++ type */ diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 9475139a3..bc76f17d4 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -2625,7 +2625,7 @@ public: ParmList *parms = CopyParmList(superparms); String *type = NewString("PyObject"); SwigType_add_pointer(type); - p = NewParm(type, NewString("self")); + p = NewParm(type, NewString("self"), n); set_nextSibling(p, parms); parms = p; @@ -3205,7 +3205,7 @@ public: String *name = NewString("self"); String *type = NewString("PyObject"); SwigType_add_pointer(type); - self = NewParm(type, name); + self = NewParm(type, name, n); Delete(type); Delete(name); Setattr(self, "lname", "O"); diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index c48e2e266..13b832752 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -588,7 +588,7 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { // ParmList *parms = Getattr(n, "parms"); // memory leak - ParmList *parms = SwigType_function_parms(SwigType_del_pointer(Copy(t))); + ParmList *parms = SwigType_function_parms(SwigType_del_pointer(Copy(t)), n); // if (debugMode) { @@ -712,10 +712,7 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { XXX Have to be a little more clever so that we can deal with struct A * - the * is getting lost. Is this still true? If so, will a SwigType_push() solve things? */ - Node *bbase = NewHash(); - - Setattr(bbase, "type", rettype); - Setattr(bbase, "name", NewString("result")); + Parm *bbase = NewParm(rettype, "result", n); String *returnTM = Swig_typemap_lookup("in", bbase, "result", f); if(returnTM) { String *tm = returnTM; @@ -1101,7 +1098,7 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, Delete(pitem); } Delete(itemList); - Printf(f->code, ")\n"); + Printf(f->code, ");\n"); if (!isSet && varaccessor > 0) { Printf(f->code, "%svaccessors = c(", tab8); @@ -1117,7 +1114,7 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, Printf(f->code, "'%s'%s", item, vcount < varaccessor ? ", " : ""); } } - Printf(f->code, ")\n"); + Printf(f->code, ");\n"); } @@ -1129,24 +1126,24 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, "stop(\"No ", (isSet ? "modifiable" : "accessible"), " field named \", name, \" in ", className, ": fields are \", paste(names(accessorFuns), sep = \", \")", ")", "\n}\n", NIL); */ - Printv(f->code, tab8, - "idx = pmatch(name, names(accessorFuns))\n", + Printv(f->code, ";", tab8, + "idx = pmatch(name, names(accessorFuns));\n", tab8, "if(is.na(idx)) \n", tab8, tab4, NIL); - Printf(f->code, "return(callNextMethod(x, name%s))\n", + Printf(f->code, "return(callNextMethod(x, name%s));\n", isSet ? ", value" : ""); - Printv(f->code, tab8, "f = accessorFuns[[idx]]\n", NIL); + Printv(f->code, tab8, "f = accessorFuns[[idx]];\n", NIL); if(isSet) { - Printv(f->code, tab8, "f(x, value)\n", NIL); - Printv(f->code, tab8, "x\n", NIL); // make certain to return the S value. + Printv(f->code, tab8, "f(x, value);\n", NIL); + Printv(f->code, tab8, "x;\n", NIL); // make certain to return the S value. } else { - Printv(f->code, tab8, "formals(f)[[1]] = x\n", NIL); + Printv(f->code, tab8, "formals(f)[[1]] = x;\n", NIL); if (varaccessor) { Printv(f->code, tab8, - "if (is.na(match(name, vaccessors))) f else f(x)\n", NIL); + "if (is.na(match(name, vaccessors))) f else f(x);\n", NIL); } else { - Printv(f->code, tab8, "f\n", NIL); + Printv(f->code, tab8, "f;\n", NIL); } } Printf(f->code, "}\n"); @@ -1157,15 +1154,15 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, isSet ? "<-" : "", getRClassName(className)); Wrapper_print(f, out); - Printf(out, ")\n"); + Printf(out, ");\n"); if(isSet) { Printf(out, "setMethod('[[<-', c('_p%s', 'character'),", getRClassName(className)); - Insert(f->code, 2, "name = i\n"); + Insert(f->code, 2, "name = i;\n"); Printf(attr->code, "%s", f->code); Wrapper_print(attr, out); - Printf(out, ")\n"); + Printf(out, ");\n"); } DelWrapper(attr); @@ -1489,8 +1486,8 @@ static List * Swig_overload_rank(Node *n, } if (!differ) { /* See if declarations differ by const only */ - String *d1 = Getattr(nodes[i].n,"decl"); - String *d2 = Getattr(nodes[j].n,"decl"); + String *d1 = Getattr(nodes[i].n, "decl"); + String *d2 = Getattr(nodes[j].n, "decl"); if (d1 && d2) { String *dq1 = Copy(d1); String *dq2 = Copy(d2); @@ -1500,49 +1497,47 @@ static List * Swig_overload_rank(Node *n, if (SwigType_isconst(d2)) { Delete(SwigType_pop(dq2)); } - if (Strcmp(dq1,dq2) == 0) { - + if (Strcmp(dq1, dq2) == 0) { + if (SwigType_isconst(d1) && !SwigType_isconst(d2)) { - if (script_lang_wrapping) { - // Swap nodes so that the const method gets ignored (shadowed by the non-const method) - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } + if (script_lang_wrapping) { + // Swap nodes so that the const method gets ignored (shadowed by the non-const method) + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + } differ = 1; if (!nodes[j].error) { - if (script_lang_wrapping) { + if (script_lang_wrapping) { Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded %s(%s) const ignored. Non-const method at %s:%d used.\n", - Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms), - Getfile(nodes[i].n), Getline(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s(%s) ignored. Method %s(%s) const at %s:%d used.\n", - Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms), - Getattr(nodes[i].n,"name"), ParmList_errorstr(nodes[i].parms), - Getfile(nodes[i].n), Getline(nodes[i].n)); - } + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), + "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); + } else { + if (!Getattr(nodes[j].n, "overload:ignore")) + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), + "using %s instead.\n", Swig_name_decl(nodes[i].n)); + } } nodes[j].error = 1; } else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) { differ = 1; if (!nodes[j].error) { - if (script_lang_wrapping) { + if (script_lang_wrapping) { Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded %s(%s) const ignored. Non-const method at %s:%d used.\n", - Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms), - Getfile(nodes[i].n), Getline(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s(%s) const ignored. Method %s(%s) at %s:%d used.\n", - Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms), - Getattr(nodes[i].n,"name"), ParmList_errorstr(nodes[i].parms), - Getfile(nodes[i].n), Getline(nodes[i].n)); - } - } + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), + "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); + } else { + if (!Getattr(nodes[j].n, "overload:ignore")) + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), + "using %s instead.\n", Swig_name_decl(nodes[i].n)); + } + } nodes[j].error = 1; } } @@ -1552,18 +1547,18 @@ static List * Swig_overload_rank(Node *n, } if (!differ) { if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s is shadowed by %s at %s:%d.\n", - Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), - Getfile(nodes[i].n), Getline(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored. Method %s at %s:%d used.\n", - Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), - Getfile(nodes[i].n), Getline(nodes[i].n)); - } + if (script_lang_wrapping) { + Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), + "Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n), + "as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n)); + } else { + if (!Getattr(nodes[j].n, "overload:ignore")) + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), + "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); + Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), + "using %s instead.\n", Swig_name_decl(nodes[i].n)); + } nodes[j].error = 1; } } @@ -1601,9 +1596,9 @@ void R::dispatchFunction(Node *n) { List *dispatch = Swig_overload_rank(n, true); int nfunc = Len(dispatch); Printv(f->code, - "argtypes <- mapply(class, list(...))\n", - "argv <- list(...)\n", - "argc <- length(argtypes)\n", NIL ); + "argtypes <- mapply(class, list(...));\n", + "argv <- list(...);\n", + "argc <- length(argtypes);\n", NIL ); Printf(f->code, "# dispatch functions %d\n", nfunc); int cur_args = -1; @@ -1649,16 +1644,16 @@ void R::dispatchFunction(Node *n) { } p = Getattr(p, "tmap:in:next"); } - Printf(f->code, ") { f <- %s%s }\n", sfname, overname); + Printf(f->code, ") { f <- %s%s; }\n", sfname, overname); } else { - Printf(f->code, "f <- %s%s", sfname, overname); + Printf(f->code, "f <- %s%s; ", sfname, overname); } } if (cur_args != -1) { Printv(f->code, "}", NIL); } - Printv(f->code, "\nf(...)", NIL); - Printv(f->code, "\n}", NIL); + Printv(f->code, ";\nf(...)", NIL); + Printv(f->code, ";\n}", NIL); Wrapper_print(f, sfile); Printv(sfile, "# Dispatch function\n", NIL); DelWrapper(f); @@ -1886,16 +1881,16 @@ int R::functionWrapper(Node *n) { String *snargs = NewStringf("%d", nargs); Printv(sfun->code, "if(is.function(", name, ")) {", "\n", "assert('...' %in% names(formals(", name, - ")) || length(formals(", name, ")) >= ", snargs, ")\n} ", NIL); + ")) || length(formals(", name, ")) >= ", snargs, ");\n} ", NIL); Delete(snargs); Printv(sfun->code, "else {\n", "if(is.character(", name, ")) {\n", - name, " = getNativeSymbolInfo(", name, ")", - "\n}\n", + name, " = getNativeSymbolInfo(", name, ");", + "\n};\n", "if(is(", name, ", \"NativeSymbolInfo\")) {\n", - name, " = ", name, "$address", "\n}\n", - "}\n", + name, " = ", name, "$address", ";\n}\n", + "}; \n", NIL); } else { Printf(sfun->code, "%s\n", tm); @@ -2090,10 +2085,10 @@ int R::functionWrapper(Node *n) { } - Printv(sfun->code, (Len(tm) ? "ans = " : ""), ".Call('", wname, - "', ", sargs, "PACKAGE='", Rpackage, "')\n", NIL); + Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname, + "', ", sargs, "PACKAGE='", Rpackage, "');\n", NIL); if(Len(tm)) - Printf(sfun->code, "%s\n\nans\n", tm); + Printf(sfun->code, "%s\n\nans;\n", tm); if (destructor) Printv(f->code, "R_ClearExternalPtr(self);\n", NIL); @@ -2452,11 +2447,11 @@ int R::generateCopyRoutines(Node *n) { /* The S functions to get and set the member value. */ String *elNameT = replaceInitialDash(elName); - Printf(copyToR->code, "obj@%s = value$%s\n", elNameT, elNameT); - Printf(copyToC->code, "obj$%s = value@%s\n", elNameT, elNameT); + Printf(copyToR->code, "obj@%s = value$%s;\n", elNameT, elNameT); + Printf(copyToC->code, "obj$%s = value@%s;\n", elNameT, elNameT); Delete(elNameT); } - Printf(copyToR->code, "obj\n}\n\n"); + Printf(copyToR->code, "obj;\n}\n\n"); String *rclassName = getRClassNameCopyStruct(type, 0); // without the Ref. Printf(sfile, "# Start definition of copy functions & methods for %s\n", rclassName); @@ -2466,9 +2461,9 @@ int R::generateCopyRoutines(Node *n) { Printf(sfile, "# Start definition of copy methods for %s\n", rclassName); - Printf(sfile, "setMethod('copyToR', '_p_%s', CopyToR%s)\n", rclassName, + Printf(sfile, "setMethod('copyToR', '_p_%s', CopyToR%s);\n", rclassName, mangledName); - Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s)\n\n", rclassName, + Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s);\n\n", rclassName, mangledName); Printf(sfile, "# End definition of copy methods for %s\n", rclassName); diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 8d5ab4fae..a28256753 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -2590,7 +2590,7 @@ public: Parm *self; String *name = NewString("self"); String *type = NewString("VALUE"); - self = NewParm(type, name); + self = NewParm(type, name, n); Delete(type); Delete(name); Setattr(self, "lname", "Qnil"); @@ -2812,7 +2812,7 @@ public: ParmList *superparms = Getattr(n, "parms"); ParmList *parms = CopyParmList(superparms); String *type = NewString("VALUE"); - p = NewParm(type, NewString("self")); + p = NewParm(type, NewString("self"), n); set_nextSibling(p, parms); parms = p; diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index 81646171a..7958b4e09 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -1648,7 +1648,7 @@ String *Preprocessor_parse(String *s) { state = 0; break; - /* Swig directives */ + /* SWIG directives */ case 100: /* %{,%} block */ if (c == '{') { @@ -1713,7 +1713,7 @@ String *Preprocessor_parse(String *s) { case 110: if (!isidchar(c)) { Ungetc(c, s); - /* Look for common Swig directives */ + /* Look for common SWIG directives */ if (Equal(decl, kpp_dinclude) || Equal(decl, kpp_dimport) || Equal(decl, kpp_dextern)) { /* Got some kind of file inclusion directive */ if (allow) { diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index 121ea150a..f4c925206 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -803,7 +803,7 @@ int Swig_MethodToFunction(Node *n, String *classname, int flags, SwigType *direc SwigType_push(type, qualifier); } SwigType_add_pointer(type); - p = NewParm(type, "self"); + p = NewParm(type, "self", n); Setattr(p, "self", "1"); Setattr(p, "hidden","1"); /* @@ -1155,7 +1155,7 @@ int Swig_DestructorToFunction(Node *n, String *classname, int cplus, int flags) type = NewString(classname); SwigType_add_pointer(type); - p = NewParm(type, "self"); + p = NewParm(type, "self", n); Setattr(p, "self", "1"); Setattr(p, "hidden", "1"); Setattr(p, "wrap:disown", "1"); @@ -1207,7 +1207,7 @@ int Swig_DestructorToFunction(Node *n, String *classname, int cplus, int flags) * This function creates a C wrapper for setting a structure member. * ----------------------------------------------------------------------------- */ -int Swig_MembersetToFunction(Node *n, String *classname, int flags, String **call) { +int Swig_MembersetToFunction(Node *n, String *classname, int flags) { String *name; ParmList *parms; Parm *p; @@ -1238,13 +1238,13 @@ int Swig_MembersetToFunction(Node *n, String *classname, int flags, String **cal t = NewString(classname); SwigType_add_pointer(t); - parms = NewParm(t, "self"); + parms = NewParm(t, "self", n); Setattr(parms, "self", "1"); Setattr(parms, "hidden","1"); Delete(t); ty = Swig_wrapped_member_var_type(type, varcref); - p = NewParm(ty, name); + p = NewParm(ty, name, n); Setattr(parms, "hidden", "1"); set_nextSibling(parms, p); @@ -1255,21 +1255,23 @@ int Swig_MembersetToFunction(Node *n, String *classname, int flags, String **cal Delete(p); if (flags & CWRAP_EXTEND) { + String *call; String *cres; String *code = Getattr(n, "code"); if (code) { /* I don't think this ever gets run - WSF */ Swig_add_extension_code(n, mangled, parms, void_type, code, cparse_cplusplus, "self"); } - *call = Swig_cfunction_call(mangled, parms); - cres = NewStringf("%s;", *call); + call = Swig_cfunction_call(mangled, parms); + cres = NewStringf("%s;", call); Setattr(n, "wrap:action", cres); + Delete(call); Delete(cres); } else { - String *cres; - *call = Swig_cmemberset_call(name, type, self, varcref); - cres = NewStringf("%s;", *call); + String *call = Swig_cmemberset_call(name, type, self, varcref); + String *cres = NewStringf("%s;", call); Setattr(n, "wrap:action", cres); + Delete(call); Delete(cres); } Setattr(n, "type", void_type); @@ -1325,7 +1327,7 @@ int Swig_MembergetToFunction(Node *n, String *classname, int flags) { t = NewString(classname); SwigType_add_pointer(t); - parms = NewParm(t, "self"); + parms = NewParm(t, "self", n); Setattr(parms, "self", "1"); Setattr(parms, "hidden","1"); Delete(t); @@ -1381,7 +1383,7 @@ int Swig_VarsetToFunction(Node *n, int flags) { type = Getattr(n, "type"); nname = SwigType_namestr(name); ty = Swig_wrapped_var_type(type, varcref); - parms = NewParm(ty, name); + parms = NewParm(ty, name, n); if (flags & CWRAP_EXTEND) { String *sname = Swig_name_set(name); diff --git a/Source/Swig/error.c b/Source/Swig/error.c index 156fe06a7..3271f93fc 100644 --- a/Source/Swig/error.c +++ b/Source/Swig/error.c @@ -49,13 +49,15 @@ static char wrn_wnum_fmt[64]; static char wrn_nnum_fmt[64]; static char err_line_fmt[64]; static char err_eof_fmt[64]; +static char diag_line_fmt[64]; +static char diag_eof_fmt[64]; static String *format_filename(const_String_or_char_ptr filename); /* ----------------------------------------------------------------------------- * Swig_warning() * - * Issue a warning message + * Issue a warning message on stderr. * ----------------------------------------------------------------------------- */ void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const char *fmt, ...) { @@ -118,7 +120,7 @@ void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const c /* ----------------------------------------------------------------------------- * Swig_error() * - * Issue an error message + * Issue an error message on stderr. * ----------------------------------------------------------------------------- */ void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, ...) { @@ -245,8 +247,8 @@ void Swig_error_msg_format(ErrorMessageFormat format) { by now a switch is used to translated into one. */ switch (format) { case EMF_MICROSOFT: - fmt_line = "%s(%d)"; - fmt_eof = "%s(999999)"; /* Is there a special character for EOF? Just use a large number. */ + fmt_line = "%s(%d) "; + fmt_eof = "%s(999999) "; /* Is there a special character for EOF? Just use a large number. */ break; case EMF_STANDARD: default: @@ -254,10 +256,12 @@ void Swig_error_msg_format(ErrorMessageFormat format) { fmt_eof = "%s:EOF"; } - sprintf(wrn_wnum_fmt, "%s: %s(%%d): ", fmt_line, warning); + sprintf(wrn_wnum_fmt, "%s: %s %%d: ", fmt_line, warning); sprintf(wrn_nnum_fmt, "%s: %s: ", fmt_line, warning); sprintf(err_line_fmt, "%s: %s: ", fmt_line, error); sprintf(err_eof_fmt, "%s: %s: ", fmt_eof, error); + sprintf(diag_line_fmt, "%s: ", fmt_line); + sprintf(diag_eof_fmt, "%s: ", fmt_eof); msg_format = format; init_fmt = 1; @@ -275,3 +279,29 @@ static String *format_filename(const_String_or_char_ptr filename) { #endif return formatted_filename; } + +/* ----------------------------------------------------------------------------- + * Swig_diagnostic() + * + * Issue a diagnostic message on stdout. + * ----------------------------------------------------------------------------- */ + +void Swig_diagnostic(const_String_or_char_ptr filename, int line, const char *fmt, ...) { + va_list ap; + String *formatted_filename = NULL; + + if (!init_fmt) + Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT); + + va_start(ap, fmt); + formatted_filename = format_filename(filename); + if (line > 0) { + Printf(stdout, diag_line_fmt, formatted_filename, line); + } else { + Printf(stdout, diag_eof_fmt, formatted_filename); + } + vPrintf(stdout, fmt, ap); + va_end(ap); + Delete(formatted_filename); +} + diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index 050e5357a..9b3e54fae 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -88,8 +88,8 @@ void Swig_banner_target_lang(File *f, const_String_or_char_ptr commentchar) { /* ----------------------------------------------------------------------------- * Swig_strip_c_comments() * - * Return a new string with C comments stripped from the input string. Null is - * returned if there aren't any. + * Return a new string with C comments stripped from the input string. NULL is + * returned if there aren't any comments. * ----------------------------------------------------------------------------- */ String *Swig_strip_c_comments(const String *s) { @@ -107,9 +107,10 @@ String *Swig_strip_c_comments(const String *s) { comment_begin = c-1; } else if (comment_begin && !comment_end && *c == '*') { ++c; - if (*c == '/') + if (*c == '/') { comment_end = c; - break; + break; + } } ++c; } diff --git a/Source/Swig/parms.c b/Source/Swig/parms.c index 9b58f5fcb..90a072a7e 100644 --- a/Source/Swig/parms.c +++ b/Source/Swig/parms.c @@ -14,10 +14,25 @@ char cvsroot_parms_c[] = "$Id$"; /* ------------------------------------------------------------------------ * NewParm() * - * Create a new parameter from datatype 'type' and name 'name'. + * Create a new parameter from datatype 'type' and name 'name' copying + * the file and line number from the Node file_line_node. * ------------------------------------------------------------------------ */ -Parm *NewParm(SwigType *type, const_String_or_char_ptr name) { +Parm *NewParm(SwigType *type, const_String_or_char_ptr name, Node *file_line_node) { + Parm *p = NewParmWithoutFileLineInfo(type, name); + Setfile(p, Getfile(file_line_node)); + Setline(p, Getline(file_line_node)); + return p; +} + +/* ------------------------------------------------------------------------ + * NewParmWithoutFileLineInfo() + * + * Create a new parameter from datatype 'type' and name 'name' without any + * file / line numbering information. + * ------------------------------------------------------------------------ */ + +Parm *NewParmWithoutFileLineInfo(SwigType *type, const_String_or_char_ptr name) { Parm *p = NewHash(); set_nodeType(p, "parm"); if (type) { @@ -114,6 +129,14 @@ int ParmList_len(ParmList *p) { return i; } +/* --------------------------------------------------------------------- + * get_empty_type() + * ---------------------------------------------------------------------- */ + +static SwigType *get_empty_type() { + return NewStringEmpty(); +} + /* --------------------------------------------------------------------- * ParmList_str() * @@ -123,7 +146,8 @@ int ParmList_len(ParmList *p) { String *ParmList_str(ParmList *p) { String *out = NewStringEmpty(); while (p) { - String *pstr = SwigType_str(Getattr(p, "type"), Getattr(p, "name")); + String *type = Getattr(p, "type"); + String *pstr = SwigType_str(type ? type : get_empty_type(), Getattr(p, "name")); Append(out, pstr); p = nextSibling(p); if (p) { @@ -144,7 +168,8 @@ String *ParmList_str_defaultargs(ParmList *p) { String *out = NewStringEmpty(); while (p) { String *value = Getattr(p, "value"); - String *pstr = SwigType_str(Getattr(p, "type"), Getattr(p, "name")); + String *type = Getattr(p, "type"); + String *pstr = SwigType_str(type ? type : get_empty_type(), Getattr(p, "name")); Append(out, pstr); if (value) { Printf(out, "=%s", value); @@ -158,6 +183,24 @@ String *ParmList_str_defaultargs(ParmList *p) { return out; } +/* ----------------------------------------------------------------------------- + * ParmList_str_multibrackets() + * + * Generates a string of parameters including default arguments adding brackets + * if more than one parameter + * ----------------------------------------------------------------------------- */ + +String *ParmList_str_multibrackets(ParmList *p) { + String *out; + String *parm_str = ParmList_str_defaultargs(p); + if (ParmList_len(p) > 1) + out = NewStringf("(%s)", parm_str); + else + out = NewStringf("%s", parm_str); + Delete(parm_str); + return out; +} + /* --------------------------------------------------------------------- * ParmList_protostr() * @@ -167,7 +210,8 @@ String *ParmList_str_defaultargs(ParmList *p) { String *ParmList_protostr(ParmList *p) { String *out = NewStringEmpty(); while (p) { - String *pstr = SwigType_str(Getattr(p, "type"), 0); + String *type = Getattr(p, "type"); + String *pstr = SwigType_str(type ? type : get_empty_type(), 0); Append(out, pstr); p = nextSibling(p); if (p) { diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c index 3de794fdc..507c8c748 100644 --- a/Source/Swig/scanner.c +++ b/Source/Swig/scanner.c @@ -16,7 +16,8 @@ char cvsroot_scanner_c[] = "$Id$"; #include extern String *cparse_file; -extern int cparse_start_line; +extern int cparse_cplusplus; +extern int cparse_start_line; struct Scanner { String *text; /* Current token value */ @@ -730,15 +731,25 @@ static int look(Scanner * s) { break; case 7: /* Identifier */ if ((c = nextchar(s)) == 0) - return SWIG_TOKEN_ID; - if (isalnum(c) || (c == '_') || (c == '$')) { + state = 71; + else if (isalnum(c) || (c == '_') || (c == '$')) { state = 7; } else { retract(s, 1); - return SWIG_TOKEN_ID; + state = 71; } break; + case 71: /* Identifier or true/false */ + if (cparse_cplusplus) { + if (Strcmp(s->text, "true") == 0) + return SWIG_TOKEN_BOOL; + else if (Strcmp(s->text, "false") == 0) + return SWIG_TOKEN_BOOL; + } + return SWIG_TOKEN_ID; + break; + case 75: /* Special identifier $ */ if ((c = nextchar(s)) == 0) return SWIG_TOKEN_DOLLAR; @@ -747,7 +758,7 @@ static int look(Scanner * s) { } else { retract(s,1); if (Len(s->text) == 1) return SWIG_TOKEN_DOLLAR; - return SWIG_TOKEN_ID; + state = 71; } break; diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index 8a7700bec..707232558 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -525,7 +525,13 @@ String *SwigType_namestr(const SwigType *t) { Putc(' ', r); Putc('>', r); suffix = SwigType_templatesuffix(t); - Append(r, suffix); + if (Len(suffix) > 0) { + String *suffix_namestr = SwigType_namestr(suffix); + Append(r, suffix_namestr); + Delete(suffix_namestr); + } else { + Append(r, suffix); + } Delete(suffix); Delete(p); return r; @@ -544,7 +550,10 @@ String *SwigType_str(SwigType *s, const_String_or_char_ptr id) { int nelements, i; if (id) { - result = NewString(id); + /* stringify the id expanding templates, for example when the id is a fully qualified templated class name */ + String *id_str = NewString(id); /* unfortunate copy due to current const limitations */ + result = SwigType_str(id_str, 0); + Delete(id_str); } else { result = NewStringEmpty(); } diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index a5f13bd77..3e7ae8c38 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -123,7 +123,7 @@ extern "C" { extern SwigType *SwigType_add_function(SwigType *t, ParmList *parms); extern SwigType *SwigType_add_template(SwigType *t, ParmList *parms); extern SwigType *SwigType_pop_function(SwigType *t); - extern ParmList *SwigType_function_parms(SwigType *t); + extern ParmList *SwigType_function_parms(SwigType *t, Node *file_line_node); extern List *SwigType_split(const SwigType *t); extern String *SwigType_pop(SwigType *t); extern void SwigType_push(SwigType *t, SwigType *s); @@ -200,6 +200,10 @@ extern "C" { /* --- Symbol table module --- */ + extern void Swig_symbol_print_tables(Symtab *symtab); + extern void Swig_symbol_print_tables_summary(void); + extern void Swig_symbol_print_symbols(void); + extern void Swig_symbol_print_csymbols(void); extern void Swig_symbol_init(void); extern void Swig_symbol_setscopename(const_String_or_char_ptr name); extern String *Swig_symbol_getscopename(void); @@ -207,6 +211,7 @@ extern "C" { extern Symtab *Swig_symbol_newscope(void); extern Symtab *Swig_symbol_setscope(Symtab *); extern Symtab *Swig_symbol_getscope(const_String_or_char_ptr symname); + extern Symtab *Swig_symbol_global_scope(void); extern Symtab *Swig_symbol_current(void); extern Symtab *Swig_symbol_popscope(void); extern Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *node); @@ -302,13 +307,8 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern String *Swig_string_title(String *s); extern void Swig_init(void); - extern void Swig_warn(const char *filename, int line, const char *msg); - extern int Swig_value_wrapper_mode(int mode); - -#define WARNING(msg) Swig_warn(__FILE__,__LINE__,msg) - typedef enum { EMF_STANDARD, EMF_MICROSOFT } ErrorMessageFormat; extern void Swig_warning(int num, const_String_or_char_ptr filename, int line, const char *fmt, ...); @@ -319,6 +319,7 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern void Swig_warnall(void); extern int Swig_warn_count(void); extern void Swig_error_msg_format(ErrorMessageFormat format); + extern void Swig_diagnostic(const_String_or_char_ptr filename, int line, const char *fmt, ...); /* --- C Wrappers --- */ extern String *Swig_cparm_name(Parm *p, int i); @@ -343,7 +344,7 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern int Swig_MethodToFunction(Node *n, String *classname, int flags, SwigType *director_type, int is_director); extern int Swig_ConstructorToFunction(Node *n, String *classname, String *none_comparison, String *director_ctor, int cplus, int flags); extern int Swig_DestructorToFunction(Node *n, String *classname, int cplus, int flags); - extern int Swig_MembersetToFunction(Node *n, String *classname, int flags, String **call); + extern int Swig_MembersetToFunction(Node *n, String *classname, int flags); extern int Swig_MembergetToFunction(Node *n, String *classname, int flags); extern int Swig_VargetToFunction(Node *n, int flags); extern int Swig_VarsetToFunction(Node *n, int flags); @@ -369,6 +370,8 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern int Swig_typemap_apply(ParmList *srcpat, ParmList *destpat); extern void Swig_typemap_clear_apply(ParmList *pattern); extern void Swig_typemap_debug(void); + extern void Swig_typemap_search_debug_set(void); + extern void Swig_typemap_used_debug_set(void); extern String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f); extern String *Swig_typemap_lookup_out(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f, String *actioncode); diff --git a/Source/Swig/swigparm.h b/Source/Swig/swigparm.h index 49ae7992e..4a928999e 100644 --- a/Source/Swig/swigparm.h +++ b/Source/Swig/swigparm.h @@ -11,7 +11,8 @@ /* $Id: swig.h 9629 2006-12-30 18:27:47Z beazley $ */ /* Individual parameters */ -extern Parm *NewParm(SwigType *type, const_String_or_char_ptr name); +extern Parm *NewParm(SwigType *type, const_String_or_char_ptr name, Node *file_line_node); +extern Parm *NewParmWithoutFileLineInfo(SwigType *type, const_String_or_char_ptr name); extern Parm *CopyParm(Parm *p); /* Parameter lists */ @@ -24,6 +25,7 @@ extern int ParmList_has_defaultargs(ParmList *p); /* Output functions */ extern String *ParmList_str(ParmList *); extern String *ParmList_str_defaultargs(ParmList *); +extern String *ParmList_str_multibrackets(ParmList *); extern String *ParmList_protostr(ParmList *); diff --git a/Source/Swig/swigscan.h b/Source/Swig/swigscan.h index 3403098df..2adf7b2be 100644 --- a/Source/Swig/swigscan.h +++ b/Source/Swig/swigscan.h @@ -64,6 +64,7 @@ extern void Scanner_freeze_line(Scanner *s, int val); #define SWIG_TOKEN_ULONGLONG 29 /* 314ULL */ #define SWIG_TOKEN_QUESTION 30 /* ? */ #define SWIG_TOKEN_COMMENT 31 /* C or C++ comment */ +#define SWIG_TOKEN_BOOL 32 /* true or false */ #define SWIG_TOKEN_ILLEGAL 99 #define SWIG_TOKEN_ERROR -1 diff --git a/Source/Swig/symbol.c b/Source/Swig/symbol.c index 055af854f..e018029a1 100644 --- a/Source/Swig/symbol.c +++ b/Source/Swig/symbol.c @@ -175,20 +175,80 @@ static Hash *global_scope = 0; /* Global scope */ /* common attribute keys, to avoid calling find_key all the times */ +/* ----------------------------------------------------------------------------- + * Swig_symbol_print_tables() + * + * Debug display of symbol tables + * ----------------------------------------------------------------------------- */ -#if 0 -void Swig_symbol_dump_symtable() { - Printf(stdout, "DUMPING SYMTABLE start =======================================\n"); - { - Hash *cst = Getattr(current_symtab, "csymtab"); - Swig_print_tree(cst); - /* - Swig_print_tree(Getattr(cst, "NumSpace")); - */ - } - Printf(stdout, "DUMPING SYMTABLE end =======================================\n"); +void Swig_symbol_print_tables(Symtab *symtab) { + if (!symtab) + symtab = current_symtab; + + Printf(stdout, "SYMBOL TABLES start =======================================\n"); + Swig_print_tree(symtab); + Printf(stdout, "SYMBOL TABLES finish =======================================\n"); +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_print_tables_summary() + * + * Debug summary display of all symbol tables by fully-qualified name + * ----------------------------------------------------------------------------- */ + +void Swig_symbol_print_tables_summary(void) { + Printf(stdout, "SYMBOL TABLES SUMMARY start =======================================\n"); + Swig_print_node(symtabs); + Printf(stdout, "SYMBOL TABLES SUMMARY finish =======================================\n"); +} + +/* ----------------------------------------------------------------------------- + * symbol_print_symbols() + * ----------------------------------------------------------------------------- */ + +static void symbol_print_symbols(const char *symboltabletype) { + Node *obj = symtabs; + Iterator ki = First(obj); + while (ki.key) { + String *k = ki.key; + Printf(stdout, "===================================================\n"); + Printf(stdout, "%s -\n", k); + { + Symtab *symtab = Getattr(Getattr(obj, k), symboltabletype); + Iterator it = First(symtab); + while (it.key) { + String *symname = it.key; + Printf(stdout, " %s\n", symname); + it = Next(it); + } + } + ki = Next(ki); + } +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_print_symbols() + * + * Debug display of all the target language symbols + * ----------------------------------------------------------------------------- */ + +void Swig_symbol_print_symbols(void) { + Printf(stdout, "SYMBOLS start =======================================\n"); + symbol_print_symbols("symtab"); + Printf(stdout, "SYMBOLS finish =======================================\n"); +} + +/* ----------------------------------------------------------------------------- + * Swig_symbol_print_csymbols() + * + * Debug display of all the C symbols + * ----------------------------------------------------------------------------- */ + +void Swig_symbol_print_csymbols(void) { + Printf(stdout, "CSYMBOLS start =======================================\n"); + symbol_print_symbols("csymtab"); + Printf(stdout, "CSYMBOLS finish =======================================\n"); } -#endif /* ----------------------------------------------------------------------------- * Swig_symbol_init() @@ -196,7 +256,7 @@ void Swig_symbol_dump_symtable() { * Create a new symbol table object * ----------------------------------------------------------------------------- */ -void Swig_symbol_init() { +void Swig_symbol_init(void) { current = NewHash(); current_symtab = NewHash(); @@ -240,7 +300,7 @@ void Swig_symbol_setscopename(const_String_or_char_ptr name) { * Get the C scopename of the current symbol table * ----------------------------------------------------------------------------- */ -String *Swig_symbol_getscopename() { +String *Swig_symbol_getscopename(void) { return Getattr(current_symtab, "name"); } @@ -295,7 +355,7 @@ String *Swig_symbol_qualifiedscopename(Symtab *symtab) { * Create a new scope. Returns the newly created scope. * ----------------------------------------------------------------------------- */ -Symtab *Swig_symbol_newscope() { +Symtab *Swig_symbol_newscope(void) { Hash *n; Hash *hsyms, *h; @@ -346,7 +406,7 @@ Symtab *Swig_symbol_setscope(Symtab *sym) { * scope to the parent scope. * ----------------------------------------------------------------------------- */ -Symtab *Swig_symbol_popscope() { +Symtab *Swig_symbol_popscope(void) { Hash *h = current_symtab; current_symtab = Getattr(current_symtab, "parentNode"); assert(current_symtab); @@ -357,13 +417,23 @@ Symtab *Swig_symbol_popscope() { return h; } +/* ----------------------------------------------------------------------------- + * Swig_symbol_global_scope() + * + * Return the symbol table for the global scope. + * ----------------------------------------------------------------------------- */ + +Symtab *Swig_symbol_global_scope(void) { + return global_scope; +} + /* ----------------------------------------------------------------------------- * Swig_symbol_current() * * Return the current symbol table. * ----------------------------------------------------------------------------- */ -Symtab *Swig_symbol_current() { +Symtab *Swig_symbol_current(void) { return current_symtab; } @@ -998,6 +1068,8 @@ Node *Swig_symbol_clookup(const_String_or_char_ptr name, Symtab *n) { String *nname = NewString(cname + 2); if (Swig_scopename_check(nname)) { s = symbol_lookup_qualified(nname, global_scope, 0, 0, 0); + } else { + s = symbol_lookup(nname, global_scope, 0); } Delete(nname); } else { @@ -1070,6 +1142,8 @@ Node *Swig_symbol_clookup_check(const_String_or_char_ptr name, Symtab *n, int (* String *nname = NewString(cname + 2); if (Swig_scopename_check(nname)) { s = symbol_lookup_qualified(nname, global_scope, 0, 0, checkfunc); + } else { + s = symbol_lookup(nname, global_scope, checkfunc); } Delete(nname); } else { @@ -1134,6 +1208,8 @@ Node *Swig_symbol_clookup_local(const_String_or_char_ptr name, Symtab *n) { String *nname = NewString(cname + 2); if (Swig_scopename_check(nname)) { s = symbol_lookup_qualified(nname, global_scope, 0, 0, 0); + } else { + s = symbol_lookup(nname, global_scope, 0); } Delete(nname); } else { @@ -1182,6 +1258,8 @@ Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr name, Symtab *n, String *nname = NewString(cname + 2); if (Swig_scopename_check(nname)) { s = symbol_lookup_qualified(nname, global_scope, 0, 0, checkfunc); + } else { + s = symbol_lookup(nname, global_scope, checkfunc); } Delete(nname); } else { @@ -1253,7 +1331,8 @@ void Swig_symbol_remove(Node *n) { Setattr(symtab, symname, symnext); fixovername = symnext; /* fix as symbol to remove is at head of linked list */ } else { - Delattr(symtab, symname); + if (symname) + Delattr(symtab, symname); } } if (symnext) { @@ -1728,7 +1807,7 @@ ParmList *Swig_symbol_template_defargs(Parm *parms, Parm *targs, Symtab *tscope, ntq = ty; } /* Printf(stderr,"value %s %s %s\n",value,ntr,ntq); */ - cp = NewParm(ntq, 0); + cp = NewParmWithoutFileLineInfo(ntq, 0); if (lp) set_nextSibling(lp, cp); else @@ -1805,7 +1884,7 @@ SwigType *Swig_symbol_template_deftype(const SwigType *type, Symtab *tscope) { String *tprefix = SwigType_templateprefix(base); String *targs = SwigType_templateargs(base); String *tsuffix = SwigType_templatesuffix(base); - ParmList *tparms = SwigType_function_parms(targs); + ParmList *tparms = SwigType_function_parms(targs, 0); Node *tempn = Swig_symbol_clookup_local(tprefix, tscope); if (!tempn && tsuffix && Len(tsuffix)) { tempn = Swig_symbol_clookup(tprefix, 0); diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c index 14d231afa..98ae9ed16 100644 --- a/Source/Swig/tree.c +++ b/Source/Swig/tree.c @@ -30,7 +30,7 @@ void Swig_print_tags(DOH *obj, DOH *root) { croot = root; while (obj) { - Printf(stdout, "%s . %s (%s:%d)\n", croot, nodeType(obj), Getfile(obj), Getline(obj)); + Swig_diagnostic(Getfile(obj), Getline(obj), "%s . %s\n", croot, nodeType(obj)); cobj = firstChild(obj); if (cobj) { newroot = NewStringf("%s . %s", croot, nodeType(obj)); @@ -268,7 +268,7 @@ void Swig_require(const char *ns, Node *n, ...) { } obj = Getattr(n, name); if (!opt && !obj) { - Printf(stderr, "%s:%d. Fatal error (Swig_require). Missing attribute '%s' in node '%s'.\n", Getfile(n), Getline(n), name, nodeType(n)); + Swig_error(Getfile(n), Getline(n), "Fatal error (Swig_require). Missing attribute '%s' in node '%s'.\n", name, nodeType(n)); assert(obj); } if (!obj) diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index 9fcbb38e0..ec44cd015 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -17,7 +17,11 @@ char cvsroot_typemap_c[] = "$Id$"; #define SWIG_DEBUG #endif -static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f); +static int typemap_search_debug = 0; +static int typemaps_used_debug = 0; +static int in_typemap_search_multi = 0; + +static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f, Node *file_line_node); /* ----------------------------------------------------------------------------- * Typemaps are stored in a collection of nested hash tables. Something like @@ -36,7 +40,7 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper * "type" - Typemap type * "pname" - Parameter name * "code" - Typemap code - * "typemap" - Descriptive text describing the actual map + * "source" - Source directive (%apply or %typemap) for the typemap * "locals" - Local variables (if any) * "kwargs" - Typemap attributes * @@ -46,7 +50,7 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper * "type" - r.int * "pname" - my_int * "code" - $1 = $input; - * "typemap" - typemap(in) int &my_int + * "source" - typemap(in) int &my_int * "locals" - int tmp * "kwargs" - warning="987:my typemap warning", foo=123 * @@ -171,12 +175,12 @@ Hash *Swig_typemap_pop_scope() { #endif /* ----------------------------------------------------------------------------- - * Swig_typemap_register() + * typemap_register() * - * Add a new multi-argument typemap + * Internal implementation for Swig_typemap_register() * ----------------------------------------------------------------------------- */ -void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs) { +static void typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs, String *source_directive) { Hash *tm; Hash *tm1; Hash *tm2; @@ -223,7 +227,7 @@ void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms /* For a multi-argument typemap, the typemap code and information is really only stored in the last argument. However, to make this work, we perform a really neat trick using - the typemap operator name. + the typemap method name. For example, consider this typemap @@ -233,35 +237,35 @@ void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms To store it, we look at typemaps for the following: - operator type-name + typemap method type-name ---------------------------------------------- "in" int foo "in-int+foo:" int *bar "in-int+foo:-p.int+bar: char *blah[] - Notice how the operator expands to encode information about + Notice how the typemap method name expands to encode information about previous arguments. */ np = nextSibling(parms); if (np) { - /* Make an entirely new operator key */ - String *newop = NewStringf("%s-%s+%s:", tmap_method, type, pname); - /* Now reregister on the remaining arguments */ - Swig_typemap_register(newop, np, code, locals, kwargs); + /* Make an entirely new typemap method key */ + String *multi_tmap_method = NewStringf("%s-%s+%s:", tmap_method, type, pname); - /* Setattr(tm2,newop,newop); */ - Delete(newop); + /* Now reregister on the remaining arguments */ + typemap_register(multi_tmap_method, np, code, locals, kwargs, source_directive); + + Delete(multi_tmap_method); } else { - String *str = SwigType_str(type, pname); - String *typemap = NewStringf("typemap(%s) %s", tmap_method, str); ParmList *clocals = CopyParmList(locals); ParmList *ckwargs = CopyParmList(kwargs); + Setfile(tm2, Getfile(code)); + Setline(tm2, Getline(code)); Setattr(tm2, "code", code); Setattr(tm2, "type", type); - Setattr(tm2, "typemap", typemap); + Setattr(tm2, "source", source_directive); if (pname) { Setattr(tm2, "pname", pname); } @@ -270,12 +274,25 @@ void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms Delete(clocals); Delete(ckwargs); - - Delete(str); - Delete(typemap); } } +/* ----------------------------------------------------------------------------- + * Swig_typemap_register() + * + * Add a new, possibly multi-argument, typemap + * ----------------------------------------------------------------------------- */ + +void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs) { + String *parms_str = ParmList_str_multibrackets(parms); + String *source_directive = NewStringf("typemap(%s) %s", tmap_method, parms_str); + + typemap_register(tmap_method, parms, code, locals, kwargs, source_directive); + + Delete(source_directive); + Delete(parms_str); +} + /* ----------------------------------------------------------------------------- * typemap_get() * @@ -311,7 +328,7 @@ int Swig_typemap_copy(const_String_or_char_ptr tmap_method, ParmList *srcparms, String *pname; SwigType *ptype; int ts = tm_scope; - String *tm_methods, *newop; + String *tm_methods, *multi_tmap_method; if (ParmList_len(parms) != ParmList_len(srcparms)) return -1; @@ -333,17 +350,24 @@ int Swig_typemap_copy(const_String_or_char_ptr tmap_method, ParmList *srcparms, break; /* Got a match. Look for next typemap */ - newop = NewStringf("%s-%s+%s:", tm_methods, ptype, pname); + multi_tmap_method = NewStringf("%s-%s+%s:", tm_methods, ptype, pname); Delete(tm_methods); - tm_methods = newop; + tm_methods = multi_tmap_method; p = nextSibling(p); } Delete(tm_methods); if (!p && tm) { - /* Got some kind of match */ - Swig_typemap_register(tmap_method, parms, Getattr(tm, "code"), Getattr(tm, "locals"), Getattr(tm, "kwargs")); + String *parms_str = ParmList_str_multibrackets(parms); + String *srcparms_str = ParmList_str_multibrackets(srcparms); + String *source_directive = NewStringf("typemap(%s) %s = %s", tmap_method, parms_str, srcparms_str); + + typemap_register(tmap_method, parms, Getattr(tm, "code"), Getattr(tm, "locals"), Getattr(tm, "kwargs"), source_directive); + + Delete(source_directive); + Delete(srcparms_str); + Delete(parms_str); return 0; } ts--; @@ -363,11 +387,11 @@ void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *parms) { SwigType *type; String *name; Parm *p; - String *newop; + String *multi_tmap_method; Hash *tm = 0; /* This might not work */ - newop = NewString(tmap_method); + multi_tmap_method = NewString(tmap_method); p = parms; while (p) { type = Getattr(p, "type"); @@ -377,17 +401,17 @@ void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *parms) { return; p = nextSibling(p); if (p) - Printf(newop, "-%s+%s:", type, name); + Printf(multi_tmap_method, "-%s+%s:", type, name); } if (tm) { - tm = Getattr(tm, typemap_method_name(newop)); + tm = Getattr(tm, typemap_method_name(multi_tmap_method)); if (tm) { Delattr(tm, "code"); Delattr(tm, "locals"); Delattr(tm, "kwargs"); } } - Delete(newop); + Delete(multi_tmap_method); } /* ----------------------------------------------------------------------------- @@ -509,9 +533,17 @@ int Swig_typemap_apply(ParmList *src, ParmList *dest) { locals = Getattr(sm1, "locals"); kwargs = Getattr(sm1, "kwargs"); if (code) { + String *src_str = ParmList_str_multibrackets(src); + String *dest_str = ParmList_str_multibrackets(dest); + String *source_directive = NewStringf("apply %s { %s }", src_str, dest_str); + Replace(nkey, dsig, "", DOH_REPLACE_ANY); Replace(nkey, "tmap:", "", DOH_REPLACE_ANY); - Swig_typemap_register(nkey, dest, code, locals, kwargs); + typemap_register(nkey, dest, code, locals, kwargs, source_directive); + + Delete(source_directive); + Delete(dest_str); + Delete(src_str); } } Delete(nkey); @@ -594,14 +626,22 @@ static SwigType *strip_arrays(SwigType *type) { return t; } +static void debug_search_result_display(Node *tm) { + if (tm) + Printf(stdout, " Using: %%%s\n", Getattr(tm, "source")); + else + Printf(stdout, " None found\n"); +} + /* ----------------------------------------------------------------------------- * typemap_search() * - * Search for a typemap match. Tries to find the most specific typemap - * that includes a 'code' attribute. + * Search for a typemap match. This is where the typemap pattern matching rules + * are implemented... tries to find the most specific typemap that includes a + * 'code' attribute. * ----------------------------------------------------------------------------- */ -static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type, const_String_or_char_ptr name, SwigType **matchtype) { +static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type, const_String_or_char_ptr name, const_String_or_char_ptr qualifiedname, SwigType **matchtype, Node *node) { Hash *result = 0, *tm, *tm1, *tma; Hash *backup = 0; SwigType *noarrays = 0; @@ -610,28 +650,53 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type int ts; int isarray; const String *cname = 0; + const String *cqualifiedname = 0; SwigType *unstripped = 0; String *tm_method = typemap_method_name(tmap_method); + int debug_display = (in_typemap_search_multi == 0) && typemap_search_debug; if ((name) && Len(name)) cname = name; + if ((qualifiedname) && Len(qualifiedname)) + cqualifiedname = qualifiedname; ts = tm_scope; + if (debug_display) { + String *typestr = SwigType_str(type, cqualifiedname ? cqualifiedname : cname); + Swig_diagnostic(Getfile(node), Getline(node), "Searching for a suitable '%s' typemap for: %s\n", tmap_method, typestr); + Delete(typestr); + } while (ts >= 0) { ctype = type; while (ctype) { /* Try to get an exact type-match */ tm = get_typemap(ts, ctype); - if (tm && cname) { - tm1 = Getattr(tm, cname); + if (debug_display && cqualifiedname) + Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, cqualifiedname)); + if (tm && cqualifiedname) { + tm1 = Getattr(tm, cqualifiedname); if (tm1) { - result = Getattr(tm1, tm_method); /* See if there is a type-name match */ + result = Getattr(tm1, tm_method); /* See if there is a type - qualified name match */ if (result && Getattr(result, "code")) goto ret_result; if (result) backup = result; } } + if (debug_display && cname) + Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, cname)); + if (tm && cname) { + tm1 = Getattr(tm, cname); + if (tm1) { + result = Getattr(tm1, tm_method); /* See if there is a type - name match */ + if (result && Getattr(result, "code")) + goto ret_result; + if (result) + backup = result; + } + } + if (debug_display) + Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, 0)); if (tm) { result = Getattr(tm, tm_method); /* See if there is simply a type match */ if (result && Getattr(result, "code")) @@ -647,18 +712,34 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type noarrays = strip_arrays(ctype); } tma = get_typemap(ts, noarrays); - if (tma && cname) { - tm1 = Getattr(tma, cname); + if (debug_display && cqualifiedname) + Printf(stdout, " Looking for: %s\n", SwigType_str(noarrays, cqualifiedname)); + if (tma && cqualifiedname) { + tm1 = Getattr(tma, cqualifiedname); if (tm1) { - result = Getattr(tm1, tm_method); /* type-name match */ + result = Getattr(tm1, tm_method); /* See if there is a type - qualified name match */ if (result && Getattr(result, "code")) goto ret_result; if (result) backup = result; } } + if (debug_display && cname) + Printf(stdout, " Looking for: %s\n", SwigType_str(noarrays, cname)); + if (tma && cname) { + tm1 = Getattr(tma, cname); + if (tm1) { + result = Getattr(tm1, tm_method); /* See if there is a type - name match */ + if (result && Getattr(result, "code")) + goto ret_result; + if (result) + backup = result; + } + } + if (debug_display) + Printf(stdout, " Looking for: %s\n", SwigType_str(noarrays, 0)); if (tma) { - result = Getattr(tma, tm_method); /* type match */ + result = Getattr(tma, tm_method); /* See if there is a type match */ if (result && Getattr(result, "code")) goto ret_result; if (result) @@ -694,21 +775,35 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type } } - /* Hmmm. Well, no match seems to be found at all. See if there is some kind of default mapping */ + /* Hmmm. Well, no match seems to be found at all. See if there is some kind of default (SWIGTYPE) mapping */ primitive = SwigType_default(type); while (primitive) { tm = get_typemap(ts, primitive); - if (tm && cname) { - tm1 = Getattr(tm, cname); + if (debug_display && cqualifiedname) + Printf(stdout, " Looking for: %s\n", SwigType_str(primitive, cqualifiedname)); + if (tm && cqualifiedname) { + tm1 = Getattr(tm, cqualifiedname); if (tm1) { - result = Getattr(tm1, tm_method); /* See if there is a type-name match */ + result = Getattr(tm1, tm_method); /* See if there is a type - qualified name match */ if (result) goto ret_result; } } - if (tm) { /* See if there is simply a type match */ - result = Getattr(tm, tm_method); + if (debug_display && cname) + Printf(stdout, " Looking for: %s\n", SwigType_str(primitive, cname)); + if (tm && cname) { + tm1 = Getattr(tm, cname); + if (tm1) { + result = Getattr(tm1, tm_method); /* See if there is a type - name match */ + if (result) + goto ret_result; + } + } + if (debug_display) + Printf(stdout, " Looking for: %s\n", SwigType_str(primitive, 0)); + if (tm) { + result = Getattr(tm, tm_method); /* See if there is simply a type match */ if (result) goto ret_result; } @@ -727,15 +822,12 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type result = backup; ret_result: - if (noarrays) - Delete(noarrays); - if (primitive) - Delete(primitive); + Delete(noarrays); + Delete(primitive); if ((unstripped) && (unstripped != type)) Delete(unstripped); - if (matchtype) { + if (matchtype) *matchtype = Copy(ctype); - } if (type != ctype) Delete(ctype); return result; @@ -752,8 +844,9 @@ static Hash *typemap_search_multi(const_String_or_char_ptr tmap_method, ParmList SwigType *type; SwigType *mtype = 0; String *name; - String *newop; - Hash *tm, *tm1; + String *multi_tmap_method; + Hash *tm; + Hash *tm1 = 0; if (!parms) { *nmatch = 0; @@ -763,23 +856,38 @@ static Hash *typemap_search_multi(const_String_or_char_ptr tmap_method, ParmList name = Getattr(parms, "name"); /* Try to find a match on the first type */ - tm = typemap_search(tmap_method, type, name, &mtype); + tm = typemap_search(tmap_method, type, name, 0, &mtype, parms); if (tm) { if (mtype && SwigType_isarray(mtype)) { Setattr(parms, "tmap:match", mtype); } Delete(mtype); - newop = NewStringf("%s-%s+%s:", tmap_method, type, name); - tm1 = typemap_search_multi(newop, nextSibling(parms), nmatch); + multi_tmap_method = NewStringf("%s-%s+%s:", tmap_method, type, name); + in_typemap_search_multi++; + tm1 = typemap_search_multi(multi_tmap_method, nextSibling(parms), nmatch); + in_typemap_search_multi--; if (tm1) tm = tm1; if (Getattr(tm, "code")) { *(nmatch) = *nmatch + 1; + if (typemap_search_debug && tm1 && (in_typemap_search_multi == 0)) { + Printf(stdout, " Multi-argument typemap found...\n"); + } } else { tm = 0; } - Delete(newop); + Delete(multi_tmap_method); } + + if (typemap_search_debug && (in_typemap_search_multi == 0)) + debug_search_result_display(tm); + if (typemaps_used_debug && (in_typemap_search_multi == 0) && tm) { + String *typestr = SwigType_str(type, name); + Swig_diagnostic(Getfile(parms), Getline(parms), "Typemap for %s (%s) : %%%s\n", typestr, tmap_method, Getattr(tm, "source")); + assert(Getfile(parms) && Len(Getfile(parms)) > 0); /* Missing file and line numbering information */ + Delete(typestr); + } + return tm; } @@ -1167,6 +1275,22 @@ static void typemap_locals(DOHString * s, ParmList *l, Wrapper *f, int argnum) { } } +/* ----------------------------------------------------------------------------- + * typemap_warn() + * + * If any warning message is attached to this parameter's "tmap::warning" + * attribute, print that warning message. + * ----------------------------------------------------------------------------- */ + +static void typemap_warn(const_String_or_char_ptr tmap_method, Parm *p) { + String *temp = NewStringf("%s:warning", tmap_method); + String *w = Getattr(p, typemap_method_name(temp)); + Delete(temp); + if (w) { + Swig_warning(0, Getfile(p), Getline(p), "%s\n", w); + } +} + /* ----------------------------------------------------------------------------- * Swig_typemap_lookup() * @@ -1195,6 +1319,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No SwigType *type; SwigType *mtype = 0; String *pname; + String *qpname = 0; Hash *tm = 0; String *s = 0; String *sdef = 0; @@ -1204,13 +1329,12 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No String *symname; String *cname = 0; String *clname = 0; - char *cop = Char(tmap_method); + char *cmethod = Char(tmap_method); int optimal_attribute = 0; int optimal_substitution = 0; int num_substitutions = 0; - /* special case, we need to check for 'ref' call - and set the default code 'sdef' */ + /* special case, we need to check for 'ref' call and set the default code 'sdef' */ if (node && Cmp(tmap_method, "newfree") == 0) { sdef = Swig_ref_call(node, lname); } @@ -1221,30 +1345,33 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No pname = Getattr(node, "name"); -#if 1 if (pname && node && checkAttribute(node, "kind", "function")) { /* - For functions, look qualified names first, such as - + For functions, add on a qualified name search, for example struct Foo { - int *foo(int bar) -> Foo::foo + int *foo(int bar) -> Foo::foo }; */ Symtab *st = Getattr(node, "sym:symtab"); String *qsn = st ? Swig_symbol_string_qualify(pname, st) : 0; - if (qsn) { - if (Len(qsn) && !Equal(qsn, pname)) { - tm = typemap_search(tmap_method, type, qsn, &mtype); - if (tm && (!Getattr(tm, "pname") || strstr(Char(Getattr(tm, "type")), "SWIGTYPE"))) { - tm = 0; - } - } - Delete(qsn); - } + if (qsn && Len(qsn) && !Equal(qsn, pname)) + qpname = qsn; } - if (!tm) -#endif - tm = typemap_search(tmap_method, type, pname, &mtype); + + tm = typemap_search(tmap_method, type, pname, qpname, &mtype, node); + if (typemap_search_debug) + debug_search_result_display(tm); + if (typemaps_used_debug && tm) { + String *typestr = SwigType_str(type, qpname ? qpname : pname); + Swig_diagnostic(Getfile(node), Getline(node), "Typemap for %s (%s) : %%%s\n", typestr, tmap_method, Getattr(tm, "source")); + assert(Getfile(node) && Len(Getfile(node)) > 0); /* Missing file and line numbering information */ + Delete(typestr); + } + + + Delete(qpname); + qpname = 0; + if (!tm) return sdef; @@ -1269,7 +1396,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No Append(value, mangle); Delete(mangle); } - sprintf(temp, "%s:%s", cop, ckwname); + sprintf(temp, "%s:%s", cmethod, ckwname); Setattr(node, typemap_method_name(temp), value); if (Cmp(temp, "out:optimal") == 0) optimal_attribute = (Cmp(value, "0") != 0) ? 1 : 0; @@ -1304,7 +1431,8 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No } } if (!optimal_substitution) { - Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(node), Getline(node), "Method %s usage of the optimal attribute in the out typemap at %s:%d ignored as the following cannot be used to generate optimal code: %s\n", Swig_name_decl(node), Getfile(s), Getline(s), clname); + Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(node), Getline(node), "Method %s usage of the optimal attribute ignored\n", Swig_name_decl(node)); + Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(s), Getline(s), "in the out typemap as the following cannot be used to generate optimal code: %s\n", clname); Delattr(node, "tmap:out:optimal"); } } else { @@ -1338,17 +1466,19 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No } else { num_substitutions = typemap_replace_vars(s, locals, type, type, pname, (char *) lname, 1); } - if (optimal_substitution && num_substitutions > 1) - Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(node), Getline(node), "Multiple calls to %s might be generated due to optimal attribute usage in the out typemap at %s:%d.\n", Swig_name_decl(node), Getfile(s), Getline(s)); + if (optimal_substitution && num_substitutions > 1) { + Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(node), Getline(node), "Multiple calls to %s might be generated due to optimal attribute usage in\n", Swig_name_decl(node)); + Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(s), Getline(s), "the out typemap.\n"); + } if (locals && f) { typemap_locals(s, locals, f, -1); } { - ParmList *parm_sublist = NewParm(type, pname); + ParmList *parm_sublist = NewParmWithoutFileLineInfo(type, pname); Setattr(parm_sublist, "lname", lname); - replace_embedded_typemap(s, parm_sublist, f); + replace_embedded_typemap(s, parm_sublist, f, tm); Delete(parm_sublist); } @@ -1361,30 +1491,23 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No Setattr(node, typemap_method_name(tmap_method), s); if (locals) { - sprintf(temp, "%s:locals", cop); + sprintf(temp, "%s:locals", cmethod); Setattr(node, typemap_method_name(temp), locals); Delete(locals); } if (Checkattr(tm, "type", "SWIGTYPE")) { - sprintf(temp, "%s:SWIGTYPE", cop); + sprintf(temp, "%s:SWIGTYPE", cmethod); Setattr(node, typemap_method_name(temp), "1"); } - /* Look for warnings */ - { - String *w; - sprintf(temp, "%s:warning", cop); - w = Getattr(node, typemap_method_name(temp)); - if (w) { - Swig_warning(0, Getfile(node), Getline(node), "%s\n", w); - } - } + /* Print warnings, if any */ + typemap_warn(cmethod, node); /* Look for code fragments */ { String *fragment; - sprintf(temp, "%s:fragment", cop); + sprintf(temp, "%s:fragment", cmethod); fragment = Getattr(node, typemap_method_name(temp)); if (fragment) { String *fname = Copy(fragment); @@ -1454,22 +1577,6 @@ static void typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr tmap_method Delete(temp); } -/* ----------------------------------------------------------------------------- - * typemap_warn() - * - * If any warning message is attached to this parameter's "tmap::warning" - * attribute, print that warning message. - * ----------------------------------------------------------------------------- */ - -static void typemap_warn(const_String_or_char_ptr tmap_method, Parm *p) { - String *temp = NewStringf("%s:warning", tmap_method); - String *w = Getattr(p, typemap_method_name(temp)); - Delete(temp); - if (w) { - Swig_warning(0, Getfile(p), Getline(p), "%s\n", w); - } -} - static void typemap_emit_code_fragments(const_String_or_char_ptr tmap_method, Parm *p) { String *temp = NewStringf("%s:fragment", tmap_method); String *f = Getattr(p, typemap_method_name(temp)); @@ -1520,7 +1627,7 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *p ParmList *locals; int argnum = 0; char temp[256]; - char *cop = Char(tmap_method); + char *cmethod = Char(tmap_method); String *kwmatch = 0; p = parms; @@ -1639,7 +1746,7 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *p } if (Checkattr(tm, "type", "SWIGTYPE")) { - sprintf(temp, "%s:SWIGTYPE", cop); + sprintf(temp, "%s:SWIGTYPE", cmethod); Setattr(p, typemap_method_name(temp), "1"); } p = nextSibling(p); @@ -1649,7 +1756,7 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *p typemap_locals(s, locals, f, argnum); } - replace_embedded_typemap(s, firstp, f); + replace_embedded_typemap(s, firstp, f, tm); /* Replace the argument number */ sprintf(temp, "%d", argnum); @@ -1662,13 +1769,13 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *p Setattr(firstp, typemap_method_name(tmap_method), s); /* Code object */ if (locals) { - sprintf(temp, "%s:locals", cop); + sprintf(temp, "%s:locals", cmethod); Setattr(firstp, typemap_method_name(temp), locals); Delete(locals); } /* Attach a link to the next parameter. Needed for multimaps */ - sprintf(temp, "%s:next", cop); + sprintf(temp, "%s:next", cmethod); Setattr(firstp, typemap_method_name(temp), p); /* Attach kwargs */ @@ -1770,7 +1877,7 @@ static List *split_embedded_typemap(String *s) { * $typemap(in, (Foo a, int b)) # multi-argument typemap matching %typemap(in) (Foo a, int b) {...} * ----------------------------------------------------------------------------- */ -static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f) { +static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f, Node *file_line_node) { char *start = 0; while ((start = strstr(Char(s), "$TYPEMAP("))) { /* note $typemap capitalisation to $TYPEMAP hack */ @@ -1814,7 +1921,7 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper /* the second parameter might contain multiple sub-parameters for multi-argument * typemap matching, so split these parameters apart */ - to_match_parms = Swig_cparse_parms(Getitem(l, 1)); + to_match_parms = Swig_cparse_parms(Getitem(l, 1), file_line_node); if (to_match_parms) { Parm *p = to_match_parms; Parm *sub_p = parm_sublist; @@ -1920,6 +2027,8 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper /* ----------------------------------------------------------------------------- * Swig_typemap_debug() + * + * Display all typemaps * ----------------------------------------------------------------------------- */ void Swig_typemap_debug() { @@ -1934,3 +2043,25 @@ void Swig_typemap_debug() { } Printf(stdout, "-----------------------------------------------------------------------------\n"); } + + +/* ----------------------------------------------------------------------------- + * Swig_typemap_search_debug_set() + * + * Turn on typemap searching debug display + * ----------------------------------------------------------------------------- */ + +void Swig_typemap_search_debug_set(void) { + typemap_search_debug = 1; +} + +/* ----------------------------------------------------------------------------- + * Swig_typemap_used_debug_set() + * + * Turn on typemaps used debug display + * ----------------------------------------------------------------------------- */ + +void Swig_typemap_used_debug_set(void) { + typemaps_used_debug = 1; +} + diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c index 8ff31bc0b..cbc2fd414 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -781,13 +781,15 @@ int SwigType_isfunction(SwigType *t) { return 0; } -ParmList *SwigType_function_parms(SwigType *t) { +/* Create a list of parameters from the type t, using the file_line_node Node for + * file and line numbering for the parameters */ +ParmList *SwigType_function_parms(SwigType *t, Node *file_line_node) { List *l = SwigType_parmlist(t); Hash *p, *pp = 0, *firstp = 0; Iterator o; for (o = First(l); o.item; o = Next(o)) { - p = NewParm(o.item, 0); + p = file_line_node ? NewParm(o.item, 0, file_line_node) : NewParmWithoutFileLineInfo(o.item, 0); if (!firstp) firstp = p; if (pp) { diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 2562e12f8..2022daf6a 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1120,11 +1120,13 @@ int SwigType_typedef_using(const_String_or_char_ptr name) { /* Figure out the scope the using directive refers to */ { prefix = Swig_scopename_prefix(name); - s = SwigType_find_scope(current_scope, prefix); - if (s) { - Hash *ttab = Getattr(s, "typetab"); - if (!Getattr(ttab, base) && defined_name) { - Setattr(ttab, base, defined_name); + if (prefix) { + s = SwigType_find_scope(current_scope, prefix); + if (s) { + Hash *ttab = Getattr(s, "typetab"); + if (!Getattr(ttab, base) && defined_name) { + Setattr(ttab, base, defined_name); + } } } } diff --git a/Source/Swig/warn.c b/Source/Swig/warn.c deleted file mode 100644 index a8dadc70b..000000000 --- a/Source/Swig/warn.c +++ /dev/null @@ -1,34 +0,0 @@ -/* ----------------------------------------------------------------------------- - * See the LICENSE file for information on copyright, usage and redistribution - * of SWIG, and the README file for authors - http://www.swig.org/release.html. - * - * warn.c - * - * SWIG warning framework. This was added to warn developers about - * deprecated APIs and other features. - * ----------------------------------------------------------------------------- */ - -char cvsroot_warn_c[] = "$Id$"; - -#include "swig.h" - -static Hash *warnings = 0; - -/* ----------------------------------------------------------------------------- - * Swig_warn() - * - * Issue a warning - * ----------------------------------------------------------------------------- */ - -void Swig_warn(const char *filename, int line, const char *msg) { - String *key; - if (!warnings) { - warnings = NewHash(); - } - key = NewStringf("%s:%d", filename, line); - if (!Getattr(warnings, key)) { - Printf(stderr, "swig-dev warning:%s:%d:%s\n", filename, line, msg); - Setattr(warnings, key, key); - } - Delete(key); -} diff --git a/Tools/mkrelease.py b/Tools/mkrelease.py index edf3b07fe..b719c470e 100755 --- a/Tools/mkrelease.py +++ b/Tools/mkrelease.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # This script builds the SWIG source tarball, creates the Windows executable and the Windows zip package -# and uploads them both to SF ready for release +# and uploads them both to SF ready for release. Also uploaded are the release notes. import sys import string import os @@ -30,10 +30,20 @@ os.system("python ./mkdist.py " + version) and failed("") print "Build Windows package" os.system("./mkwindows.sh " + version) and failed("") -print "Uploading to Sourceforge" -os.system("rsync --archive --verbose -P --times -e ssh swig-" + version + ".tar.gz " + username + "@frs.sourceforge.net:uploads/") and failed("") -os.system("rsync --archive --verbose -P --times -e ssh swigwin-" + version + ".zip " + username + "@frs.sourceforge.net:uploads/") and failed("") +print "Uploading to SourceForge" + +swig_dir_sf = username + ",swig@frs.sourceforge.net:/home/frs/project/s/sw/swig/swig/swig-" + version + "/" +swigwin_dir_sf = username + ",swig@frs.sourceforge.net:/home/frs/project/s/sw/swig/swigwin/swigwin-" + version + "/" + +release_notes_file = "release-notes-" + version + ".txt" +os.system("rm -f " + release_notes_file) +os.system("cat swig-" + version + "/README " + "swig-" + version + "/CHANGES.current > " + release_notes_file) + +os.system("rsync --archive --verbose -P --times -e ssh " + "swig-" + version + ".tar.gz " + release_notes_file + " " + swig_dir_sf) and failed("") +os.system("rsync --archive --verbose -P --times -e ssh " + "swigwin-" + version + ".zip " + swigwin_dir_sf) and failed("") os.system("svn copy -m \"rel-" + version + "\" https://swig.svn.sourceforge.net/svnroot/swig/trunk https://swig.svn.sourceforge.net/svnroot/swig/tags/rel-" + version + "/") print "Finished" + +print "Now log in to SourceForge and set the operating system and link the release notes to each of the tarball and zip file in the File Manager." diff --git a/configure.in b/configure.in index 7180068ae..42d1d1397 100644 --- a/configure.in +++ b/configure.in @@ -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],[1.3.40],[http://www.swig.org]) +AC_INIT([swig],[1.3.41],[http://www.swig.org]) AC_PREREQ(2.58) AC_CONFIG_SRCDIR([Source/Swig/swig.h]) AC_CONFIG_AUX_DIR([Tools/config]) @@ -316,11 +316,7 @@ esac # Optional CFLAGS used to silence compiler warnings on some platforms. AC_SUBST(PLATFLAGS) -case $host in - *-*-darwin*) PLATFLAGS="-Wno-long-double";; - *) PLATFLAGS="";; -esac - +PLATFLAGS= # Check for specific libraries. Used for SWIG examples AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV