diff --git a/CCache/Makefile.in b/CCache/Makefile.in index ec55ccaf5..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 @@ -53,7 +52,7 @@ uninstall: $(PACKAGE_NAME)$(EXEEXT) $(PACKAGE_NAME).1 clean: /bin/rm -f $(OBJS) *~ $(PACKAGE_NAME)$(EXEEXT) -clean-docs: +distclean-docs: rm -f $(PACKAGE_NAME).1 web/ccache-man.html check : test @@ -63,9 +62,12 @@ test: test.sh check: test -distclean: clean - /bin/rm -f Makefile config.h config.sub config.log build-stamp config.status configure config.h +distclean: clean distclean-docs + /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 b7fde04cc..902308847 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,64 +1,371 @@ -Version 1.3.40 (in progress) +Version 1.3.41 (in progress) ============================ -2009-05-26: wsfulton - [C#] Improved std::map wrappers based on patch from Yuval Baror. The C# proxy - now implements System.Collections.Generic.IDictionary<>. +2010-02-27: wsfulton + [Python] Remove -dirvtable from the optimizations included by -O as it this option + currently leads to memory leaks as reported by Johan Blake. - 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 +2010-02-13: wsfulton + [Ruby] A few fixes for compiling under ruby-1.9.x including patch from 'Nibble'. - 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 +2010-02-13: wsfulton + [Ruby] Apply patch from Patrick Bennett to fix RARRAY_LEN and RARRAY_PTR usage for Ruby 1.9.x + used in various STL wrappers. + +2010-02-13: wsfulton + [C#, Java] Fix incorrect multiply defined symbol name error when an enum item + and class name have the same name, as reported by Nathan Krieger. Example: + + class Vector {}; + namespace Text { + enum Preference { Vector }; + } + + This also fixes other incorrect corner case target language symbol name clashes. + +2010-02-11: wsfulton + Add the -debug-lsymbols option for displaying the target language layer symbols. + +2010-02-09: wsfulton + Fix -MM and -MMD options on Windows. They were not omitting files in the SWIG library as + they should be. + +2010-02-08: wsfulton + Fix #1807329 - When Makefile dependencies are being generated using the -M family of options + on Windows, the file paths have been corrected to use single backslashes rather than double + backslashes as path separators. + +2010-02-06: wsfulton + Fix #2918902 - language specific files not being generated in correct directory on + Windows when using forward slashes for -o, for example: + swig -python -c++ -o subdirectory/theinterface_wrap.cpp subdirectory/theinterface.i + +2010-02-05: wsfulton + Fix #2894405 - assertion when using -xmlout. + +2010-01-28: wsfulton + Fix typemap matching bug when a templated type has a typemap both specialized and not + specialized. For example: + + template struct XX { ... }; + %typemap(in) const XX & "..." + %typemap(in) const XX< int > & "..." + + resulted in the 2nd typemap being applied for all T in XX< T >. + +2010-01-22: wsfulton + Fix #2933129 - typemaps not being found when the unary scope operator (::) is used to denote + global scope, the typemap is now used in situations like this: + + struct X {}; + %typemap(in) const X & "..." + void m(const ::X &); + + and this: + + struct X {}; + %typemap(in) const ::X & "..." + void m(const X &); + +2010-01-20: wsfulton + Fix some unary scope operator (::) denoting global scope problems in the types generated + into the C++ layer. Previously the unary scope operator was dropped in the generated code + if the type had any sort of qualifier, for example when using pointers, references, like + ::foo*, ::foo&, bar< ::foo* >. + +2010-01-13: olly + [PHP] Add datetime to the list of PHP predefined classes (patch + from David Fletcher in SF#2931042). + +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. + + 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. + + 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. + +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. + +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 + +2010-01-03: wsfulton + Fix missing file/line numbers for typemap warnings and in output from the + -debug-tmsearch/-debug-tmused options. + +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-12-23: wsfulton + Fix for %javaexception and directors so that all the appropriate throws clauses + are generated. Problem reported by Peter Greenwood. + +2009-12-20: wsfulton + Add -debug-tmsearch option for debugging the typemap pattern matching rules. + Documented in Typemaps.html. + +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-12-04: olly + [Ruby] Improve support for Ruby 1.9 under GCC. Addresses part of + SF#2859614. + +2009-12-04: olly + Fix handling of modulo operator (%) in constant expressions + (SF#2818562). + +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-12-03: olly + [PHP] Add typemaps for long long and unsigned long long, and for + pointer to method. + +2009-12-02: olly + [PHP] Fix warning and rename of reserved class name to be case + insensitive. + +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-11-29: wsfulton + [Java, C#] Fix generated quoting when using %javaconst(1)/%csconst(1) for + static const char member variables. + + %javaconst(1) A; + %csconst(1) A; + struct X { + static const char A = 'A'; + }; + +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. + + %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-05-14: bhy - [Python] Fix the wrong pointer value returned by SwigPyObject_repr(). +2009-11-09: drjoe + Fix R for -fcompact and add std_map.i -2009-05-13: mutandiz (Mikel Bancroft) - [allegrocl] Minor tweak when wrapping in -nocwrap mode. +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-05-11: wsfulton - [C#] Improved std::vector wrappers on the C# proxy side from Yuval Baror. These - implement IList<> instead of IEnumerable<> where possible. + struct Outer { + struct InnerStruct { int x; }; + InnerStruct* getInnerStruct(); + }; -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-11-08: wsfulton + Ignored nested class/struct warnings now display the name of the ignored class/struct. -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-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-04-21: wsfulton - [C#] Fix #2753469 - bool &OUTPUT and bool *OUTPUT typemaps initialisation. +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-04-09: wsfulton - Fix #2746858 - C macro expression using floating point numbers +2009-11-03: wsfulton + Fix some usage of unary scope operator (::) denoting global scope, for example: -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: + namespace AA { /* ... */ } + using namespace ::AA; + + and bug #1816802 - SwigValueWrapper should be used: + + struct CC { + CC(int); // no default constructor + }; + ::CC x(); + + and in template parameter specializations: + + struct S {}; + template struct X { void a() {}; }; + template <> struct X { void b() {}; }; + %template(MyTConcrete) X< ::S >; + + plus probably some other corner case usage of ::. + +2009-11-02: olly + [Python] Fix potential memory leak in initialisation code for the + generated module. + +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-10-20: wsfulton + [Python] Fix std::vector. This would previously compile, but not run correctly. + +2009-10-20: wsfulton + Fixed previously fairly poor template partial specialization and explicit + specialization support. Numerous bugs in this area have been fixed including: + + - Template argument deduction implemented for template type arguments, eg this now + works: + template class X {}; + template class X {}; + %template(X1) X; // Chooses T * specialization + + 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; + + 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-09-14: wsfulton + [C#] Add %csattributes for adding C# attributes to enum values, see docs for example. + +2009-09-11: wsfulton + Fix memmove regression in cdata.i as reported by Adriaan Renting. + +2009-09-07: wsfulton + Fix constant expressions containing <= or >=. + +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: + + && || == != < > <= >= (Actually the last 4 are still broken). For example: + + #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-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 - %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 @@
    • Basics @@ -138,7 +138,7 @@ to it.

      17.1 Basics

      -

      17.1.1 Running Swig

      +

      17.1.1 Running SWIG

      diff --git a/Doc/Manual/Arguments.html b/Doc/Manual/Arguments.html index af8780452..8ab51faf6 100644 --- a/Doc/Manual/Arguments.html +++ b/Doc/Manual/Arguments.html @@ -30,8 +30,6 @@ -Disclaimer: This chapter is under construction. -

      In Chapter 3, SWIG's treatment of basic datatypes and pointers was described. In particular, primitive types such as int and @@ -351,7 +349,7 @@ function like this in an interface file :

       %module example
      -%include typemaps.i
      +%include "typemaps.i"
       ...
       %{
       extern void negate(double *);
      diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html
      index 3e17ee7f1..324be63ec 100644
      --- a/Doc/Manual/CSharp.html
      +++ b/Doc/Manual/CSharp.html
      @@ -55,7 +55,7 @@ The PInvoke interface has been chosen over Microsoft's Managed C++ interface as
       PInvoke is part of the ECMA/ISO C# specification.
       It is also better suited for robust production environments due to the Managed C++ flaw called the
       Mixed DLL Loading Problem.
      -Swig C# works equally well on non-Microsoft operating systems such as Linux, Solaris and Apple Mac using
      +SWIG C# works equally well on non-Microsoft operating systems such as Linux, Solaris and Apple Mac using
       Mono and Portable.NET.
       

      @@ -99,6 +99,7 @@ namespace com.bloggs.widget { ... }
      +Note that by default, the generated C# classes have no namespace and the module name is unrelated to namespaces. The module name is just like in Java and is merely used to name some of the generated classes.
    • @@ -131,7 +132,7 @@ If it was used, it would generate an illegal runtime initialisation via a PInvok C# doesn't support the notion of throws clauses. Therefore there is no 'throws' typemap attribute support for adding exception classes to a throws clause. Likewise there is no need for an equivalent to %javaexception. -In fact, throwing C# exceptions works quite differently, see C# Exceptions> below. +In fact, throwing C# exceptions works quite differently, see C# Exceptions below.
    • @@ -248,7 +249,9 @@ public static extern IntPtr function(string jarg1);

      Support for type attributes. The 'imtype' and 'cstype' typemaps can have an optional inattributes and outattributes typemap attribute. -There are C# attributes and typemap attributes, don't get confused!! +The 'imtype' typemap can also have an optional directorinattributes and directoroutattributes +typemap attribute which attaches to director delegates, an implementation detail of directors, see directors implementation. +Note that there are C# attributes and typemap attributes, don't get confused between the two!! The C# attributes specified in these typemap attributes are generated wherever the type is used in the C# wrappers. These can be used to specify any C# attribute associated with a C/C++ type, but are more typically used for the C# MarshalAs attribute. For example: @@ -292,11 +295,16 @@ These attributes are associated with the C/C++ parameter type or return type, wh the attribute features and typemaps covered next. Note that all these different C# attributes can be combined so that a method has more than one attribute.

      + +

      +The directorinattributes and directoroutattributes typemap attribute are attached to the delegates in the director class, for example, the SwigDelegateBase_0 +

      +
    • -Support for attaching C# attributes to wrapped methods and variables. +Support for attaching C# attributes to wrapped methods, variables and enum values. This is done using the %csattributes feature, see %feature directives. Note that C# attributes are attached to proxy classes and enums using the csattributes typemap. For example, imagine we have a custom attribute class, ThreadSafeAttribute, for labelling thread safety. @@ -343,6 +351,38 @@ they can be added using the 'csvarin' and 'csvarout' typemaps respectively. Note that the type used for the property is specified in the 'cstype' typemap. If the 'out' attribute exists in this typemap, then the type used is from the 'out' attribute.

      + +

      +An example for attaching attributes to the enum and enum values is shown below. +

      + +
      +
      +%typemap(csattributes) Couleur "[System.ComponentModel.Description(\"Colours\")]"
      +%csattributes Rouge "[System.ComponentModel.Description(\"Red\")]"
      +%csattributes Vert "[System.ComponentModel.Description(\"Green\")]"
      +%inline %{
      +  enum Couleur { Rouge, Orange, Vert };
      +%}
      +
      +
      + +

      +which will result in the following C# enum: +

      + +
      +
      +[System.ComponentModel.Description("Colours")]
      +public enum Couleur {
      +  [System.ComponentModel.Description("Red")]
      +  Rouge,
      +  Orange,
      +  [System.ComponentModel.Description("Green")]
      +  Vert
      +}
      +
      +
    • @@ -947,7 +987,7 @@ without setting the canthrow attribute you will get a warning message s
      -example.i:21: Warning(845): Unmanaged code contains a call to a SWIG_CSharpSetPendingException
      +example.i:21: Warning 845: Unmanaged code contains a call to a SWIG_CSharpSetPendingException
       method and C# code does not handle pending exceptions via the canthrow attribute.
       
      diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index c135b7c6f..0cda0b8f4 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -337,25 +337,31 @@
  • Typemap specifications -
  • Pattern matching rules +
  • Pattern matching rules
  • Code generation rules
  • Common typemap methods -
  • Typemaps for multiple languages +
  • Typemaps for multiple target languages
  • Optimal code generation when returning by value
  • Multi-argument typemaps
  • The run-time type checker
  • Typemaps and overloading
  • More about %apply and %clear @@ -488,6 +494,7 @@
  • Cross language polymorphism + @@ -1264,9 +1281,6 @@
  • Simple pointers
  • Unbounded C Arrays
  • String handling -
  • Arrays -
  • String arrays -
  • STL wrappers
  • Typemaps @@ -1564,7 +1579,7 @@
  • Writing a Language Module -
  • Typemaps - +
  • Debugging Options
  • Guide to parse tree nodes +
  • Further Development Information diff --git a/Doc/Manual/Customization.html b/Doc/Manual/Customization.html index ec73e5460..82e1c411f 100644 --- a/Doc/Manual/Customization.html +++ b/Doc/Manual/Customization.html @@ -53,6 +53,21 @@ The %exception directive allows you to define a general purpose excepti handler. For example, you can specify the following:

    +
    +%exception {
    +    try {
    +        $action
    +    }
    +    catch (RangeError) {
    +        ... handle error ...
    +    }
    +}
    +
    + +

    +How the exception is handled depends on the target language, for example, Python: +

    +
     %exception {
         try {
    @@ -60,7 +75,7 @@ handler. For example, you can specify the following:
         }
         catch (RangeError) {
             PyErr_SetString(PyExc_IndexError,"index out-of-bounds");
    -        return NULL;
    +        SWIG_fail;
         }
     }
     
    diff --git a/Doc/Manual/Extending.html b/Doc/Manual/Extending.html index 73f1a6673..cc40024e6 100644 --- a/Doc/Manual/Extending.html +++ b/Doc/Manual/Extending.html @@ -48,7 +48,7 @@
  • Writing a Language Module -
  • Typemaps - +
  • Debugging Options
  • Guide to parse tree nodes +
  • Further Development Information @@ -1025,7 +1027,7 @@ Deletes s.

    -int Len(String_or_char *s) +int Len(const String_or_char *s)

    @@ -1033,7 +1035,7 @@ Returns the length of the string.

    -char *Char(String_or_char *s) +char *Char(const String_or_char *s)

    @@ -1041,7 +1043,7 @@ Returns a pointer to the first character in a string.

    -void Append(String *s, String_or_char *t) +void Append(String *s, const String_or_char *t)

    @@ -1049,7 +1051,7 @@ Appends t to the end of string s.

    -void Insert(String *s, int pos, String_or_char *t) +void Insert(String *s, int pos, const String_or_char *t)

    @@ -1162,7 +1164,7 @@ Returns the number of items in h.

    -Object *Getattr(Hash *h, String_or_char *key) +Object *Getattr(Hash *h, const String_or_char *key)

    @@ -1171,7 +1173,7 @@ a simple char * string. Returns NULL if not found.

    -int Setattr(Hash *h, String_or_char *key, Object_or_char *val) +int Setattr(Hash *h, const String_or_char *key, const Object_or_char *val)

    @@ -1185,7 +1187,7 @@ of val. Returns 1 if this operation replaced an existing hash entry,

    -int Delattr(Hash *h, String_or_char *key) +int Delattr(Hash *h, const String_or_char *key)

    @@ -1249,7 +1251,7 @@ negative, the first item is returned.

    -int *Setitem(List *x, int n, Object_or_char *val) +int *Setitem(List *x, int n, const Object_or_char *val)

    @@ -1271,7 +1273,7 @@ for n.

    -void Append(List *x, Object_or_char *t) +void Append(List *x, const Object_or_char *t)

    @@ -1281,7 +1283,7 @@ used to create a String object.

    -void Insert(String *s, int pos, Object_or_char *t) +void Insert(String *s, int pos, const Object_or_char *t)

    @@ -1479,13 +1481,14 @@ Same as the C tell() function.

    -File *NewFile(const char *filename, const char *mode) +File *NewFile(const char *filename, const char *mode, List *newfiles)

    Create a File object using the fopen() library call. This file differs from FILE * in that it can be placed in the standard -SWIG containers (lists, hashes, etc.). +SWIG containers (lists, hashes, etc.). The filename is added to the +newfiles list if newfiles is non-zero and the file was created successfully.

    @@ -1922,7 +1925,7 @@ Adds a reference to ty.

    -void SwigType_add_array(SwigType *ty, String_or_char *dim) +void SwigType_add_array(SwigType *ty, const String_or_char *size)

    @@ -1962,7 +1965,7 @@ Sets nth array dimensions of ty to rep.

    -void SwigType_add_qualifier(SwigType *ty, String_or_char *q) +void SwigType_add_qualifier(SwigType *ty, const String_or_char *q)

    @@ -1971,7 +1974,7 @@ Adds a type qualifier q to ty. q is typically

    -void SwigType_add_memberpointer(SwigType *ty, String_or_char *cls) +void SwigType_add_memberpointer(SwigType *ty, const String_or_char *cls)

    @@ -2292,7 +2295,7 @@ The following functions produce strings that are suitable for output.

    -String *SwigType_str(SwigType *ty, String_or_char *id = 0) +String *SwigType_str(SwigType *ty, const String_or_char *id = 0)

    @@ -2303,7 +2306,7 @@ used to convert string-encoded types back into a form that is valid C syntax.

    -String *SwigType_lstr(SwigType *ty, String_or_char *id = 0) +String *SwigType_lstr(SwigType *ty, const String_or_char *id = 0)

    @@ -2312,7 +2315,7 @@ is generated from the type's lvalue (as generated from SwigType_ltype).

    -String *SwigType_lcaststr(SwigType *ty, String_or_char *id = 0) +String *SwigType_lcaststr(SwigType *ty, const String_or_char *id = 0)

    @@ -2323,7 +2326,7 @@ this function produces the string "(char *) foo".

    -String *SwigType_rcaststr(SwigType *ty, String_or_char *id = 0) +String *SwigType_rcaststr(SwigType *ty, const String_or_char *id = 0)

    @@ -2470,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

    @@ -2601,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); + } ... } } @@ -2776,6 +2779,7 @@ such as: class PYTHON : public Language { protected: /* General DOH objects used for holding the strings */ + File *f_begin; File *f_runtime; File *f_header; File *f_wrappers; @@ -2791,22 +2795,25 @@ int Python::top(Node *n) { ... /* Initialize I/O */ - f_runtime = NewFile(outfile, "w"); - if (!f_runtime) { + f_begin = NewFile(outfile, "w", SWIG_output_files()); + if (!f_begin) { FileErrorDisplay(outfile); SWIG_exit(EXIT_FAILURE); } + f_runtime = NewString(""); f_init = NewString(""); f_header = NewString(""); f_wrappers = NewString(""); /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("begin", f_begin); Swig_register_filebyname("header", f_header); Swig_register_filebyname("wrapper", f_wrappers); Swig_register_filebyname("runtime", f_runtime); Swig_register_filebyname("init", f_init); /* Output module initialization code */ + Swig_banner(f_begin); ... /* Emit code for children */ @@ -2814,16 +2821,18 @@ int Python::top(Node *n) { ... /* Write all to the file */ - Dump(f_header, f_runtime); - Dump(f_wrappers, f_runtime); - Wrapper_pretty_print(f_init, f_runtime); + Dump(f_runtime, f_begin); + Dump(f_header, f_begin); + Dump(f_wrappers, f_begin); + Wrapper_pretty_print(f_init, f_begin); /* Cleanup files */ + Delete(f_runtime); Delete(f_header); Delete(f_wrappers); Delete(f_init); - Close(f_runtime); - Delete(f_runtime); + Close(f_begin); + Delete(f_begin); return SWIG_OK; } @@ -3046,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 @@ -3218,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

    @@ -3247,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

    @@ -3279,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

    @@ -3336,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

    @@ -3360,11 +3588,30 @@ 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-lsymbols   - Display target language layer symbols
    +-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

    @@ -3774,6 +4021,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 a19cc5e84..7869c5269 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -253,6 +253,12 @@ To change this, you can use the -o option. It is also possible to change the output directory that the Java files are generated into using -outdir.

    +

    +The module name, specified with %module, determines the name of various generated classes as discussed later. +Note that the module name does not define a Java package and by default, the generated Java classes do not have a Java package. +The -package option described below can specify a Java package name to use. +

    +

    The following sections have further practical examples and details on how you might go about compiling and using the generated files. @@ -441,6 +447,19 @@ $

    This error usually indicates that you forgot to include some object files or libraries in the linking of the native library file. Make sure you compile both the SWIG wrapper file and the code you are wrapping into the native library file. +If you forget to compile and link in the SWIG wrapper file into your native library file, you will get a message similar to the following: +

    + +
    +$ java runme
    +Exception in thread "main" java.lang.UnsatisfiedLinkError: exampleJNI.gcd(II)I
    +	at exampleJNI.gcd(Native Method)
    +	at example.gcd(example.java:12)
    +	at runme.main(runme.java:18)
    +
    + +

    +where gcd is the missing JNI function that SWIG generated into the wrapper file. Also make sure you pass all of the required libraries to the linker. The java -verbose:jni commandline switch is also a great way to get more information on unresolved symbols. One last piece of advice is to beware of the common faux pas of having more than one native library version in your path. @@ -657,7 +676,9 @@ This is often combined with the -outdir to specify a package directory swig -java -package com.bloggs.swig -outdir com/bloggs/swig example.i +

    SWIG won't create the directory, so make sure it exists beforehand. +

    21.3.2 Functions

    @@ -1753,7 +1774,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 5ac66dc2e..406bdeaef 100644 --- a/Doc/Manual/Modules.html +++ b/Doc/Manual/Modules.html @@ -10,6 +10,7 @@

      +
    • Modules Introduction
    • Basics
    • The SWIG runtime code
    • External access to the runtime @@ -22,11 +23,49 @@ +

      15.1 Modules Introduction

      + + +

      +Each invocation of SWIG requires a module name to be specified. +The module name is used to name the resulting target language extension module. +Exactly what this means and and what the name is used for +depends on the target language, for example the name can define +a target language namespace or merely be a useful name for naming files or helper classes. +Essentially, a module comprises target language wrappers for a chosen collection of global variables/functions, structs/classes and other C/C++ types. +

      + +

      +The module name can be supplied in one of two ways. +The first is to specify it with the special %module +directive. This directive must appear at the beginning of the interface file. +The general form of this directive is: +

      + +
      +%module(option1="value1",option2="value2",...) modulename
      +
      + +

      +where the modulename is mandatory and the options add one or more optional additional features. +Typically no options are specified, for example: +

      + +
      +%module mymodule
      +
      + +

      +The second way to specify the module name is with the -module command line option, for example -module mymodule. +If the module name is supplied on the command line, it overrides the name specified by the +%module directive. +

      +

      When first working with SWIG, users commonly start by creating a single module. That is, you might define a single SWIG interface that wraps some set of C/C++ code. You then compile all of the generated -wrapper code into a module and use it. For large applications, however, +wrapper code together and use it. For large applications, however, this approach is problematic---the size of the generated wrapper code can be rather large. Moreover, it is probably easier to manage the target language interface when it is broken up into smaller pieces. @@ -34,10 +73,11 @@ target language interface when it is broken up into smaller pieces.

      This chapter describes the problem of using SWIG in programs -where you want to create a collection of modules. +where you want to create a collection of modules. +Each module in the collection is created via separate invocations of SWIG.

      -

      15.1 Basics

      +

      15.2 Basics

      @@ -98,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.
       
      @@ -135,7 +175,7 @@ in parallel from multiple threads as SWIG provides no locking - for more on that issue, read on.

      -

      15.2 The SWIG runtime code

      +

      15.3 The SWIG runtime code

      @@ -201,7 +241,7 @@ can peacefully coexist. So the type structures are separated by the is empty. Only modules compiled with the same pair will share type information.

      -

      15.3 External access to the runtime

      +

      15.4 External access to the runtime

      As described in The run-time type checker, @@ -238,7 +278,7 @@ SWIG_TYPE_TABLE to be the same as the module whose types you are trying to access.

      -

      15.4 A word of caution about static libraries

      +

      15.5 A word of caution about static libraries

      @@ -249,7 +289,7 @@ into it. This is very often NOT what you want and it can lead to unexpect behavior. When working with dynamically loadable modules, you should try to work exclusively with shared libraries.

      -

      15.5 References

      +

      15.6 References

      @@ -257,7 +297,7 @@ Due to the complexity of working with shared libraries and multiple modules, it an outside reference. John Levine's "Linkers and Loaders" is highly recommended.

      -

      15.6 Reducing the wrapper file size

      +

      15.7 Reducing the wrapper file size

      diff --git a/Doc/Manual/Ocaml.html b/Doc/Manual/Ocaml.html index 6dbf24c11..b65831192 100644 --- a/Doc/Manual/Ocaml.html +++ b/Doc/Manual/Ocaml.html @@ -634,13 +634,13 @@ length. Instead, use multiple returns, as in the argout_ref example. #include "example.h" %} -%include stl.i +%include <stl.i> namespace std { %template(StringVector) std::vector < string >; }; -%include example.h +%include "example.h" This example is in Examples/ocaml/stl diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 1dc8e7d2f..40500dc5a 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -40,7 +40,7 @@

    • Modules and packages
  • Input and output parameters -
  • Exception handling +
  • Exception handling
  • Remapping datatypes with typemaps
  • Typemap Examples
      -
    • Converting a Perl5 array to a char ** -
    • Return values +
    • Converting a Perl5 array to a char ** +
    • Return values
    • Returning values from arguments
    • Accessing array structure members
    • Turning Perl references into C pointers @@ -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 :

      @@ -264,7 +264,7 @@ extern int fact(int); %} // Include code for rebuilding Perl -%include perlmain.i +%include <perlmain.i>

      @@ -815,7 +815,7 @@ extern char *path; // Declared later in the input

      -Constants are wrapped as read-only Perl variables. For example: +By default, constants are wrapped as read-only Perl variables. For example:

      @@ -838,6 +838,19 @@ $example::FOO = 2; # Error
      +

      +Alternatively, if you use swig's -const option, constants are wrapped +such that the leading $ isn't required (by using a constant subroutine), which +usually gives a more natural Perl interface, for example: +

      + +
      +
      +use example;
      +print example::FOO,"\n";
      +
      +
      +

      28.4.4 Pointers

      @@ -879,7 +892,7 @@ if (defined($ptr)) {

      -To create a NULL pointer, you should pass the undef value to +To create a NULL pointer, you should pass the undef value to a function.

      @@ -889,7 +902,7 @@ pointer that SWIG wrapper functions return. Suppose that $a and $b are two references that point to the same C object. In general, $a and $b will be different--since they are different references. Thus, it is a mistake to check the equality -of $a and $b to check the equality of two C +of $a and $b to check the equality of two C pointers. The correct method to check equality of C pointers is to dereference them as follows :

      @@ -1543,7 +1556,7 @@ example:
       %module example
      -%include typemaps.i
      +%include "typemaps.i"
       
       void add(int x, int y, int *REFERENCE);
       
      @@ -1567,7 +1580,7 @@ print "$c\n"; Note: The REFERENCE feature is only currently supported for numeric types (integers and floating point).

      -

      28.6 Exception handling

      +

      28.6 Exception handling

      @@ -2107,7 +2120,7 @@ might look at the files "perl5.swg" and "typemaps.i" in the SWIG library.

      -

      28.8.1 Converting a Perl5 array to a char **

      +

      28.8.1 Converting a Perl5 array to a char **

      @@ -2160,7 +2173,7 @@ reference to be used as a char ** datatype. }; myav = av_make(len,svs); free(svs); - $result = newRV((SV*)myav); + $result = newRV_noinc((SV*)myav); sv_2mortal($result); argvi++; } @@ -2199,7 +2212,7 @@ print @$b,"\n"; # Print it out

      -

      28.8.2 Return values

      +

      28.8.2 Return values

      @@ -2714,7 +2727,7 @@ corresponding Perl object (this situation turns out to come up frequently when constructing objects like linked lists and trees). When C takes possession of an object, you can change Perl's ownership by simply deleting the object from the %OWNER hash. This is -done using the DISOWN method. +done using the DISOWN method.

      diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html
      index 6e87a29a2..b9dcb83c5 100644
      --- a/Doc/Manual/Php.html
      +++ b/Doc/Manual/Php.html
      @@ -32,16 +32,22 @@
       
  • PHP Pragmas, Startup and Shutdown code +
  • Cross language polymorphism + -

    -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, @@ -95,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.

    @@ -479,7 +485,7 @@ One can include cpointer.i to generate PHP wrappers to int
     %module example
    -%include cpointer.i
    +%include "cpointer.i"
     %pointer_functions(int,intp)
     
     void add( int *in1, int *in2, int *result);
    @@ -513,7 +519,7 @@ parameter names as appropriate.
     
     
     %module example
    -%include typemaps.i
    +%include "typemaps.i"
     
     void add( int *INPUT, int *INPUT, int *OUTPUT);
     
    @@ -545,7 +551,7 @@ named typemap REFERENCE.
     
     
     %module example
    -%include phppointers.i
    +%include "phppointers.i"
     
     void add( int *REF, int *REF, int *REF);
     
    @@ -866,5 +872,381 @@ The %rinit and %rshutdown statements insert code
     into the request init and shutdown code respectively.
     

    +

    29.3 Cross language polymorphism

    + + +

    +Proxy classes provide a more natural, object-oriented way to access +extension classes. As described above, each proxy instance has an +associated C++ instance, and method calls to the proxy are passed to the +C++ instance transparently via C wrapper functions. +

    + +

    +This arrangement is asymmetric in the sense that no corresponding +mechanism exists to pass method calls down the inheritance chain from +C++ to PHP. In particular, if a C++ class has been extended in PHP +(by extending the proxy class), these extensions will not be visible +from C++ code. Virtual method calls from C++ are thus not able access +the lowest implementation in the inheritance chain. +

    + +

    +Changes have been made to SWIG 1.3.18 to address this problem and make +the relationship between C++ classes and proxy classes more symmetric. +To achieve this goal, new classes called directors are introduced at the +bottom of the C++ inheritance chain. Support for generating PHP classes +has been added in SWIG 1.3.40. The job of the directors is to route +method calls correctly, either to C++ implementations higher in the +inheritance chain or to PHP implementations lower in the inheritance +chain. The upshot is that C++ classes can be extended in PHP and from +C++ these extensions look exactly like native C++ classes. Neither C++ +code nor PHP code needs to know where a particular method is +implemented: the combination of proxy classes, director classes, and C +wrapper functions takes care of all the cross-language method routing +transparently. +

    + +

    29.3.1 Enabling directors

    + + +

    +The director feature is disabled by default. To use directors you +must make two changes to the interface file. First, add the "directors" +option to the %module directive, like this: +

    + +
    +
    +%module(directors="1") modulename
    +
    +
    + +

    +Without this option no director code will be generated. Second, you +must use the %feature("director") directive to tell SWIG which classes +and methods should get directors. The %feature directive can be applied +globally, to specific classes, and to specific methods, like this: +

    + +
    +
    +// generate directors for all classes that have virtual methods
    +%feature("director");         
    +
    +// generate directors for all virtual methods in class Foo
    +%feature("director") Foo;      
    +
    +// generate a director for just Foo::bar()
    +%feature("director") Foo::bar; 
    +
    +
    + +

    +You can use the %feature("nodirector") directive to turn off +directors for specific classes or methods. So for example, +

    + +
    +
    +%feature("director") Foo;
    +%feature("nodirector") Foo::bar;
    +
    +
    + +

    +will generate directors for all virtual methods of class Foo except +bar(). +

    + +

    +Directors can also be generated implicitly through inheritance. +In the following, class Bar will get a director class that handles +the methods one() and two() (but not three()): +

    + +
    +
    +%feature("director") Foo;
    +class Foo {
    +public:
    +    Foo(int foo);
    +    virtual void one();
    +    virtual void two();
    +};
    +
    +class Bar: public Foo {
    +public:
    +    virtual void three();
    +};
    +
    +
    + +

    +then at the PHP side you can define +

    + +
    +
    +require("mymodule.php");
    +
    +class MyFoo extends Foo {
    +  function one() {
    +     print "one from php\n";
    +  }
    +}
    +
    +
    + + +

    29.3.2 Director classes

    + + + + + +

    +For each class that has directors enabled, SWIG generates a new class +that derives from both the class in question and a special +Swig::Director class. These new classes, referred to as director +classes, can be loosely thought of as the C++ equivalent of the PHP +proxy classes. The director classes store a pointer to their underlying +PHP object. Indeed, this is quite similar to the "_cPtr" and "thisown" +members of the PHP proxy classes. +

    + +

    +For simplicity let's ignore the Swig::Director class and refer to the +original C++ class as the director's base class. By default, a director +class extends all virtual methods in the inheritance chain of its base +class (see the preceding section for how to modify this behavior). +Thus all virtual method calls, whether they originate in C++ or in +PHP via proxy classes, eventually end up in at the implementation in the +director class. The job of the director methods is to route these method +calls to the appropriate place in the inheritance chain. By "appropriate +place" we mean the method that would have been called if the C++ base +class and its extensions in PHP were seamlessly integrated. That +seamless integration is exactly what the director classes provide, +transparently skipping over all the messy extension API glue that binds +the two languages together. +

    + +

    +In reality, the "appropriate place" is one of only two possibilities: +C++ or PHP. Once this decision is made, the rest is fairly easy. If the +correct implementation is in C++, then the lowest implementation of the +method in the C++ inheritance chain is called explicitly. If the correct +implementation is in PHP, the Zend API is used to call the method of the +underlying PHP object (after which the usual virtual method resolution +in PHP automatically finds the right implementation). +

    + +

    +Now how does the director decide which language should handle the method call? +The basic rule is to handle the method in PHP, unless there's a good +reason not to. The reason for this is simple: PHP has the most +"extended" implementation of the method. This assertion is guaranteed, +since at a minimum the PHP proxy class implements the method. If the +method in question has been extended by a class derived from the proxy +class, that extended implementation will execute exactly as it should. +If not, the proxy class will route the method call into a C wrapper +function, expecting that the method will be resolved in C++. The wrapper +will call the virtual method of the C++ instance, and since the director +extends this the call will end up right back in the director method. Now +comes the "good reason not to" part. If the director method were to blindly +call the PHP method again, it would get stuck in an infinite loop. We avoid this +situation by adding special code to the C wrapper function that tells +the director method to not do this. The C wrapper function compares the +called and the declaring class name of the given method. If these are +not the same, then the C wrapper function tells the director to resolve +the method by calling up the C++ inheritance chain, preventing an +infinite loop. +

    + +

    +One more point needs to be made about the relationship between director +classes and proxy classes. When a proxy class instance is created in +PHP, SWIG creates an instance of the original C++ class and assigns it +to ->_cPtr. This is exactly what happens without directors +and is true even if directors are enabled for the particular class in +question. When a class derived from a proxy class is created, +however, SWIG then creates an instance of the corresponding C++ director +class. The reason for this difference is that user-defined subclasses +may override or extend methods of the original class, so the director +class is needed to route calls to these methods correctly. For +unmodified proxy classes, all methods are ultimately implemented in C++ +so there is no need for the extra overhead involved with routing the +calls through PHP. +

    + +

    29.3.3 Ownership and object destruction

    + + +

    +Memory management issues are slightly more complicated with directors +than for proxy classes alone. PHP instances hold a pointer to the +associated C++ director object, and the director in turn holds a pointer +back to the PHP object. By default, proxy classes own their C++ director +object and take care of deleting it when they are garbage collected. +

    + +

    +This relationship can be reversed by calling the special +->thisown property of the proxy class. After setting this +property to 0, the director class no longer destroys the PHP +object. Assuming no outstanding references to the PHP object remain, +the PHP object will be destroyed at the same time. This is a good thing, +since directors and proxies refer to each other and so must be created +and destroyed together. Destroying one without destroying the other will +likely cause your program to segfault. +

    + +

    +Here is an example: +

    + +
    +
    +class Foo {
    +public:
    +    ...
    +};
    +class FooContainer {
    +public:
    +    void addFoo(Foo *);
    +    ...
    +};
    +
    +
    + +
    + +
    +
    +$c = new FooContainer();
    +$a = new Foo();
    +$a->thisown = 0;
    +$c->addFoo($a);
    +
    +
    + +

    +In this example, we are assuming that FooContainer will take care of +deleting all the Foo pointers it contains at some point. +

    + +

    29.3.4 Exception unrolling

    + + +

    +With directors routing method calls to PHP, and proxies routing them +to C++, the handling of exceptions is an important concern. By default, the +directors ignore exceptions that occur during method calls that are +resolved in PHP. To handle such exceptions correctly, it is necessary +to temporarily translate them into C++ exceptions. This can be done with +the %feature("director:except") directive. The following code should +suffice in most cases: +

    + +
    +
    +%feature("director:except") {
    +    if ($error == FAILURE) {
    +        throw Swig::DirectorMethodException();
    +    }
    +}
    +
    +
    + +

    +This code will check the PHP error state after each method call from a +director into PHP, and throw a C++ exception if an error occurred. This +exception can be caught in C++ to implement an error handler. +Currently no information about the PHP error is stored in the +Swig::DirectorMethodException object, but this will likely change in the +future. +

    + +

    +It may be the case that a method call originates in PHP, travels up to +C++ through a proxy class, and then back into PHP via a director method. +If an exception occurs in PHP at this point, it would be nice for that +exception to find its way back to the original caller. This can be done +by combining a normal %exception directive with the +director:except handler shown above. Here is an example of a +suitable exception handler: +

    + +
    +
    +%exception {
    +    try { $action }
    +    catch (Swig::DirectorException &e) { SWIG_fail; }
    +}
    +
    +
    + +

    +The class Swig::DirectorException used in this example is actually a +base class of Swig::DirectorMethodException, so it will trap this +exception. Because the PHP error state is still set when +Swig::DirectorMethodException is thrown, PHP will register the exception +as soon as the C wrapper function returns. +

    + +

    29.3.5 Overhead and code bloat

    + + +

    +Enabling directors for a class will generate a new director method for +every virtual method in the class' inheritance chain. This alone can +generate a lot of code bloat for large hierarchies. Method arguments +that require complex conversions to and from target language types can +result in large director methods. For this reason it is recommended that +you selectively enable directors only for specific classes that are +likely to be extended in PHP and used in C++. +

    + +

    +Compared to classes that do not use directors, the call routing in the +director methods does add some overhead. In particular, at least one +dynamic cast and one extra function call occurs per method call from +PHP. Relative to the speed of PHP execution this is probably completely +negligible. For worst case routing, a method call that ultimately +resolves in C++ may take one extra detour through PHP in order to ensure +that the method does not have an extended PHP implementation. This could +result in a noticeable overhead in some cases. +

    + +

    +Although directors make it natural to mix native C++ objects with PHP +objects (as director objects) via a common base class pointer, one +should be aware of the obvious fact that method calls to PHP objects +will be much slower than calls to C++ objects. This situation can be +optimized by selectively enabling director methods (using the %feature +directive) for only those methods that are likely to be extended in PHP. +

    + +

    29.3.6 Typemaps

    + + +

    +Typemaps for input and output of most of the basic types from director +classes have been written. These are roughly the reverse of the usual +input and output typemaps used by the wrapper code. The typemap +operation names are 'directorin', 'directorout', and 'directorargout'. +The director code does not currently use any of the other kinds of +typemaps. It is not clear at this point which kinds are appropriate and +need to be supported. +

    + + +

    29.3.7 Miscellaneous

    + + +

    Director typemaps for STL classes are mostly in place, and hence you +should be able to use std::string, etc., as you would any other type. +

    + 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 f4867b69d..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
      @@ -339,7 +336,7 @@ python that you run the command with. Taking apart the command line: setup.py is the tradition)
    • build_ext -- telling distutils to build extensions
    • --inplace -- this tells distutils to put the extension lib in the current dir. - Other wise, it will put it inside a build hierarchy, and you'd have to move it to use it. + Otherwise, it will put it inside a build hierarchy, and you'd have to move it to use it.

    @@ -363,8 +360,8 @@ program using commands like this (shown for Linux):

     $ swig -python example.i
    -$ gcc -c -fPIC example.c
    -$ gcc -c -fPIC example_wrap.c -I/usr/local/include/python2.0
    +$ gcc -O2 -fPIC -c example.c
    +$ gcc -O2 -fPIC -c example_wrap.c -I/usr/local/include/python2.5
     $ gcc -shared example.o example_wrap.o -o _example.so
     
    @@ -433,7 +430,7 @@ extern int mod(int, int); extern double My_variable; %} -%include embed.i // Include code for a static version of Python +%include "embed.i" // Include code for a static version of Python
  • @@ -654,26 +651,19 @@ compiler. For example:
     $ swig -c++ -python example.i
    -$ g++ -c example.cxx
    -$ g++ -c example_wrap.cxx -I/usr/local/include/python2.0
    +$ g++ -O2 -fPIC -c example.cxx
    +$ g++ -O2 -fPIC -c example_wrap.cxx -I/usr/local/include/python2.5
     $ g++ -shared example.o example_wrap.o -o _example.so
     

    -On some platforms, you could also need to generate -position-independent code (PIC), by using a compiler option such as -fPIC. -Notably, the x86_64 (Opteron and EM64T) platform requires it, and when -using the GNU Compiler Suite, you will need to modify the previous example -as follows: +The -fPIC option tells GCC to generate position-independent code (PIC) +which is required for most architectures (it's not vital on x86, but +still a good idea as it allows code pages from the library to be shared between +processes). Other compilers may need a different option specified instead of +-fPIC.

    -
    -$ swig -c++ -python example.i
    -$ g++ -fPIC -c example.cxx
    -$ g++ -fPIC -c example_wrap.cxx -I/usr/local/include/python2.0
    -$ g++ -shared example.o example_wrap.o -o _example.so
    -
    -

    In addition to this, you may need to include additional library files to make it work. For example, if you are using the Sun C++ compiler on @@ -683,7 +673,7 @@ Solaris, you often need to add an extra library -lCrun like this:

     $ swig -c++ -python example.i
     $ CC -c example.cxx
    -$ CC -c example_wrap.cxx -I/usr/local/include/python2.0
    +$ CC -c example_wrap.cxx -I/usr/local/include/python2.5
     $ CC -G example.o example_wrap.o -L/opt/SUNWspro/lib -o _example.so -lCrun
     
    @@ -1144,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>
     

    @@ -1154,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: @@ -1178,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.

    @@ -1720,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).
     
    @@ -3861,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 2070db0c0..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).
    +
    +
    @@ -2393,7 +2397,7 @@ intset;
    -%include std_set.i
    +%include <std_set.i>
    @@ -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 d52f0441c..02d0ca3a4 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -174,13 +174,8 @@ int bar(int x); ...

    -The name of the module is supplied using the special %module -directive (or the -module command line option). This -directive must appear at the beginning of the file and is used to name -the resulting extension module (in addition, this name often defines -a namespace in the target language). If the module name is supplied on the -command line, it overrides the name specified with the -%module directive. +The module name is supplied using the special %module +directive. Modules are described further in the Modules Introduction section.

    @@ -335,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) */
      @@ -360,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 ...
       }
      @@ -376,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. +

    @@ -672,7 +677,6 @@ enum boolean {NO=0, YES=1}; enum months {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC}; %constant double BLAH = 42.37; -#define F_CONST (double) 5 // A floating pointer constant with cast #define PI_4 PI/4 #define FLAGS 0x04 | 0x08 | 0x40 @@ -711,8 +715,15 @@ the declaration

    defines a constant because PI was already defined as a constant and the value is known. +However, for the same conservative reasons even a constant with a simple cast will be ignored, such as

    +
    +
    +#define F_CONST (double) 5            // A floating pointer constant with cast
    +
    +
    +

    The use of constant expressions is allowed, but SWIG does not evaluate them. Rather, it passes them through to the output file and lets the C @@ -786,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 @@ -2361,7 +2378,7 @@ You can make a Vector look a lot like a class by writing a SWIG interfa #include "vector.h" %} -%include vector.h // Just grab original C header file +%include "vector.h" // Just grab original C header file %extend Vector { // Attach these functions to struct Vector Vector(double x, double y, double z) { Vector *v; @@ -2387,6 +2404,10 @@ You can make a Vector look a lot like a class by writing a SWIG interfa

    Note the usage of the $self special variable. Its usage is identical to a C++ 'this' pointer and should be used whenever access to the struct instance is required. +Also note that C++ constructor and destructor syntax has been used to simulate a constructor and destructor, even for C code. +There is one subtle difference to a normal C++ constructor implementation though and that is although the constructor declaration +is as per a normal C++ constructor, the newly constructed object must be returned as if the constructor declaration +had a return value, a Vector * in this case.

    @@ -2484,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); } %} @@ -2497,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);
     }
     %}
     
    @@ -2541,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).

    @@ -2624,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

    @@ -2711,6 +2750,10 @@ initialization code (in that order).

      +
    • Begin section.
      +A placeholder to put code at the beginning of the C/C++ wrapper file. +
    • +
    • Runtime code.
      This code is internal to SWIG and is used to include type-checking and other support functions that are used by the rest of the module. @@ -2883,10 +2926,16 @@ interface to your program. SWIG's %include directive to process an entire C source/header file. -
    • Make sure everything in the interface file uses ANSI C/C++syntax. +
    • Make sure everything in the interface file uses ANSI C/C++ syntax.
    • Make sure all necessary `typedef' declarations and -type-information is available in the interface file. +type-information is available in the interface file. +In particular, ensure that the type information is specified in the correct order as required by a C/C++ compiler. +Most importantly, define a type before it is used! A C compiler will tell you +if the full type information is not available if it is needed, whereas +SWIG will usually not warn or error out as it is designed to work without +full type information. However, if type information is not specified +correctly, the wrappers can be sub-optimal and even result in uncompileable C/C++ code.
    • If your program has a main() function, you may need to rename it (read on). @@ -2945,16 +2994,21 @@ extern void dump(FILE *f);

      Of course, in this case, our header file is pretty simple so we could -have made an interface file like this as well:

      +use a simpler approach and use an interface file like this:

       /* File : interface.i */
       %module mymodule
      -%include header.h
      +%{
      +#include "header.h"
      +%}
      +%include "header.h"
       

      -Naturally, your mileage may vary.

      +The main advantage of this approach is minimal maintenance of an interface file for when the header file changes in the future. +In more complex projects, an interface file containing numerous %include and #include statements like this is one of the most common approaches to interface file design due to lower maintenance overhead. +

      5.7.3 Why use separate interface files?

      diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index ef7487ff8..d1498224f 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.

    @@ -3817,7 +3836,7 @@ When this conflict occurs, you will get an error message that resembles this:
    -example.i:26. Error. 'foo' is multiply defined in the generated module.
    +example.i:26. Error. 'foo' is multiply defined in the generated target language module.
     example.i:23. Previous declaration of 'foo'
     
    @@ -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/Tcl.html b/Doc/Manual/Tcl.html index b36395cab..b37df2853 100644 --- a/Doc/Manual/Tcl.html +++ b/Doc/Manual/Tcl.html @@ -66,6 +66,7 @@

    +
  • Tcl/Tk Stubs @@ -190,7 +191,7 @@ extern int mod(int, int); extern double My_variable; %} -%include tclsh.i // Include code for rebuilding tclsh +%include "tclsh.i" // Include code for rebuilding tclsh @@ -1501,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).
     
    @@ -2822,7 +2823,7 @@ int print_args(char **argv) { return i; } %} -%include tclsh.i +%include "tclsh.i" @@ -3409,5 +3410,27 @@ short, but clever Tcl script can be combined with SWIG to do many interesting things.

    +

    33.10 Tcl/Tk Stubs

    + + +

    +For background information about the Tcl Stubs feature, see +http://www.tcl.tk/doc/howto/stubs.html. +

    + +

    +As of SWIG 1.3.10, the generated C/C++ wrapper will use the Tcl Stubs +feature if compiled with -DUSE_TCL_STUBS. +

    + +

    +As of SWIG 1.3.40, the generated C/C++ wrapper will use the Tk Stubs +feature if compiled with -DUSE_TK_STUBS. Also, you can override +the minimum version to support which is passed to Tcl_InitStubs() +and Tk_InitStubs() with -DSWIG_TCL_STUBS_VERSION="8.3" +or the version being compiled with using +-DSWIG_TCL_STUBS_VERSION=TCL_VERSION. +

    + diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index 777184069..14623b37d 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -22,25 +22,31 @@
  • Typemap specifications -
  • Pattern matching rules +
  • Pattern matching rules
  • Code generation rules
  • Common typemap methods -
  • Typemaps for multiple languages +
  • Typemaps for multiple target languages
  • Optimal code generation when returning by value
  • Multi-argument typemaps
  • The run-time type checker
  • Typemaps and overloading
  • More about %apply and %clear @@ -83,10 +89,6 @@ -

    -Disclaimer: This chapter is under construction! -

    -

    10.1 Introduction

    @@ -225,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).

    @@ -655,7 +660,7 @@ of "The C Programming Language" by Kernighan and Ritchie or This section describes the behavior of the %typemap directive itself.

    -

    10.2.1 Defining a typemap

    +

    10.2.1 Defining a typemap

    @@ -676,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.

    @@ -988,11 +994,12 @@ It should be noted that for scoping to work, SWIG has to know that stringclass string.

    -

    10.3 Pattern matching rules

    +

    10.3 Pattern matching rules

    -The section describes the pattern matching rules by which C datatypes are associated with typemaps. +The section describes the pattern matching rules by which C/C++ datatypes are associated with typemaps. +The matching rules can be observed in practice by using the debugging options also described.

    10.3.1 Basic matching rules

    @@ -1007,18 +1014,19 @@ is used.
    • Typemaps that exactly match TYPE and NAME.
    • Typemaps that exactly match TYPE only. +
    • If TYPE is a C++ template of type T< TPARMS >, where TPARMS are the template parameters, + the type is stripped of the template parameters and the following checks are then made: +
        +
      • Typemaps that exactly match T and NAME. +
      • Typemaps that exactly match T only. +

    -If TYPE includes qualifiers (const, volatile, etc.), they are stripped and the following -checks are made: +If TYPE includes qualifiers (const, volatile, etc.), they are stripped to form a new stripped type +and the matching rules above are repeated on the stripped type.

    -
      -
    • Typemaps that match the stripped TYPE and NAME. -
    • Typemaps that match the stripped TYPE only. -
    -

    If TYPE is an array. The following transformation is made:

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

    10.3.2 Typedef reductions

    +

    10.3.2 Typedef reductions

    @@ -1241,6 +1249,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

    @@ -1378,7 +1406,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

    @@ -1408,6 +1436,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

    @@ -1646,6 +1873,7 @@ each type must have its own local variable declaration.

    Within all typemaps, the following special variables are expanded. +This is by no means a complete list as some target languages have additional special variables which are documented in the language specific chapters.

    @@ -1892,6 +2120,86 @@ Another approach, which only works for arrays is to use the $1_basetype +

    10.4.4 Special variable macros

    + + +

    +Special variable macros are like macro functions in that they take one or more input arguments +which are used for the macro expansion. +They look like macro/function calls but use the special variable $ prefix to the macro name. +Note that unlike normal macros, the expansion is not done by the preprocessor, +it is done during the SWIG parsing/compilation stages. +The following special variable macros are available across all language modules. +

    + +

    10.4.4.1 $descriptor(type)

    + + +

    +This macro expands into the type descriptor structure for any C/C++ type specified in type. +It behaves like the $1_descriptor special variable described above except that the type to expand is +taken from the macro argument rather than inferred from the typemap type. +For example, $descriptor(std::vector<int> *) will expand into SWIGTYPE_p_std__vectorT_int_t. +This macro is mostly used in the scripting target languages and is demonstrated later in the Run-time type checker usage section. +

    + +

    10.4.4.2 $typemap(method, typepattern)

    + + +

    +This macro uses the pattern matching rules described earlier to lookup and +then substitute the special variable macro with the code in the matched typemap. +The typemap to search for is specified by the arguments, where method is the typemap method name and +typepattern is a type pattern as per the %typemap specification in the Defining a typemap section. +

    + +

    +The special variables within the matched typemap are expanded into those for the matched typemap type, +not the typemap within which the macro is called. +In practice, there is little use for this macro in the scripting target languages. +It is mostly used in the target languages that are statically typed as a way to obtain the target language type given the C/C++ type and more commonly only when the C++ type is a template parameter. +

    + +

    +The example below is for C# only and uses some typemap method names documented in the C# chapter, but it shows some of the possible syntax variations. +

    + +
    +
    +%typemap(cstype) unsigned long    "uint"
    +%typemap(cstype) unsigned long bb "bool"
    +%typemap(cscode) BarClass %{
    +  void foo($typemap(cstype, unsigned long aa) var1,
    +           $typemap(cstype, unsigned long bb) var2,
    +           $typemap(cstype, (unsigned long bb)) var3,
    +           $typemap(cstype, unsigned long) var4)
    +  {
    +    // do something
    +  }
    +%}
    +
    +
    + +

    +The result is the following expansion +

    + +
    +
    +%typemap(cstype) unsigned long    "uint"
    +%typemap(cstype) unsigned long bb "bool"
    +%typemap(cscode) BarClass %{
    +  void foo(uint var1,
    +           bool var2,
    +           bool var3,
    +           uint var4)
    +  {
    +    // do something
    +  }
    +%}
    +
    +
    +

    10.5 Common typemap methods

    @@ -2600,12 +2908,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:

    @@ -2636,8 +2944,9 @@ The example above also shows a common approach of issuing a warning for an as ye

    The "out" typemap is the main typemap for return types. This typemap supports an optional attribute flag called "optimal", which is for reducing -temporary variables and the amount of generated code. -It only really makes a difference when returning objects by value and it cannot always be used, +temporary variables and the amount of generated code, thereby giving the compiler the opportunity to +use return value optimization for generating faster executing code. +It only really makes a difference when returning objects by value and has some limitations on usage, as explained later on.

    @@ -2695,7 +3004,7 @@ XX(const XX &) Note that three objects are being created as well as an assignment. Wouldn't it be great if the XX::create() method was the only time a constructor was called? As the method returns by value, this is asking a lot and the code that SWIG generates by default -makes it impossible for the compiler to make this type of optimisation. +makes it impossible for the compiler to use return value optimisation (RVO). However, this is where the "optimal" attribute in the "out" typemap can help out. If the typemap code is kept the same and just the "optimal" attribute specified like this:

    @@ -2754,7 +3063,7 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() {

    The major difference is the result temporary variable holding the value returned from XX::create() is no longer generated and instead the copy constructor call is made directly from the value returned by XX::create(). -With modern compiler optimisations turned on, the copy is not actually done, in fact the object is never created +With modern compilers implementing RVO, the copy is not actually done, in fact the object is never created on the stack in XX::create() at all, it is simply created directly on the heap. In the first instance, the $1 special variable in the typemap is expanded into result. In the second instance, $1 is expanded into XX::create() and this is essentially @@ -2762,7 +3071,7 @@ what the "optimal" attribute is telling SWIG to do.

    -This kind of optimisation is not turned on by default as it has a number of restrictions. +The "optimal" attribute optimisation is not turned on by default as it has a number of restrictions. Firstly, some code cannot be condensed into a simple call for passing into the copy constructor. One common occurrence is when %exception is used. Consider adding the following %exception to the example: @@ -2786,8 +3095,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) {
    @@ -2808,8 +3117,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.
     
    @@ -3114,7 +3423,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.

    @@ -3294,7 +3603,7 @@ structures rather than creating new ones. These swig_module_info structures are chained together in a circularly linked list.

    -

    10.10.2 Usage

    +

    10.10.2 Usage

    This section covers how to use these functions from typemaps. To learn how to @@ -3334,8 +3643,8 @@ type tables and improves efficiency.

    Occasionally, you might need to write a typemap that needs to convert -pointers of other types. To handle this, a special macro substitution -$descriptor(type) can be used to generate the SWIG type +pointers of other types. To handle this, the special variable macro +$descriptor(type) covered earlier can be used to generate the SWIG type descriptor name for any C datatype. For example:

    @@ -3973,6 +4282,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/Doc/Manual/Windows.html b/Doc/Manual/Windows.html index bc8c8fa51..5d16a8b9f 100644 --- a/Doc/Manual/Windows.html +++ b/Doc/Manual/Windows.html @@ -248,7 +248,7 @@ Execute the steps in the order shown and don't use spaces in path names. In fact
      1. Download the following packages from the MinGW download page - or MinGW SourceForge download page. + or MinGW SourceForge download page. Note that at the time of writing, the majority of these are in the Current release list and some are in the Snapshot or Previous release list.
          diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 37a02c59f..daee3d220 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -319,7 +319,7 @@ python_clean: rm -f *_wrap* *~ .~* mypython@EXEEXT@ *.pyc rm -f core @EXTRA_CLEAN@ rm -f *.@OBJEXT@ *@SO@ *@PYTHON_SO@ - if [ -f runme.py ]; then (rm -f runme3.py runme3.py.bak;) fi; + if [ -f runme.py ]; then rm -f runme3.py runme3.py.bak; fi ################################################################## @@ -336,12 +336,13 @@ OCTAVE_SO = @OCTAVE_SO@ # ---------------------------------------------------------------- # Build a C dynamically loadable module +# Note: Octave requires C++ compiler when compiling C wrappers # ---------------------------------------------------------------- octave: $(SRCS) $(SWIG) -octave $(SWIGOPT) $(INTERFACEPATH) $(CXX) -g -c $(CCSHARED) $(CXXFLAGS) $(ICXXSRCS) $(CXXSRCS) $(INCLUDES) -I$(OCTAVE_INCLUDE) - $(CC) -g -c $(CCSHARED) $(CFLAGS) $(SRCS) $(INCLUDES) $(OCTAVE_INCLUDE) + $(CC) -g -c $(CCSHARED) $(CFLAGS) $(SRCS) $(INCLUDES) $(LDSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(OCTAVE_DLNK) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(OCTAVE_SO) # ----------------------------------------------------------------- @@ -1124,11 +1125,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/index.html b/Examples/perl5/index.html index 254bd41f5..5648c587d 100644 --- a/Examples/perl5/index.html +++ b/Examples/perl5/index.html @@ -66,24 +66,6 @@ The examples have been extensively tested on the following platforms: Please see the Windows page in the main manual for information on using the examples on Windows.

          -The most recent version of Perl used for testing is as follows: - -

          -
          -% perl -version
          -This is perl, v5.6.0 built for sun4-solaris
          -
          -Copyright 1987-2000, Larry Wall
          -
          -Perl may be copied only under the terms of either the Artistic License or the
          -GNU General Public License, which may be found in the Perl 5.0 source kit.
          -
          -Complete documentation for Perl, including FAQ lists, should be found on
          -this system using `man perl' or `perldoc perl'.  If you have access to the
          -Internet, point your browser at http://www.perl.com/, the Perl Home Page.
          -
          -
          -

          Due to wide variations in the Perl C API and differences between versions such as the ActivePerl release for Windows, the code generated by SWIG is extremely messy. We have made every attempt to maintain compatibility with 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/callback/Makefile b/Examples/php/callback/Makefile new file mode 100644 index 000000000..42597202b --- /dev/null +++ b/Examples/php/callback/Makefile @@ -0,0 +1,22 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm +SWIGOPT = + +all:: + $(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' php_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' php_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile php_clean + rm -f $(TARGET).php + +check: all + $(MAKE) -f $(TOP)/Makefile php_run diff --git a/Examples/php/callback/example.cxx b/Examples/php/callback/example.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/php/callback/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/php/callback/example.h b/Examples/php/callback/example.h new file mode 100644 index 000000000..2a0194999 --- /dev/null +++ b/Examples/php/callback/example.h @@ -0,0 +1,22 @@ +/* File : example.h */ + +#include + +class Callback { +public: + virtual ~Callback() { std::cout << "Callback::~Callback()" << std:: endl; } + virtual void run() { std::cout << "Callback::run()" << std::endl; } +}; + + +class Caller { +private: + Callback *_callback; +public: + Caller(): _callback(0) {} + ~Caller() { delCallback(); } + void delCallback() { delete _callback; _callback = 0; } + void setCallback(Callback *cb) { delCallback(); _callback = cb; } + void call() { if (_callback) _callback->run(); } +}; + diff --git a/Examples/php/callback/example.i b/Examples/php/callback/example.i new file mode 100644 index 000000000..90beda01a --- /dev/null +++ b/Examples/php/callback/example.i @@ -0,0 +1,13 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +%include "std_string.i" + +/* turn on director wrapping Callback */ +%feature("director") Callback; + +%include "example.h" + diff --git a/Examples/php/callback/index.html b/Examples/php/callback/index.html new file mode 100644 index 000000000..2aa720e24 --- /dev/null +++ b/Examples/php/callback/index.html @@ -0,0 +1,19 @@ + + +SWIG:Examples:php:callback + + + + + +SWIG/Examples/php/callback/ +
          + +

          Implementing C++ callbacks in PHP

          + +

          +This example illustrates how to use directors to implement C++ callbacks in PHP. + +


          + + diff --git a/Examples/php/callback/runme.php b/Examples/php/callback/runme.php new file mode 100644 index 000000000..2be71994f --- /dev/null +++ b/Examples/php/callback/runme.php @@ -0,0 +1,47 @@ +thisown = 0; +$caller->setCallback($callback); +$caller->call(); +$caller->delCallback(); + +print "\n"; +print "Adding and calling a PHP callback\n"; +print "------------------------------------\n"; + +# Add a PHP callback. + +$callback = new PhpCallback(); +$callback->thisown = 0; +$caller->setCallback($callback); +$caller->call(); +$caller->delCallback(); + +# All done. + +print "php exit\n"; + +?> diff --git a/Examples/php/check.list b/Examples/php/check.list index 9daad455b..28c7a619f 100644 --- a/Examples/php/check.list +++ b/Examples/php/check.list @@ -1,16 +1,18 @@ # see top-level Makefile.in # (see also top-level configure.in kludge) +callback class constants cpointer disown enum +extend funcptr overloading pointer pragmas -reference proxy +reference simple sync value diff --git a/Examples/php/class/Makefile b/Examples/php/class/Makefile index 252a72660..1bc0beaab 100644 --- a/Examples/php/class/Makefile +++ b/Examples/php/class/Makefile @@ -4,7 +4,7 @@ CXXSRCS = example.cxx TARGET = example INTERFACE = example.i LIBS = -SWIGOPT = -noproxy +SWIGOPT = all:: $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ diff --git a/Examples/php/class/runme.php b/Examples/php/class/runme.php index a9ca657dc..12b686052 100644 --- a/Examples/php/class/runme.php +++ b/Examples/php/class/runme.php @@ -1,22 +1,20 @@ x = 20; +$c->y = 30; +$s->x = -10; +$s->y = 5; print "\nHere is their current position:\n"; -print " Circle = (" . Shape_x_get($c) . "," . Shape_y_get($c) . ")\n"; -print " Square = (" . Shape_x_get($s) . "," . Shape_y_get($s) . ")\n"; +print " Circle = ({$c->x},{$c->y})\n"; +print " Square = ({$s->x},{$s->y})\n"; # ----- Call some methods ----- @@ -39,18 +37,16 @@ print " Square = (" . Shape_x_get($s) . "," . Shape_y_get($s) . ")\n"; # invoke the appropriate virtual method on each object. print "\nHere are some properties of the shapes:\n"; foreach (array($c,$s) as $o) { - print " $o\n"; - print " area = " . Shape_area($o) . "\n"; - print " perimeter = " . Shape_perimeter($o) . "\n"; - } + print " ". get_class($o) . "\n"; + print " area = {$o->area()}\n"; + print " perimeter = {$o->perimeter()}\n"; +} # ----- Delete everything ----- print "\nGuess I'll clean up now\n"; # Note: this invokes the virtual destructor -#delete_Shape($c); -#delete_Shape($s); $c = NULL; $s = NULL; @@ -58,7 +54,7 @@ $s = NULL; # the square. $o = NULL; -print nshapes() . " shapes remain\n"; +print Shape::get_nshapes() . " shapes remain\n"; print "Goodbye\n"; ?> 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/php/extend/Makefile b/Examples/php/extend/Makefile new file mode 100644 index 000000000..42597202b --- /dev/null +++ b/Examples/php/extend/Makefile @@ -0,0 +1,22 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm +SWIGOPT = + +all:: + $(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' php_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' php_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile php_clean + rm -f $(TARGET).php + +check: all + $(MAKE) -f $(TOP)/Makefile php_run diff --git a/Examples/php/extend/example.cxx b/Examples/php/extend/example.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/php/extend/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/php/extend/example.h b/Examples/php/extend/example.h new file mode 100644 index 000000000..b27ab9711 --- /dev/null +++ b/Examples/php/extend/example.h @@ -0,0 +1,56 @@ +/* File : example.h */ + +#include +#include +#include +#include +#include + +class Employee { +private: + std::string name; +public: + Employee(const char* n): name(n) {} + virtual std::string getTitle() { return getPosition() + " " + getName(); } + virtual std::string getName() { return name; } + virtual std::string getPosition() const { return "Employee"; } + virtual ~Employee() { printf("~Employee() @ %p\n", this); } +}; + + +class Manager: public Employee { +public: + Manager(const char* n): Employee(n) {} + virtual std::string getPosition() const { return "Manager"; } +}; + + +class EmployeeList { + std::vector list; +public: + EmployeeList() { + list.push_back(new Employee("Bob")); + list.push_back(new Employee("Jane")); + list.push_back(new Manager("Ted")); + } + void addEmployee(Employee *p) { + list.push_back(p); + std::cout << "New employee added. Current employees are:" << std::endl; + std::vector::iterator i; + for (i=list.begin(); i!=list.end(); i++) { + std::cout << " " << (*i)->getTitle() << std::endl; + } + } + const Employee *get_item(int i) { + return list[i]; + } + ~EmployeeList() { + std::vector::iterator i; + std::cout << "~EmployeeList, deleting " << list.size() << " employees." << std::endl; + for (i=list.begin(); i!=list.end(); i++) { + delete *i; + } + std::cout << "~EmployeeList empty." << std::endl; + } +}; + diff --git a/Examples/php/extend/example.i b/Examples/php/extend/example.i new file mode 100644 index 000000000..c8ec32e09 --- /dev/null +++ b/Examples/php/extend/example.i @@ -0,0 +1,15 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +%include "std_vector.i" +%include "std_string.i" + +/* turn on director wrapping for Manager */ +%feature("director") Employee; +%feature("director") Manager; + +%include "example.h" + diff --git a/Examples/php/extend/index.html b/Examples/php/extend/index.html new file mode 100644 index 000000000..32c6a4913 --- /dev/null +++ b/Examples/php/extend/index.html @@ -0,0 +1,19 @@ + + +SWIG:Examples:php:extend + + + + + +SWIG/Examples/php/extend/ +
          + +

          Extending a simple C++ class in PHP

          + +

          +This example illustrates the extending of a C++ class with cross language polymorphism. + +


          + + diff --git a/Examples/php/extend/runme.php b/Examples/php/extend/runme.php new file mode 100644 index 000000000..158683142 --- /dev/null +++ b/Examples/php/extend/runme.php @@ -0,0 +1,76 @@ +getName() . " is a " . $e->getPosition() . "\n"; +printf("Just call her \"%s\"\n", $e->getTitle()); +print "----------------------\n"; + +# Create a new EmployeeList instance. This class does not have a C++ +# director wrapper, but can be used freely with other classes that do. + +$list = new EmployeeList(); + +# EmployeeList owns its items, so we must surrender ownership of objects +# we add. This involves first clearing the ->disown member to tell the +# C++ director to start reference counting. + +$e->thisown = 0; +$list->addEmployee($e); +print "----------------------\n"; + +# Now we access the first four items in list (three are C++ objects that +# EmployeeList's constructor adds, the last is our CEO). The virtual +# methods of all these instances are treated the same. For items 0, 1, and +# 2, both all methods resolve in C++. For item 3, our CEO, getTitle calls +# getPosition which resolves in PHP. The call to getPosition is +# slightly different, however, from the e.getPosition() call above, since +# now the object reference has been "laundered" by passing through +# EmployeeList as an Employee*. Previously, PHP resolved the call +# immediately in CEO, but now PHP thinks the object is an instance of +# class Employee (actually EmployeePtr). So the call passes through the +# Employee proxy class and on to the C wrappers and C++ director, +# eventually ending up back at the CEO implementation of getPosition(). +# The call to getTitle() for item 3 runs the C++ Employee::getTitle() +# method, which in turn calls getPosition(). This virtual method call +# passes down through the C++ director class to the PHP implementation +# in CEO. All this routing takes place transparently. + +print "(position, title) for items 0-3:\n"; + +printf(" %s, \"%s\"\n", $list->get_item(0)->getPosition(), $list->get_item(0)->getTitle()); +printf(" %s, \"%s\"\n", $list->get_item(1)->getPosition(), $list->get_item(1)->getTitle()); +printf(" %s, \"%s\"\n", $list->get_item(2)->getPosition(), $list->get_item(2)->getTitle()); +printf(" %s, \"%s\"\n", $list->get_item(3)->getPosition(), $list->get_item(3)->getTitle()); +print "----------------------\n"; + +# Time to delete the EmployeeList, which will delete all the Employee* +# items it contains. The last item is our CEO, which gets destroyed as its +# reference count goes to zero. The PHP destructor runs, and is still +# able to call the getName() method since the underlying C++ object still +# exists. After this destructor runs the remaining C++ destructors run as +# usual to destroy the object. + +unset($list); +print "----------------------\n"; + +# All done. + +print "php exit\n"; + +?> diff --git a/Examples/php/reference/Makefile b/Examples/php/reference/Makefile index 252a72660..1bc0beaab 100644 --- a/Examples/php/reference/Makefile +++ b/Examples/php/reference/Makefile @@ -4,7 +4,7 @@ CXXSRCS = example.cxx TARGET = example INTERFACE = example.i LIBS = -SWIGOPT = -noproxy +SWIGOPT = all:: $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ diff --git a/Examples/php/reference/example.cxx b/Examples/php/reference/example.cxx index 3e13841d2..13e47eade 100644 --- a/Examples/php/reference/example.cxx +++ b/Examples/php/reference/example.cxx @@ -17,7 +17,7 @@ Vector operator+(const Vector &a, const Vector &b) { return r; } -char *Vector::print() { +char *Vector::as_string() { static char temp[512]; sprintf(temp,"Vector %p (%g,%g,%g)", this, x,y,z); return temp; @@ -47,4 +47,3 @@ int VectorArray::size() { printf("VectorArray: size %d self=%p\n",maxsize,this); return maxsize; } - diff --git a/Examples/php/reference/example.h b/Examples/php/reference/example.h index 4915adb1b..1b88cbf5c 100644 --- a/Examples/php/reference/example.h +++ b/Examples/php/reference/example.h @@ -7,7 +7,7 @@ public: Vector() : x(0), y(0), z(0) { }; Vector(double x, double y, double z) : x(x), y(y), z(z) { }; friend Vector operator+(const Vector &a, const Vector &b); - char *print(); + char *as_string(); }; class VectorArray { diff --git a/Examples/php/reference/example.i b/Examples/php/reference/example.i index 55d1828a8..d6122866b 100644 --- a/Examples/php/reference/example.i +++ b/Examples/php/reference/example.i @@ -1,6 +1,10 @@ /* File : example.i */ -/* This file has a few "typical" uses of C++ references. */ +/* This example has nothing to do with references but the name is used by all + * the other languages so it's hard to rename to something more meaningful. + * + * Mostly it shows how to use %extend. + */ %module example @@ -12,7 +16,7 @@ class Vector { public: Vector(double x, double y, double z); ~Vector(); - char *print(); + char *as_string(); }; /* This helper function calls an overloaded operator */ @@ -41,4 +45,3 @@ public: } } }; - diff --git a/Examples/php/reference/runme.php b/Examples/php/reference/runme.php index 00aaa5298..5d264ee43 100644 --- a/Examples/php/reference/runme.php +++ b/Examples/php/reference/runme.php @@ -1,18 +1,17 @@ as_string()}\n"; +print " Created b: {$b->as_string()}\n"; # ----- Call an overloaded operator ----- @@ -23,56 +22,28 @@ print " Created b: $b " . Vector_print($b) . "\n"; # It returns a new allocated object. print "Adding a+b\n"; -$c = addv($a,$b); -print " a+b =". Vector_print($c)."\n"; - -# Note: Unless we free the result, a memory leak will occur -$c = None; +$c = example::addv($a, $b); +print " a+b ={$c->as_string()}\n"; # ----- Create a vector array ----- -# Note: Using the high-level interface here print "Creating an array of vectors\n"; -$va = new_VectorArray(10); +$va = new VectorArray(10); -print " va: $va size=".VectorArray_size($va)."\n"; +print " va: size={$va->size()}\n"; # ----- Set some values in the array ----- # These operators copy the value of $a and $b to the vector array -VectorArray_set($va,0,$a); -VectorArray_set($va,1,$b); - -VectorArray_get($va,0); -# This will work, but it will cause a memory leak! - -VectorArray_set($va,2,addv($a,$b)); - -# The non-leaky way to do it - -$c = addv($a,$b); -VectorArray_set($va,3,$c); -$c = None; +$va->set(0, $a); +$va->set(1, $b); +$va->set(2, addv($a, $b)); # Get some values from the array print "Getting some array values\n"; for ($i = 0; $i < 5; $i++) { -print "do $i\n"; - print " va($i) = ". Vector_print(VectorArray_get($va,$i)). "\n"; + print " va[$i] = {$va->get($i)->as_string()}\n"; } -# Watch under resource meter to check on this -#print "Making sure we don't leak memory.\n"; -#for ($i = 0; $i < 1000000; $i++) { -# $c = VectorArray_get($va,$i % 10); -#} - -# ----- Clean up ----- -print "Cleaning up\n"; -# wants fixing FIXME -$va = None; -$a = None; -$b = None; - ?> diff --git a/Examples/python/callback/example.h b/Examples/python/callback/example.h index 1a0e8c432..2a0194999 100644 --- a/Examples/python/callback/example.h +++ b/Examples/python/callback/example.h @@ -1,6 +1,5 @@ /* File : example.h */ -#include #include class Callback { 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/multimap/example.i b/Examples/ruby/multimap/example.i index 56952ec9e..f68422a18 100644 --- a/Examples/ruby/multimap/example.i +++ b/Examples/ruby/multimap/example.i @@ -20,7 +20,7 @@ extern int gcd(int x, int y); if (TYPE($input) != T_ARRAY) { SWIG_exception(SWIG_ValueError, "Expected an array"); } - $1 = RARRAY($input)->len; + $1 = RARRAY_LEN($input); if ($1 == 0) { SWIG_exception(SWIG_ValueError, "List must contain at least 1 element"); } @@ -47,7 +47,7 @@ extern int gcdmain(int argc, char *argv[]); SWIG_exception(SWIG_ValueError, "Expected a string"); } $1 = STR2CSTR($input); - $2 = RSTRING($input)->len; + $2 = RSTRING_LEN($input); } extern int count(char *bytes, int len, char c); @@ -61,7 +61,7 @@ extern int count(char *bytes, int len, char c); SWIG_exception(SWIG_ValueError,"Expected a string"); } temp = STR2CSTR($input); - $2 = RSTRING($input)->len; + $2 = RSTRING_LEN($input); $1 = (char *) malloc($2+1); memmove($1,temp,$2); } 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/allegrocl/Makefile.in b/Examples/test-suite/allegrocl/Makefile.in index df7193389..5f75bfc08 100644 --- a/Examples/test-suite/allegrocl/Makefile.in +++ b/Examples/test-suite/allegrocl/Makefile.in @@ -89,8 +89,12 @@ SKIP_CPP_STD_CASES = Yes include $(srcdir)/../common.mk +# Overridden variables here # SWIGOPT += -debug-module 4 +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: $(setup) @@ -110,9 +114,9 @@ include $(srcdir)/../common.mk # Runs the testcase. A testcase is only run if # a file is found which has _runme.lisp appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(ALLEGROCLBIN) -batch -s $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(ALLEGROCLBIN) -batch -s $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi %.clean: @rm -f $*.cl diff --git a/Examples/test-suite/catches.i b/Examples/test-suite/catches.i new file mode 100644 index 000000000..8f09ae24c --- /dev/null +++ b/Examples/test-suite/catches.i @@ -0,0 +1,33 @@ +%module catches + +%{ +#if defined(_MSC_VER) + #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) +#endif +%} + +%include // for throws(...) typemap + +%catches(int, const char *, const ThreeException&) test_catches(int i); +%catches(int, ...) test_exception_specification(int i); // override the exception specification +%catches(...) test_catches_all(int i); + +%inline %{ +struct ThreeException {}; +void test_catches(int i) { + if (i == 1) { + throw int(1); + } else if (i == 2) { + throw (const char *)"two"; + } else if (i == 3) { + throw ThreeException(); + } +} +void test_exception_specification(int i) throw(int, const char *, const ThreeException&) { + test_catches(i); +} +void test_catches_all(int i) { + test_catches(i); +} +%} + diff --git a/Examples/test-suite/cffi/Makefile.in b/Examples/test-suite/cffi/Makefile.in index c34519633..bf21b3552 100644 --- a/Examples/test-suite/cffi/Makefile.in +++ b/Examples/test-suite/cffi/Makefile.in @@ -11,10 +11,14 @@ top_builddir = @top_builddir@ include $(srcdir)/../common.mk +# Overridden variables here # no C++ tests for now CPP_TEST_CASES = #C_TEST_CASES += +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: $(setup) @@ -34,9 +38,9 @@ CPP_TEST_CASES = # Runs the testcase. A testcase is only run if # a file is found which has _runme.lisp appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(CFFIBIN) -batch -s $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(CFFIBIN) -batch -s $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi # Clean: (does nothing, we dont generate extra cffi code) %.clean: diff --git a/Examples/test-suite/char_strings.i b/Examples/test-suite/char_strings.i index 12e4b5aa2..2561108c6 100644 --- a/Examples/test-suite/char_strings.i +++ b/Examples/test-suite/char_strings.i @@ -149,6 +149,18 @@ const char global_const_char_array2[sizeof(CPLUSPLUS_MSG)+1] = CPLUSPLUS_MSG; %inline %{ // char *& tests +char *&GetCharPointerRef() { + static char str[] = CPLUSPLUS_MSG; + static char *ptr = str; + return ptr; +} + +bool SetCharPointerRef(char *&str, unsigned int number) { + static char static_str[] = CPLUSPLUS_MSG; + strcpy(static_str, str); + return check(static_str, number); +} + const char *&GetConstCharPointerRef() { static const char str[] = CPLUSPLUS_MSG; static const char *ptr = str; diff --git a/Examples/test-suite/chicken/Makefile.in b/Examples/test-suite/chicken/Makefile.in index 764518880..42fe6100a 100644 --- a/Examples/test-suite/chicken/Makefile.in +++ b/Examples/test-suite/chicken/Makefile.in @@ -23,70 +23,73 @@ EXTRA_TEST_CASES += chicken_ext_test.externaltest include $(srcdir)/../common.mk - # Overridden variables here SWIGOPT += -nounit +# Custom tests - tests with additional commandline options +# If there exists a PROXYSUFFIX runme file, we also generate the wrapper +# with the -proxy argument +%.cppproxy: SWIGOPT += -proxy +%.cppproxy: SCRIPTSUFFIX = $(PROXYSUFFIX) + +%.cproxy: SWIGOPT += -proxy +%.cproxy: SCRIPTSUFFIX = $(PROXYSUFFIX) + +%.multiproxy: SWIGOPT += -proxy -noclosuses +%.multiproxy: SCRIPTSUFFIX = $(PROXYSUFFIX) + # Rules for the different types of tests %.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(PROXYSUFFIX) ]; then ( \ - $(MAKE) $*.cppproxy; ) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(PROXYSUFFIX) ]; then \ + $(MAKE) $*.cppproxy; \ + fi %.ctest: $(setup) +$(swig_and_compile_c) $(run_testcase) - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(PROXYSUFFIX) ]; then ( \ - $(MAKE) $*.cproxy; ) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(PROXYSUFFIX) ]; then \ + $(MAKE) $*.cproxy; \ + fi %.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(PROXYSUFFIX) ]; then ( \ - $(MAKE) $*.multiproxy; ) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(PROXYSUFFIX) ]; then \ + $(MAKE) $*.multiproxy; \ + fi %.externaltest: $(setup) +$(swig_and_compile_external) $(run_testcase) -# Runs the testcase. A testcase is only run if -# a file is found which has _runme.scm appended after the testcase name. -run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(CHICKEN_CSI) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; - -# If there exists a PROXYSUFFIX runme file, we also generate the wrapper -# with the -proxy argument -%.cppproxy: SWIGOPT += -proxy -%.cppproxy: SCRIPTSUFFIX = $(PROXYSUFFIX) %.cppproxy: echo "$(ACTION)ing testcase $* (with run test) under chicken with -proxy" +$(swig_and_compile_cpp) $(run_testcase) -%.cproxy: SWIGOPT += -proxy -%.cproxy: SCRIPTSUFFIX = $(PROXYSUFFIX) %.cproxy: echo "$(ACTION)ing testcase $* (with run test) under chicken with -proxy" +$(swig_and_compile_c) $(run_testcase) -%.multiproxy: SWIGOPT += -proxy -noclosuses -%.multiproxy: SCRIPTSUFFIX = $(PROXYSUFFIX) %.multiproxy: echo "$(ACTION)ing testcase $* (with run test) under chicken with -proxy" +$(swig_and_compile_multi_cpp) $(run_testcase) +# Runs the testcase. A testcase is only run if +# a file is found which has _runme.scm appended after the testcase name. +run_testcase = \ + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(CHICKEN_CSI) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi + # Clean %.clean: diff --git a/Examples/test-suite/clisp/Makefile.in b/Examples/test-suite/clisp/Makefile.in index 279ab97da..2ebaa6750 100644 --- a/Examples/test-suite/clisp/Makefile.in +++ b/Examples/test-suite/clisp/Makefile.in @@ -11,10 +11,14 @@ top_builddir = @top_builddir@ include $(srcdir)/../common.mk +# Overridden variables here # no C++ tests for now CPP_TEST_CASES = #C_TEST_CASES += +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: $(setup) @@ -34,9 +38,9 @@ CPP_TEST_CASES = # Runs the testcase. A testcase is only run if # a file is found which has _runme.lisp appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(CLISPBIN) -batch -s $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(CLISPBIN) -batch -s $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi # Clean: (does nothing, we dont generate extra clisp code) %.clean: diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 443cf2256..c69c152df 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -16,8 +16,8 @@ # b) Define rules for %.ctest, %.cpptest, %.multicpptest and %.clean. # c) Define srcdir, top_srcdir and top_builddir (these are the # equivalent to configure's variables of the same name). -# 3) One off special commandline options can be achieved by adding a -# test case to CUSTOM_TEST_CASES and defining rules to run and test. +# 3) One off special commandline options for a testcase can be added. +# See custom tests below. # # The 'check' target runs the testcases including SWIG invocation, # C/C++ compilation, target language compilation (if any) and runtime @@ -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 ####################################################################### @@ -71,27 +73,25 @@ INTERFACEDIR = ../ # Note that any whitespace after the last entry in each list will break make # -# Broken C++ test cases. (Can be run individually using make testcase.cpptest.) +# Broken C++ test cases. (Can be run individually using: make testcase.cpptest) CPP_TEST_BROKEN += \ constants \ cpp_broken \ exception_partial_info \ extend_variable \ li_std_vector_ptr \ - namespace_union \ - nested_struct \ overload_complicated \ template_default_pointer \ template_expr \ $(CPP0X_TEST_BROKEN) -# Broken C test cases. (Can be run individually using make testcase.ctest.) +# Broken C test cases. (Can be run individually using: make testcase.ctest) C_TEST_BROKEN += \ tag_no_clash_with_variable -# C++ test cases. (Can be run individually using make testcase.cpptest.) +# C++ test cases. (Can be run individually using: make testcase.cpptest) CPP_TEST_CASES += \ $(CPP0X_TEST_CASES) \ abstract_access \ @@ -119,6 +119,7 @@ CPP_TEST_CASES += \ arrays_scope \ bloody_hell \ bools \ + catches \ cast_operator \ casts \ char_strings \ @@ -190,6 +191,7 @@ CPP_TEST_CASES += \ extend_placement \ extend_template \ extend_template_ns \ + extern_c \ extern_namespace \ extern_throws \ features \ @@ -198,6 +200,7 @@ CPP_TEST_CASES += \ fvirtual \ global_namespace \ global_ns_arg \ + global_scope_types \ global_vars \ grouping \ ignore_parameter \ @@ -222,6 +225,7 @@ CPP_TEST_CASES += \ li_typemaps \ li_windows \ long_long_apply \ + memberin_extend \ member_pointer \ member_template \ minherit \ @@ -238,9 +242,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 +262,7 @@ CPP_TEST_CASES += \ overload_template \ overload_template_fast \ pointer_reference \ + preproc_constants \ primitive_ref \ private_assign \ protected_rename \ @@ -293,10 +301,13 @@ CPP_TEST_CASES += \ smart_pointer_templatevariables \ smart_pointer_typedef \ special_variables \ + special_variable_macros \ static_array_member \ static_const_member \ static_const_member_2 \ + struct_initialization_cpp \ struct_value \ + symbol_clash \ template \ template_arg_replace \ template_arg_scope \ @@ -326,6 +337,8 @@ CPP_TEST_CASES += \ template_inherit_abstract \ template_int_const \ template_methods \ + template_nested \ + template_nested_typemaps \ template_ns \ template_ns2 \ template_ns3 \ @@ -335,6 +348,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 \ @@ -370,9 +385,11 @@ CPP_TEST_CASES += \ typedef_scope \ typedef_sizet \ typedef_struct \ + typemap_global_scope \ typemap_namespace \ typemap_ns_using \ typemap_numinputs \ + typemap_template \ typemap_out_optimal \ typemap_variables \ typemap_various \ @@ -396,6 +413,7 @@ CPP_TEST_CASES += \ virtual_destructor \ virtual_poly \ voidtest \ + wallkw \ wrapmacro # C++0x test cases. @@ -437,8 +455,10 @@ CPP0X_TEST_BROKEN = CPP_STD_TEST_CASES += \ director_string \ ignore_template_constructor \ + li_std_combinations \ li_std_deque \ li_std_except \ + li_std_map \ li_std_pair \ li_std_string \ li_std_vector \ @@ -455,11 +475,12 @@ CPP_TEST_CASES += ${CPP_STD_TEST_CASES} endif -# C test cases. (Can be run individually using make testcase.ctest.) +# C test cases. (Can be run individually using: make testcase.ctest) C_TEST_CASES += \ arrays \ char_constant \ const_const \ + constant_expr \ empty \ enums \ extern_declaration \ @@ -477,24 +498,28 @@ 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 \ unions -# Multi-module C++ test cases . (Can be run individually using make testcase.multicpptest.) +# Multi-module C++ test cases . (Can be run individually using make testcase.multicpptest) MULTI_CPP_TEST_CASES += \ clientdata_prop \ imports \ @@ -503,10 +528,13 @@ MULTI_CPP_TEST_CASES += \ template_typedef_import \ multi_import +# Custom tests - tests with additional commandline options +wallkw.cpptest: SWIGOPT += -Wallkw + + NOT_BROKEN_TEST_CASES = $(CPP_TEST_CASES:=.cpptest) \ $(C_TEST_CASES:=.ctest) \ $(MULTI_CPP_TEST_CASES:=.multicpptest) \ - $(CUSTOM_TEST_CASES:=.customtest) \ $(EXTRA_TEST_CASES) BROKEN_TEST_CASES = $(CPP_TEST_BROKEN:=.cpptest) \ @@ -515,7 +543,6 @@ BROKEN_TEST_CASES = $(CPP_TEST_BROKEN:=.cpptest) \ ALL_CLEAN = $(CPP_TEST_CASES:=.clean) \ $(C_TEST_CASES:=.clean) \ $(MULTI_CPP_TEST_CASES:=.clean) \ - $(CUSTOM_TEST_CASES:=.clean) \ $(CPP_TEST_BROKEN:=.clean) \ $(C_TEST_BROKEN:=.clean) 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/constant_pointers.i b/Examples/test-suite/constant_pointers.i index 5bd2fd533..c2344fb6a 100644 --- a/Examples/test-suite/constant_pointers.i +++ b/Examples/test-suite/constant_pointers.i @@ -121,7 +121,8 @@ int* const globalRet2() {return &GlobalInt;} %{ static int wxEVT_COMMAND_BUTTON_CLICKEDv; -static int **wxEVT_COMMAND_BUTTON_CLICKEDp; +static int *wxEVT_COMMAND_BUTTON_CLICKEDp; +static int **wxEVT_COMMAND_BUTTON_CLICKEDpp = &wxEVT_COMMAND_BUTTON_CLICKEDp; #if defined(SWIGR) #undef lang1 /* conflicts with symbol in R internals */ #endif @@ -137,7 +138,7 @@ char *langs[] ={ lang1 }; #define EWXWEXPORT_VAR const int* wxEVENT_COMMAND_BUTTON_CLICKEDr = (int*) &wxEVT_COMMAND_BUTTON_CLICKEDv; - const int* wxEVENT_COMMAND_BUTTON_CLICKEDp = (int*) *wxEVT_COMMAND_BUTTON_CLICKEDp; + const int* wxEVENT_COMMAND_BUTTON_CLICKEDp = (int*) *wxEVT_COMMAND_BUTTON_CLICKEDpp; char **languages1 = &langs[0]; char **languages2 = (char **)&langs[0]; } diff --git a/Examples/test-suite/constructor_copy.i b/Examples/test-suite/constructor_copy.i index c74268a68..f6bdcb240 100644 --- a/Examples/test-suite/constructor_copy.i +++ b/Examples/test-suite/constructor_copy.i @@ -73,10 +73,6 @@ public: %include "std_vector.i" -#if defined(SWIGCSHARP) -SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(Flow, Space::Flow) -#endif - #if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGR) || defined(SWIGOCTAVE) || defined(SWIGRUBY) #define SWIG_GOOD_VECTOR %ignore std::vector::vector(size_type); 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< p in ismap) { if ((p.Key * 10.1) != p.Value.num) - throw new Exception("Iteration test on specialized map failed for index " + p.Key); + throw new Exception("Iteration test on complex type map failed for index " + p.Key); } } @@ -191,12 +191,12 @@ public class li_std_map_runme { } if (ispmap.Count != 10) - throw new Exception("Count test on specialized pointer map failed"); + throw new Exception("Count test on complex type pointer map failed"); foreach (KeyValuePair p in ispmap) { if ((p.Key * 10.1) != p.Value.num) - throw new Exception("Iteration test on specialized pointer map failed for index " + p.Key); + throw new Exception("Iteration test on complex type pointer map failed for index " + p.Key); } } { @@ -207,29 +207,29 @@ public class li_std_map_runme { } if (iscpmap.Count != 10) - throw new Exception("Count test on specialized const pointer map failed"); + throw new Exception("Count test on complex type const pointer map failed"); foreach (KeyValuePair p in iscpmap) { if ((p.Key * 10.1) != p.Value.num) - throw new Exception("Iteration test on specialized const pointer map failed for index " + p.Key); + throw new Exception("Iteration test on complex type const pointer map failed for index " + p.Key); } } - // Test non-specialized map + // Test complex type as key (Struct) { StructIntMap limap = new StructIntMap(); Struct s7 = new Struct(7); Struct s8 = new Struct(8); - limap.setitem(s7 , 8); - if (limap.getitem(s7) != 8) - throw new Exception("Assignment test on non-specialized map failed"); + limap[s7] = 8; + if (limap[s7] != 8) + throw new Exception("Assignment test on complex key map failed"); if (!limap.ContainsKey(s7)) - throw new Exception("Key test (1) on non-specialized map failed"); + throw new Exception("Key test (1) on complex key map failed"); if (limap.ContainsKey(s8)) - throw new Exception("Key test (2) on non-specialized map failed"); + throw new Exception("Key test (2) on complex key map failed"); } // All done diff --git a/Examples/test-suite/csharp/li_std_vector_runme.cs b/Examples/test-suite/csharp/li_std_vector_runme.cs index a2da91e15..617116d5a 100644 --- a/Examples/test-suite/csharp/li_std_vector_runme.cs +++ b/Examples/test-suite/csharp/li_std_vector_runme.cs @@ -158,7 +158,8 @@ public class li_std_vector_runme { } catch (ArgumentNullException) { } { - myDoubleVector = new DoubleVector() { 123.4, 567.8, 901.2 }; + // Collection initializer test, requires C# 3.0 +// myDoubleVector = new DoubleVector() { 123.4, 567.8, 901.2 }; } // IndexOf() test @@ -542,8 +543,8 @@ public class li_std_vector_runme { // Dispose() { - using (StructVector vs = new StructVector() { new Struct(0.0), new Struct(11.1) } ) - using (DoubleVector vd = new DoubleVector() { 0.0, 11.1 } ) { + using (StructVector vs = new StructVector( new Struct[] { new Struct(0.0), new Struct(11.1) } ) ) + using (DoubleVector vd = new DoubleVector( new double[] { 0.0, 11.1 } ) ) { } } diff --git a/Examples/test-suite/csharp/overload_template_runme.cs b/Examples/test-suite/csharp/overload_template_runme.cs index e4910161b..e25420169 100644 --- a/Examples/test-suite/csharp/overload_template_runme.cs +++ b/Examples/test-suite/csharp/overload_template_runme.cs @@ -7,8 +7,8 @@ public class runme { int f = overload_template.foo(); - f += overload_template.max(3,4); - double b = overload_template.max(3.4,5.2); + f += overload_template.maximum(3,4); + double b = overload_template.maximum(3.4,5.2); b++; // warning suppression // mix 1 diff --git a/Examples/test-suite/csharp/preproc_constants_c_runme.cs b/Examples/test-suite/csharp/preproc_constants_c_runme.cs new file mode 100644 index 000000000..76c684d85 --- /dev/null +++ b/Examples/test-suite/csharp/preproc_constants_c_runme.cs @@ -0,0 +1,70 @@ +using System; +using System.Reflection; +using preproc_constants_cNamespace; + +// Same as preproc_constants_c.i testcase, but bool types are int instead +public class runme { + static void Main() { + assert( typeof(int) == preproc_constants_c.CONST_INT1.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_INT2.GetType() ); + assert( typeof(uint) == preproc_constants_c.CONST_UINT1.GetType() ); + assert( typeof(uint) == preproc_constants_c.CONST_UINT2.GetType() ); + assert( typeof(uint) == preproc_constants_c.CONST_UINT3.GetType() ); + assert( typeof(uint) == preproc_constants_c.CONST_UINT4.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_LONG1.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_LONG2.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_LONG3.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_LONG4.GetType() ); + assert( typeof(long) == preproc_constants_c.CONST_LLONG1.GetType() ); + assert( typeof(long) == preproc_constants_c.CONST_LLONG2.GetType() ); + assert( typeof(long) == preproc_constants_c.CONST_LLONG3.GetType() ); + assert( typeof(long) == preproc_constants_c.CONST_LLONG4.GetType() ); + assert( typeof(ulong) == preproc_constants_c.CONST_ULLONG1.GetType() ); + assert( typeof(ulong) == preproc_constants_c.CONST_ULLONG2.GetType() ); + assert( typeof(ulong) == preproc_constants_c.CONST_ULLONG3.GetType() ); + assert( typeof(ulong) == preproc_constants_c.CONST_ULLONG4.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE1.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE2.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE3.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE4.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE5.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE6.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_BOOL1.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_BOOL2.GetType() ); + assert( typeof(char) == preproc_constants_c.CONST_CHAR.GetType() ); + assert( typeof(string) == preproc_constants_c.CONST_STRING1.GetType() ); + assert( typeof(string) == preproc_constants_c.CONST_STRING2.GetType() ); + + assert( typeof(int) == preproc_constants_c.INT_AND_BOOL.GetType() ); +// assert( typeof(int) == preproc_constants_c.INT_AND_CHAR.GetType() ); + assert( typeof(int) == preproc_constants_c.INT_AND_INT.GetType() ); + assert( typeof(uint) == preproc_constants_c.INT_AND_UINT.GetType() ); + assert( typeof(int) == preproc_constants_c.INT_AND_LONG.GetType() ); + assert( typeof(uint) == preproc_constants_c.INT_AND_ULONG.GetType() ); + assert( typeof(long) == preproc_constants_c.INT_AND_LLONG.GetType() ); + assert( typeof(ulong) == preproc_constants_c.INT_AND_ULLONG.GetType() ); + assert( typeof(int ) == preproc_constants_c.BOOL_AND_BOOL.GetType() ); + + assert( typeof(int) == preproc_constants_c.EXPR_MULTIPLY.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_DIVIDE.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_PLUS.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_MINUS.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_LSHIFT.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_RSHIFT.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_LTE.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_GTE.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_INEQUALITY.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_EQUALITY.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_AND.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_XOR.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_OR.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_LAND.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_LOR.GetType() ); + assert( typeof(double) == preproc_constants_c.EXPR_CONDITIONAL.GetType() ); + + } + static void assert(bool assertion) { + if (!assertion) + throw new ApplicationException("test failed"); + } +} diff --git a/Examples/test-suite/csharp/preproc_constants_runme.cs b/Examples/test-suite/csharp/preproc_constants_runme.cs new file mode 100644 index 000000000..9fae5914a --- /dev/null +++ b/Examples/test-suite/csharp/preproc_constants_runme.cs @@ -0,0 +1,69 @@ +using System; +using System.Reflection; +using preproc_constantsNamespace; + +public class runme { + static void Main() { + assert( typeof(int) == preproc_constants.CONST_INT1.GetType() ); + assert( typeof(int) == preproc_constants.CONST_INT2.GetType() ); + assert( typeof(uint) == preproc_constants.CONST_UINT1.GetType() ); + assert( typeof(uint) == preproc_constants.CONST_UINT2.GetType() ); + assert( typeof(uint) == preproc_constants.CONST_UINT3.GetType() ); + assert( typeof(uint) == preproc_constants.CONST_UINT4.GetType() ); + assert( typeof(int) == preproc_constants.CONST_LONG1.GetType() ); + assert( typeof(int) == preproc_constants.CONST_LONG2.GetType() ); + assert( typeof(int) == preproc_constants.CONST_LONG3.GetType() ); + assert( typeof(int) == preproc_constants.CONST_LONG4.GetType() ); + assert( typeof(long) == preproc_constants.CONST_LLONG1.GetType() ); + assert( typeof(long) == preproc_constants.CONST_LLONG2.GetType() ); + assert( typeof(long) == preproc_constants.CONST_LLONG3.GetType() ); + assert( typeof(long) == preproc_constants.CONST_LLONG4.GetType() ); + assert( typeof(ulong) == preproc_constants.CONST_ULLONG1.GetType() ); + assert( typeof(ulong) == preproc_constants.CONST_ULLONG2.GetType() ); + assert( typeof(ulong) == preproc_constants.CONST_ULLONG3.GetType() ); + assert( typeof(ulong) == preproc_constants.CONST_ULLONG4.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE1.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE2.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE3.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE4.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE5.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE6.GetType() ); + assert( typeof(bool) == preproc_constants.CONST_BOOL1.GetType() ); + assert( typeof(bool) == preproc_constants.CONST_BOOL2.GetType() ); + assert( typeof(char) == preproc_constants.CONST_CHAR.GetType() ); + assert( typeof(string) == preproc_constants.CONST_STRING1.GetType() ); + assert( typeof(string) == preproc_constants.CONST_STRING2.GetType() ); + + assert( typeof(int) == preproc_constants.INT_AND_BOOL.GetType() ); +// assert( typeof(int) == preproc_constants.INT_AND_CHAR.GetType() ); + assert( typeof(int) == preproc_constants.INT_AND_INT.GetType() ); + assert( typeof(uint) == preproc_constants.INT_AND_UINT.GetType() ); + assert( typeof(int) == preproc_constants.INT_AND_LONG.GetType() ); + assert( typeof(uint) == preproc_constants.INT_AND_ULONG.GetType() ); + assert( typeof(long) == preproc_constants.INT_AND_LLONG.GetType() ); + assert( typeof(ulong) == preproc_constants.INT_AND_ULLONG.GetType() ); + assert( typeof(int ) == preproc_constants.BOOL_AND_BOOL.GetType() ); + + assert( typeof(int) == preproc_constants.EXPR_MULTIPLY.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_DIVIDE.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_PLUS.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_MINUS.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_LSHIFT.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_RSHIFT.GetType() ); + assert( typeof(bool) == preproc_constants.EXPR_LTE.GetType() ); + assert( typeof(bool) == preproc_constants.EXPR_GTE.GetType() ); + assert( typeof(bool) == preproc_constants.EXPR_INEQUALITY.GetType() ); + assert( typeof(bool) == preproc_constants.EXPR_EQUALITY.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_AND.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_XOR.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_OR.GetType() ); + assert( typeof(bool) == preproc_constants.EXPR_LAND.GetType() ); + assert( typeof(bool) == preproc_constants.EXPR_LOR.GetType() ); + assert( typeof(double) == preproc_constants.EXPR_CONDITIONAL.GetType() ); + + } + static void assert(bool assertion) { + if (!assertion) + throw new ApplicationException("test failed"); + } +} diff --git a/Examples/test-suite/csharp/special_variable_macros_runme.cs b/Examples/test-suite/csharp/special_variable_macros_runme.cs new file mode 100644 index 000000000..bd6fd4b04 --- /dev/null +++ b/Examples/test-suite/csharp/special_variable_macros_runme.cs @@ -0,0 +1,22 @@ +using System; +using special_variable_macrosNamespace; + +public class runme { + static void Main() { + Name name = new Name(); + if (special_variable_macros.testFred(name) != "none") + throw new Exception("test failed"); + if (special_variable_macros.testJack(name) != "$specialname") + throw new Exception("test failed"); + if (special_variable_macros.testJill(name) != "jilly") + throw new Exception("test failed"); + if (special_variable_macros.testMary(name) != "SWIGTYPE_p_NameWrap") + throw new Exception("test failed"); + if (special_variable_macros.testJim(name) != "multiname num") + throw new Exception("test failed"); + if (special_variable_macros.testJohn(new PairIntBool(10, false)) != 123) + throw new Exception("test failed"); + NewName newName = NewName.factory("factoryname"); + name = newName.getStoredName(); + } +} diff --git a/Examples/test-suite/csharp_attributes.i b/Examples/test-suite/csharp_attributes.i index 101e89732..bca595d9a 100644 --- a/Examples/test-suite/csharp_attributes.i +++ b/Examples/test-suite/csharp_attributes.i @@ -1,4 +1,4 @@ -%module csharp_attributes +%module(directors="1") csharp_attributes // Test the inattributes and outattributes typemaps %typemap(cstype, outattributes="[IntOut]", inattributes="[IntIn]") int "int" @@ -15,6 +15,8 @@ public: int GlobalFunction(int myInt) { return myInt; } %} +//%include "enumsimple.swg" +//%include "enumtypesafe.swg" // Test the attributes feature %csattributes MoreStations::MoreStations() "[InterCity1]" @@ -25,6 +27,8 @@ int GlobalFunction(int myInt) { return myInt; } %csattributes Wales "[InterCity6]" %csattributes Paddington() "[InterCity7]" %csattributes DidcotParkway "[InterCity8]" +%csattributes MoreStations::Cardiff "[System.ComponentModel.Description(\"Cardiff city station\")]" +%csattributes Swansea "[System.ComponentModel.Description(\"Swansea city station\")]" %typemap(csattributes) MoreStations "[Eurostar1]" %typemap(csattributes) MoreStations::Wales "[Eurostar2]" @@ -46,3 +50,13 @@ enum Cymru { Llanelli }; double MoreStations::WestonSuperMare = 0.0; %} +// Test directorinattributes and directoroutattributes +%typemap(imtype, directoroutattributes="[DirectorIntegerOut]", directorinattributes="[DirectorIntegerIn]") int "int" +%feature("director") YetMoreStations; + +%inline %{ +struct YetMoreStations { + virtual int Slough(int x) {} + virtual ~YetMoreStations() {} +}; +%} diff --git a/Examples/test-suite/csharp_prepost.i b/Examples/test-suite/csharp_prepost.i index 0c35c1833..817f5b9b9 100644 --- a/Examples/test-suite/csharp_prepost.i +++ b/Examples/test-suite/csharp_prepost.i @@ -25,7 +25,10 @@ "$csclassname.getCPtr(d$csinput)" // post only in csin typemap -%typemap(csin, post=" int size = $csinput.Count;\n for (int i=0; i &vpost +%typemap(csin, post=" int size = $csinput.Count;\n" + " for (int i=0; i &vpost "$csclassname.getCPtr($csinput)" %inline %{ diff --git a/Examples/test-suite/default_args.i b/Examples/test-suite/default_args.i index 69c90e2e6..839d28e3e 100644 --- a/Examples/test-suite/default_args.i +++ b/Examples/test-suite/default_args.i @@ -119,6 +119,7 @@ // tests valuewrapper +%feature("compactdefaultargs") MyClass2::set; %inline %{ enum MyType { Val1, Val2 }; @@ -134,6 +135,7 @@ void set(MyClass1 cl1 = Val1) {} // This could have been written : set(MyClass1 cl1 = MyClass1(Val1)) // But it works in C++ since there is a "conversion" constructor in MyClass1. + void set2(MyClass1 cl1 = Val1) {} }; %} diff --git a/Examples/test-suite/derived_nested.i b/Examples/test-suite/derived_nested.i index 2e9ace304..29114d5a0 100644 --- a/Examples/test-suite/derived_nested.i +++ b/Examples/test-suite/derived_nested.i @@ -3,6 +3,11 @@ This was reported in bug #909389 */ %module derived_nested +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) BB::CC; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) BB::DD; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) BB::EE; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) BB::FF; + %inline %{ class A { int x; }; @@ -11,5 +16,12 @@ class B { class D : public A { int z; }; //ok }; +struct BB { + class CC { int y; }; + class DD : public A { int z; }; + struct EE : public A { int z; }; + struct FF : public A { int z; } ff_instance; // Bug 1960977 + void useEE(const EE& e) {} +}; %} diff --git a/Examples/test-suite/director_detect.i b/Examples/test-suite/director_detect.i index 355e5ee91..fcb01b3e9 100644 --- a/Examples/test-suite/director_detect.i +++ b/Examples/test-suite/director_detect.i @@ -15,7 +15,9 @@ %feature("director") Foo; %newobject Foo::cloner(); +%newobject Foo::get_class(); %newobject Bar::cloner(); +%newobject Bar::get_class(); %inline { diff --git a/Examples/test-suite/director_protected.i b/Examples/test-suite/director_protected.i index df3418506..fee45b4a6 100644 --- a/Examples/test-suite/director_protected.i +++ b/Examples/test-suite/director_protected.i @@ -11,6 +11,13 @@ %newobject *::create(); +#ifdef SWIGPHP +// TODO: Currently we do not track the dynamic type of returned objects +// in PHP, so we need the factory helper. +%include factory.i +%factory(Foo *Bar::create, Bar); +#endif + %rename(a) Bar::hello; %rename(s) Foo::p; %rename(q) Foo::r; diff --git a/Examples/test-suite/director_stl.i b/Examples/test-suite/director_stl.i index cbcb4ba85..46946e513 100644 --- a/Examples/test-suite/director_stl.i +++ b/Examples/test-suite/director_stl.i @@ -17,7 +17,11 @@ %feature("director") Foo; %feature("director:except") { +#ifndef SWIGPHP if ($error != NULL) { +#else + if ($error == FAILURE) { +#endif throw Swig::DirectorMethodException(); } } diff --git a/Examples/test-suite/director_using.i b/Examples/test-suite/director_using.i index 104528ca4..9001ffbb9 100644 --- a/Examples/test-suite/director_using.i +++ b/Examples/test-suite/director_using.i @@ -1,5 +1,7 @@ %module(directors="1",dirprot="1") director_using +%warnfilter(SWIGWARN_PHP_PUBLIC_BASE) FooBar; + %{ #include #include diff --git a/Examples/test-suite/enum_thorough.i b/Examples/test-suite/enum_thorough.i index 31e3e2105..974227a01 100644 --- a/Examples/test-suite/enum_thorough.i +++ b/Examples/test-suite/enum_thorough.i @@ -487,11 +487,53 @@ struct Instances { // Repeated values #if defined(SWIGJAVA) %javaconst(1); +// needed for typesafe and proper enums only +%javaconst(0) ignoreA_three; +%javaconst(0) ignoreA_thirteen; #elif defined(SWIGCSHARP) +// needed for typesafe enums only +#ifdef SWIG_TEST_NOCSCONST + %csconst(0) ignoreA_three; + %csconst(0) ignoreA_thirteen; +#endif %csconst(1); #endif -#if defined(SWIGPERL) +%ignore ignoreA_one; +%ignore ignoreA_two; +%ignore ignoreA_twelve; +%ignore ignoreA_thirty_one; + +%ignore ignoreB_ten; +%ignore ignoreB_twenty; +%ignore ignoreB_thirty; +%ignore ignoreB_forty; + +%ignore ignoreC_eleven; +%ignore ignoreC_thirty_one; +%ignore ignoreC_forty_one; + +%ignore ignoreD_ten; +%ignore ignoreD_twenty; + +%ignore ignoreE_twenty; + +%inline %{ +struct IgnoreTest { + enum IgnoreA { ignoreA_zero, ignoreA_one, ignoreA_two, ignoreA_three, ignoreA_ten=10, ignoreA_eleven, ignoreA_twelve, ignoreA_thirteen, ignoreA_fourteen, ignoreA_twenty=20, ignoreA_thirty=30, ignoreA_thirty_one, ignoreA_thirty_two, ignoreA_thirty_three }; + enum IgnoreB { ignoreB_ten=10, ignoreB_eleven, ignoreB_twelve, ignoreB_twenty=20, ignoreB_thirty=30, ignoreB_thirty_one, ignoreB_thirty_two, ignoreB_forty=40, ignoreB_forty_one, ignoreB_forty_two }; + enum IgnoreC { ignoreC_ten=10, ignoreC_eleven, ignoreC_twelve, ignoreC_twenty=20, ignoreC_thirty=30, ignoreC_thirty_one, ignoreC_thirty_two, ignoreC_forty=40, ignoreC_forty_one, ignoreC_forty_two }; + enum IgnoreD { ignoreD_ten=10, ignoreD_twenty=20, ignoreD_twenty_one, ignoreD_twenty_two }; + enum IgnoreE { ignoreE_zero, ignoreE_twenty=20, ignoreE_twenty_one, ignoreE_twenty_two }; +}; + +IgnoreTest::IgnoreA ignoreATest(IgnoreTest::IgnoreA n) { return n; } +IgnoreTest::IgnoreB ignoreBTest(IgnoreTest::IgnoreB n) { return n; } +IgnoreTest::IgnoreC ignoreCTest(IgnoreTest::IgnoreC n) { return n; } +IgnoreTest::IgnoreD ignoreDTest(IgnoreTest::IgnoreD n) { return n; } +IgnoreTest::IgnoreE ignoreETest(IgnoreTest::IgnoreE n) { return n; } +%} + %inline %{ namespace RepeatSpace { @@ -509,24 +551,3 @@ repeat repeatTest(repeat e) { return e; } %} -#else -%inline %{ - -namespace RepeatSpace { -typedef enum -{ - one = 1, - initial = one, - two, - three, - last = three, - end = last -} repeat; -repeat repeatTest(repeat e) { return e; } -} - -%} - - -#endif - diff --git a/Examples/test-suite/enum_thorough_typesafe.i b/Examples/test-suite/enum_thorough_typesafe.i index 8bae5b07a..e205e8ad1 100644 --- a/Examples/test-suite/enum_thorough_typesafe.i +++ b/Examples/test-suite/enum_thorough_typesafe.i @@ -3,5 +3,7 @@ // Test enum wrapping using the typesafe enum pattern in the target language %include "enumtypesafe.swg" +#define SWIG_TEST_NOCSCONST // For C# typesafe enums + %include "enum_thorough.i" diff --git a/Examples/test-suite/enums.i b/Examples/test-suite/enums.i index 3ea48b90e..40be28e94 100644 --- a/Examples/test-suite/enums.i +++ b/Examples/test-suite/enums.i @@ -8,6 +8,7 @@ %warnfilter(SWIGWARN_RUBY_WRONG_NAME) globalinstance1; %warnfilter(SWIGWARN_RUBY_WRONG_NAME) globalinstance2; %warnfilter(SWIGWARN_RUBY_WRONG_NAME) globalinstance3; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK); %inline %{ @@ -32,8 +33,14 @@ bar3(foo3 x) {} enum sad { boo, hoo = 5 }; +#ifdef __cplusplus /* For Octave and g++ which compiles C test code as C++ */ +extern "C" { +#endif /* Unnamed enum instance */ enum { globalinstance1, globalinstance2, globalinstance3 = 30 } GlobalInstance; +#ifdef __cplusplus +} +#endif /* Anonymous enum */ enum { AnonEnum1, AnonEnum2 = 100 }; @@ -58,7 +65,7 @@ typedef struct _iFoo enum { Phoo = +50, Char = 'a' - } e; + } e; } iFoo; %} #else @@ -71,5 +78,20 @@ struct iFoo }; }; %} - #endif + +// enum declaration and initialization +%inline %{ +enum Exclamation { + goodness, + gracious, + me +} enumInstance = me; + +enum ContainYourself { + slap = 10, + my, + thigh +} Slap = slap, My = my, Thigh = thigh, *pThigh = &Thigh, arrayContainYourself[3] = {slap, my, thigh}; +%} + diff --git a/Examples/test-suite/extern_c.i b/Examples/test-suite/extern_c.i new file mode 100644 index 000000000..9c17d18fb --- /dev/null +++ b/Examples/test-suite/extern_c.i @@ -0,0 +1,16 @@ +%module extern_c + +%inline %{ +extern "C" { +void RealFunction(int value); +typedef void Function1(int value); // Fails +typedef int Integer1; +} +typedef void Function2(int value); // Works +typedef int Integer2; +%} + +%{ +void RealFunction(int value) {} +%} + diff --git a/Examples/test-suite/global_namespace.i b/Examples/test-suite/global_namespace.i index 02139f6c4..31dbb9e59 100644 --- a/Examples/test-suite/global_namespace.i +++ b/Examples/test-suite/global_namespace.i @@ -11,8 +11,8 @@ class Klass6 {}; class Klass7 {}; struct KlassMethods { - static void methodA(::Klass1 v, const ::Klass2 cv, const ::Klass3 *cp, ::Klass4 *p, const ::Klass5 &cr, ::Klass6 &r, Klass7*& pr) {} - static void methodB( Klass1 v, const Klass2 cv, const Klass3 *cp, Klass4 *p, const Klass5 &cr, Klass6 &r, Klass7*& pr) {} + static void methodA(::Klass1 v, const ::Klass2 cv, const ::Klass3 *cp, ::Klass4 *p, const ::Klass5 &cr, ::Klass6 &r, ::Klass7*& pr) {} + static void methodB( Klass1 v, const Klass2 cv, const Klass3 *cp, Klass4 *p, const Klass5 &cr, Klass6 &r, Klass7*& pr) {} }; %} @@ -28,8 +28,8 @@ class XYZ7 {}; } struct XYZMethods { - static void methodA(::Space::XYZ1 v, const ::Space::XYZ2 cv, const ::Space::XYZ3 *cp, ::Space::XYZ4 *p, const ::Space::XYZ5 &cr, ::Space::XYZ6 &r, Space::XYZ7*& pr) {} - static void methodB( Space::XYZ1 v, const Space::XYZ2 cv, const Space::XYZ3 *cp, Space::XYZ4 *p, const Space::XYZ5 &cr, Space::XYZ6 &r, Space::XYZ7*& pr) {} + static void methodA(::Space::XYZ1 v, const ::Space::XYZ2 cv, const ::Space::XYZ3 *cp, ::Space::XYZ4 *p, const ::Space::XYZ5 &cr, ::Space::XYZ6 &r, ::Space::XYZ7*& pr) {} + static void methodB( Space::XYZ1 v, const Space::XYZ2 cv, const Space::XYZ3 *cp, Space::XYZ4 *p, const Space::XYZ5 &cr, Space::XYZ6 &r, Space::XYZ7*& pr) {} }; %} diff --git a/Examples/test-suite/global_scope_types.i b/Examples/test-suite/global_scope_types.i new file mode 100644 index 000000000..4c73dfa72 --- /dev/null +++ b/Examples/test-suite/global_scope_types.i @@ -0,0 +1,44 @@ +%module global_scope_types + +// no constructor/destructor wrappers as they do not use global scope operator which we are trying to test here +%nodefaultctor Dingaling; +%nodefaultdtor Dingaling; + +%inline %{ +struct Dingaling {}; +typedef Dingaling DINGALING; +template struct MyTemplate { + T tt(T t) { return t; } + T& ttr(T& t) { return t; } +}; + +#ifndef SWIG +// This is added so that the code will not compile, if the global scope operator on Dingaling is omitted in the generated code +namespace Spac { + class Dingaling { + Dingaling(); + Dingaling(const Dingaling& t); + Dingaling& operator=(const Dingaling t); + }; +} +using namespace Spac; +#endif + +namespace Spac { + + struct Ting {}; + typedef Ting TING; + + class Test { + public: + void something(::Dingaling t, ::Dingaling* pt, ::Dingaling& rt, const ::Dingaling& crt) {} + void tsomething(MyTemplate< ::Dingaling > t1, MyTemplate< const ::Dingaling* > t2) {} +// void usomething(::MyTemplate< ::DINGALING > t3, ::MyTemplate< ::DINGALING *> t4) {} // needs fixing + void nothing(::Spac::Ting*, ::Spac::TING&) {} + }; + +} + +void funcptrtest( void (*)(::Dingaling) ) {} +%} + diff --git a/Examples/test-suite/guile/Makefile.in b/Examples/test-suite/guile/Makefile.in index 25d40674d..c6be92c32 100644 --- a/Examples/test-suite/guile/Makefile.in +++ b/Examples/test-suite/guile/Makefile.in @@ -9,14 +9,22 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ GUILE = @GUILE@ +GUILE_RUNTIME=-runtime + +C_TEST_CASES = long_long \ + list_vector \ + multivalue \ + pointer_in_out -C_TEST_CASES = long_long list_vector pointer_in_out multivalue include $(srcdir)/../common.mk # Overridden variables here # none! +# Custom tests - tests with additional commandline options +%.multicpptest: SWIGOPT += $(GUILE_RUNTIME) + # Rules for the different types of tests %.cpptest: $(setup) @@ -28,19 +36,6 @@ include $(srcdir)/../common.mk +$(swig_and_compile_c) $(run_testcase) -# override the default in common.mk by adding SWIGOPT += -swig_and_compile_multi_cpp = \ - for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ - SWIGOPT=" -runtime "; \ - export SWIGOPT; \ - $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile CXXSRCS="$(CXXSRCS)" \ - SWIG_LIB="$(SWIG_LIB)" SWIG="$(SWIG)" LIBS='$(LIBS)' \ - INCLUDES="$(INCLUDES)" SWIGOPT="$(SWIGOPT) $$SWIGOPT" NOLINK=true \ - TARGET="$(TARGETPREFIX)$${f}$(TARGETSUFFIX)" INTERFACEDIR="$(INTERFACEDIR)" INTERFACE="$$f.i" \ - $(LANGUAGE)$(VARIANT)_cpp; \ - SWIGOPT=" -noruntime "; \ - done - %.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) @@ -49,9 +44,9 @@ swig_and_compile_multi_cpp = \ # Runs the testcase. A testcase is only run if # a file is found which has _runme.scm appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(GUILE) -l $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(GUILE) -l $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi # Clean %.clean: diff --git a/Examples/test-suite/guilescm/Makefile.in b/Examples/test-suite/guilescm/Makefile.in index eb53f020e..ba1cba440 100644 --- a/Examples/test-suite/guilescm/Makefile.in +++ b/Examples/test-suite/guilescm/Makefile.in @@ -6,34 +6,29 @@ EXTRA_TEST_CASES += guilescm_ext_test.externaltest include ../guile/Makefile +# Overridden variables here INCLUDES += -I$(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/guilescm - VARIANT = # Refer to the guile directory for the run scripts SCRIPTPREFIX = ../guile/ +GUILE_RUNTIME= + +# Custom tests - tests with additional commandline options +# none! # Runs the testcase. A testcase is only run if # a file is found which has _runme.scm appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(GUILE) -l $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(GUILE) -l $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi setup = \ if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ echo "$(ACTION)ing testcase $* (with run test) under $(LANGUAGE) (with SCM API)" ; \ else \ echo "$(ACTION)ing testcase $* under $(LANGUAGE) (with SCM API)" ; \ - fi; - -swig_and_compile_multi_cpp = \ - for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ - $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile CXXSRCS="$(CXXSRCS)" \ - SWIG_LIB="$(SWIG_LIB)" SWIG="$(SWIG)" LIBS='$(LIBS)' \ - INCLUDES="$(INCLUDES)" SWIGOPT="$(SWIGOPT) $$SWIGOPT" NOLINK=true \ - TARGET="$(TARGETPREFIX)$${f}$(TARGETSUFFIX)" INTERFACEDIR="$(INTERFACEDIR)" INTERFACE="$$f.i" \ - $(LANGUAGE)$(VARIANT)_cpp; \ - done + fi %.externaltest: $(local_setup) @@ -46,9 +41,9 @@ local_setup = \ echo "$(ACTION)ing testcase $* (with run test) under $(LANGUAGE) (with SCM API)" ; \ else \ echo "$(ACTION)ing testcase $* under $(LANGUAGE) (with SCM API)" ; \ - fi; + fi local_run_testcase = \ - if [ -f $(srcdir)/$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(GUILE) -l $(srcdir)/$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(GUILE) -l $(srcdir)/$*$(SCRIPTSUFFIX); \ + fi diff --git a/Examples/test-suite/java/Makefile.in b/Examples/test-suite/java/Makefile.in index 03c10d498..5c96ca154 100644 --- a/Examples/test-suite/java/Makefile.in +++ b/Examples/test-suite/java/Makefile.in @@ -40,6 +40,9 @@ include $(srcdir)/../common.mk SWIGOPT += -package $* INTERFACEDIR = ../../ +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: $(setup) @@ -64,24 +67,24 @@ setup = \ echo "$(ACTION)ing testcase $* under $(LANGUAGE)" ; \ fi; \ if [ ! -d $* ]; then \ - mkdir $*; \ - fi; + mkdir $*; \ + fi # Compiles java files then runs the testcase. A testcase is only run if # a file is found which has _runme.java appended after the testcase name. # Note Java uses LD_LIBRARY_PATH under Unix, PATH under Cygwin/Windows, SHLIB_PATH on HPUX and DYLD_LIBRARY_PATH on Mac OS X. run_testcase = \ - (cd $* && $(COMPILETOOL) $(JAVAC) -classpath . *.java) && \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - $(COMPILETOOL) $(JAVAC) -classpath . -d . $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ - env LD_LIBRARY_PATH="$*:$$LD_LIBRARY_PATH" PATH="$*:$$PATH" SHLIB_PATH="$*:$$SHLIB_PATH" DYLD_LIBRARY_PATH="$*:$$DYLD_LIBRARY_PATH" $(RUNTOOL) $(JAVA) -classpath . $*_runme;) \ - fi; + cd $* && $(COMPILETOOL) $(JAVAC) -classpath . *.java && cd .. && \ + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + $(COMPILETOOL) $(JAVAC) -classpath . -d . $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ + env LD_LIBRARY_PATH="$*:$$LD_LIBRARY_PATH" PATH="$*:$$PATH" SHLIB_PATH="$*:$$SHLIB_PATH" DYLD_LIBRARY_PATH="$*:$$DYLD_LIBRARY_PATH" $(RUNTOOL) $(JAVA) -classpath . $*_runme; \ + fi # Clean: remove testcase directories %.clean: @if [ -d $* ]; then \ - rm -rf $*; \ - fi; + rm -rf $*; \ + fi clean: @rm -f *.class hs_err*.log diff --git a/Examples/test-suite/java/char_strings_runme.java b/Examples/test-suite/java/char_strings_runme.java index 2c71d3ea7..4f3331596 100644 --- a/Examples/test-suite/java/char_strings_runme.java +++ b/Examples/test-suite/java/char_strings_runme.java @@ -127,15 +127,26 @@ public class char_strings_runme { // char *& tests for (i=0; i +%include +%include + +%template(VectorInt) std::vector; +%template(VectorString) std::vector; +%template(PairIntString) std::pair; + +%template(VectorPairIntString) std::vector< std::pair >; +%template(PairIntVectorString) std::pair< int, std::vector >; + +%template(VectorVectorString) std::vector< std::vector >; +%template(PairIntPairIntString) std::pair< int, std::pair >; diff --git a/Examples/test-suite/li_std_map.i b/Examples/test-suite/li_std_map.i index 356e86df3..d5929d786 100644 --- a/Examples/test-suite/li_std_map.i +++ b/Examples/test-suite/li_std_map.i @@ -46,18 +46,6 @@ struct Struct { %} -#if defined(SWIGCSHARP) - -// Specialize some more non-default map types -SWIG_STD_MAP_SPECIALIZED(int, int *, int, SWIGTYPE_p_int) -SWIG_STD_MAP_SPECIALIZED(int, const int *, int, SWIGTYPE_p_int) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(int, Struct) -SWIG_STD_MAP_SPECIALIZED(int, Struct *, int, Struct) -SWIG_STD_MAP_SPECIALIZED(int, const Struct *, int, Struct) -SWIG_STD_MAP_SPECIALIZED(Struct *, int, Struct, int) - -#endif - //#if !defined(SWIGR) // Test out some maps with pointer types diff --git a/Examples/test-suite/li_std_vector.i b/Examples/test-suite/li_std_vector.i index c6e2ea9ad..74b3f6e6f 100644 --- a/Examples/test-suite/li_std_vector.i +++ b/Examples/test-suite/li_std_vector.i @@ -75,12 +75,7 @@ const std::vector & vecstructconstptr(const std::vector; %template(StructureConstPtrVector) std::vector; #endif @@ -93,10 +88,6 @@ SWIG_STD_VECTOR_SPECIALIZE(SWIGTYPE_p_int, const int *) %template(StructPtrVector) std::vector; %template(StructConstPtrVector) std::vector; -#if defined(SWIGCSHARP) -SWIG_STD_VECTOR_SPECIALIZE(MyClass, MyClass *) -#endif - #if !defined(SWIGTCL) %inline { struct MyClass {}; diff --git a/Examples/test-suite/li_std_vector_extra.i b/Examples/test-suite/li_std_vector_extra.i index 9c2497f7c..114de3f11 100644 --- a/Examples/test-suite/li_std_vector_extra.i +++ b/Examples/test-suite/li_std_vector_extra.i @@ -125,15 +125,16 @@ std::vector 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/Makefile.in b/Examples/test-suite/lua/Makefile.in index b370ae163..0ddc86a7d 100644 --- a/Examples/test-suite/lua/Makefile.in +++ b/Examples/test-suite/lua/Makefile.in @@ -24,6 +24,9 @@ include $(srcdir)/../common.mk # Overridden variables here LIBS = -L. +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: $(setup) @@ -43,9 +46,9 @@ LIBS = -L. # Runs the testcase. A testcase is only run if # a file is found which has _runme.lua appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(LUA) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(LUA) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi # Clean: (does nothing, we dont generate extra lua code) %.clean: 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/lua/overload_template_runme.lua b/Examples/test-suite/lua/overload_template_runme.lua index c62a42c02..19cc7e9dd 100644 --- a/Examples/test-suite/lua/overload_template_runme.lua +++ b/Examples/test-suite/lua/overload_template_runme.lua @@ -2,12 +2,12 @@ require("import") -- the import fn import("overload_template") -- import code for k,v in pairs(overload_template) 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 new file mode 100644 index 000000000..c6eb10526 --- /dev/null +++ b/Examples/test-suite/memberin_extend.i @@ -0,0 +1,33 @@ +%module memberin_extend + +// Tests memberin typemap is not used for %extend. +// The test extends the struct with a pseudo member variable + +%inline %{ +#include +struct ExtendMe { +}; +%} + +%{ +#include +std::map ExtendMeStringMap; +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 { + char *thing; +} + 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/mzscheme/Makefile.in b/Examples/test-suite/mzscheme/Makefile.in index 753b01ff6..fcaf33a48 100644 --- a/Examples/test-suite/mzscheme/Makefile.in +++ b/Examples/test-suite/mzscheme/Makefile.in @@ -14,6 +14,9 @@ include $(srcdir)/../common.mk # Overridden variables here # none! +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: $(setup) @@ -33,9 +36,9 @@ include $(srcdir)/../common.mk # Runs the testcase. A testcase is only run if # a file is found which has _runme.scm appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(MZSCHEME) -r $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(MZSCHEME) -r $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi # Clean %.clean: diff --git a/Examples/test-suite/name_warnings.i b/Examples/test-suite/name_warnings.i index 527dbcfaa..4032f20e1 100644 --- a/Examples/test-suite/name_warnings.i +++ b/Examples/test-suite/name_warnings.i @@ -35,7 +35,9 @@ namespace std { typedef complex None; +#ifndef SWIGPHP // clone() *is* an invalid method name in PHP. A* clone(int) { return NULL; } +#endif virtual ~A() {} virtual int func() = 0; 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 ea365a6fe..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 @@ -27,7 +29,7 @@ struct a struct { /*struct*/ struct { - int b; + int b; /**< v1/v2 B-tree & local/fractal heap for groups, B-tree for chunked datasets */ } c; } d; }; 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/ocaml/Makefile.in b/Examples/test-suite/ocaml/Makefile.in index 0e6235f94..f16c3da95 100644 --- a/Examples/test-suite/ocaml/Makefile.in +++ b/Examples/test-suite/ocaml/Makefile.in @@ -14,13 +14,13 @@ C_TEST_CASES = run_testcase = \ if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) -a \ - -f $(top_srcdir)/Examples/test-suite/$*.list ] ; then ( \ + -f $(top_srcdir)/Examples/test-suite/$*.list ] ; then \ $(COMPILETOOL) $(OCAMLC) -c $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ - $(COMPILETOOL) $(OCAMLC) swig.cmo -custom -g -cc '$(CXX)' -o runme `cat $(top_srcdir)/Examples/test-suite/$(*).list | sed -e 's/\(.*\)/\1_wrap.o \1.cmo/g'`&& $(RUNTOOL) ./runme) ; \ - elif [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ + $(COMPILETOOL) $(OCAMLC) swig.cmo -custom -g -cc '$(CXX)' -o runme `cat $(top_srcdir)/Examples/test-suite/$(*).list | sed -e 's/\(.*\)/\1_wrap.o \1.cmo/g'`&& $(RUNTOOL) ./runme; \ + elif [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ $(COMPILETOOL) $(OCAMLC) -c $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ $(COMPILETOOL) $(OCAMLC) swig.cmo -custom -g -cc '$(CXX)' -o runme $(srcdir)/$(*).cmo $(srcdir)/$(*)_runme.cmo $(srcdir)/$(*)_wrap.o && \ - $(RUNTOOL) ./runme) ; \ + $(RUNTOOL) ./runme; \ fi ; check_quant: @@ -44,6 +44,9 @@ include $(srcdir)/../common.mk # Overridden variables here # none! +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: echo $@ >> testing diff --git a/Examples/test-suite/octave/Makefile.in b/Examples/test-suite/octave/Makefile.in index b12cf500a..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 @@ -34,6 +33,9 @@ include $(srcdir)/../common.mk # Overridden variables here LIBS = -L. +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: $(setup) @@ -53,9 +55,9 @@ LIBS = -L. # Runs the testcase. A testcase is only run if # a file is found which has _runme.m appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH OCTAVEPATH=$(srcdir):OCTAVEPATH $(RUNTOOL) $(OCTAVE) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH OCTAVEPATH=$(srcdir):OCTAVEPATH $(RUNTOOL) $(OCTAVE) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi # Clean: remove the generated .m file %.clean: diff --git a/Examples/test-suite/octave/director_exception_runme.m b/Examples/test-suite/octave/director_exception_runme.m deleted file mode 100644 index 3e0b23064..000000000 --- a/Examples/test-suite/octave/director_exception_runme.m +++ /dev/null @@ -1,57 +0,0 @@ -director_exception - -MyFoo=@() subclass(Foo(), - 'ping',@(self) raise(NotImplementedError("MyFoo::ping() EXCEPTION"))); - -MyFoo2=@() subclass(Foo(), - 'ping',@(self) true); - -ok = 0; - -a = MyFoo(); -b = launder(a); - -try - b.pong(); -catch - [etype,e]=raised(); - if (etype=="NotImplementedError") - ok=1; - endif -end_try_catch - -if (!ok) - error -endif - -ok = 0; - -a = MyFoo2(); -b = launder(a); - -try - b.pong(); -catch - ok = 1; -end_try_catch - -if (!ok) - error -endif - - -try - raise(Exception2()); -catch - if (!strcmp(raised,"Exception2")) - rethrow(lasterr); - endif -end_try_catch - -try - raise(Exception1()); -catch - if (!strcmp(raised,"Exception1")) - rethrow(lasterr); - endif -end_try_catch diff --git a/Examples/test-suite/octave/director_finalizer_runme.m b/Examples/test-suite/octave/director_finalizer_runme.m deleted file mode 100644 index 3781a0f77..000000000 --- a/Examples/test-suite/octave/director_finalizer_runme.m +++ /dev/null @@ -1,56 +0,0 @@ -director_finalizer - -MyFoo=@() subclass(Foo(),'__del__',@delete_MyFoo); -function delete_MyFoo(self) - self.orStatus(2); - try - Foo.__del__(self); - catch - end_try_catch -endfunction - -resetStatus(); - -a = MyFoo(); -clear a; - -if (getStatus() != 3) - error -endif - -resetStatus(); - -a = MyFoo(); -launder(a); - -if (getStatus() != 0) - error -endif - -clear a; - -if (getStatus() != 3) - error -endif - -resetStatus(); - -a = MyFoo().__disown__(); -deleteFoo(a); - -if (getStatus() != 3) - error -endif - -resetStatus(); - -a = MyFoo().__disown__(); -deleteFoo(launder(a)); - -if (getStatus() != 3) - error -endif - -resetStatus(); - - diff --git a/Examples/test-suite/octave/empty_runme.m b/Examples/test-suite/octave/empty_runme.m index c6cac6926..e7b64f1cd 100644 --- a/Examples/test-suite/octave/empty_runme.m +++ b/Examples/test-suite/octave/empty_runme.m @@ -1 +1,2 @@ empty + 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/exception_order_runme.m b/Examples/test-suite/octave/exception_order_runme.m index a5914f822..3fb2b9a50 100644 --- a/Examples/test-suite/octave/exception_order_runme.m +++ b/Examples/test-suite/octave/exception_order_runme.m @@ -6,40 +6,39 @@ a = A(); try a.foo() catch - if (!strcmp(raised(),"E1")) - error, "bad exception order" + if (!strcmp(lasterror.message, "error: C++ side threw an exception of type E1\n")) + error("bad exception order") endif end_try_catch try a.bar() catch - if (!strcmp(raised(),"E2")) - error, "bad exception order" + if (!strcmp(lasterror.message, "error: C++ side threw an exception of type E2\n")) + error("bad exception order") endif end_try_catch try a.foobar() catch - [t,e]=raised(); - if (!strcmp(e.args(0),"postcatch unknown")) - error + if (!strcmp(lasterror.message, "error: postcatch unknown (SWIG_RuntimeError)\n")) + error("bad exception order") endif end_try_catch try a.barfoo(1) catch - if (!strcmp(raised(),"E1")) - error, "bad exception order" + if (!strcmp(lasterror.message, "error: C++ side threw an exception of type E1\n")) + error("bad exception order") endif end_try_catch try a.barfoo(2) catch - if (!strcmp(raised(),"E2")) - error, "bad exception order" + if (!strcmp(lasterror.message, "error: C++ side threw an exception of type E2 *\n")) + error("bad exception order") endif end_try_catch diff --git a/Examples/test-suite/octave/imports_runme.m b/Examples/test-suite/octave/imports_runme.m index 3964552ab..be9db5919 100644 --- a/Examples/test-suite/octave/imports_runme.m +++ b/Examples/test-suite/octave/imports_runme.m @@ -1,7 +1,7 @@ # This is the import runtime testcase. -imports_b -imports_a +imports_b; +imports_a; x = imports_b.B(); x.hello(); diff --git a/Examples/test-suite/octave/li_std_vector_runme.m b/Examples/test-suite/octave/li_std_vector_runme.m index b9f33ee02..83d1f2cb0 100644 --- a/Examples/test-suite/octave/li_std_vector_runme.m +++ b/Examples/test-suite/octave/li_std_vector_runme.m @@ -1,160 +1,11 @@ li_std_vector iv = IntVector(4); -for i=0:4, +for i=0:3, iv(i) = i; endfor - x = average(iv); -y = average([1,2,3,4]); -a = half([10,10.5,11,11.5]); - -dv = DoubleVector(10); -for i=0:10, - dv(i) = i/2.0; -endfor - -halve_in_place(dv); - - -bv = BoolVector(4); -bv(0)= 1; -bv(1)= 0; -bv(2)= 4; -bv(3)= 0; - -if (bv(0) != bv(2)) - error("bad std::vector mapping") +if (x != 1.5) + error("average failed"); endif - -b = B(5); -va = VecA([b,None,b,b]); - -if (va(0).f(1) != 6) - error("bad std::vector mapping") -endif - -if (vecAptr(va) != 6) - error("bad std::vector mapping") -endif - -b.val = 7; -if (va(3).f(1) != 8) - error("bad std::vector mapping") -endif - - -ip = PtrInt(); -ap = new_ArrInt(10); - -ArrInt_setitem(ip,0,123); -ArrInt_setitem(ap,2,123); - -vi = IntPtrVector((ip,ap,None)); -if (ArrInt_getitem(vi[0],0) != ArrInt_getitem(vi[1],2)) - error("bad std::vector mapping") -endif - -delete_ArrInt(ap); - - -a = halfs([10,8,4,3]); - -v = IntVector(); -v(0:2) = [1,2]; -if (v(0) != 1 || v[1] != 2) - error("bad setslice") -endif - -if (v(0:-1)(0) != 1) - error("bad getslice") -endif - -if (v(0:-2).size() != 0) - error("bad getslice") - -v(0:1) = [2]; -if (v(0) != 2) - error("bad setslice") -endif - -v(1:) = [3]; -if (v(1) != 3) - error("bad setslice") -endif - -v(2:) = [3] -if (v(2) != 3) - error("bad setslice") -endif - -if (v(0:)(0) != v(0)) - error("bad getslice") -endif - - -v.erase(:) -if (v.size() != 0) - error("bad getslice") -endif - -v.erase(:) -if (v.size() != 0) - error("bad getslice") -endif - - - -v = vecStr({"hello ", "world"}); -if (v(0) != 'hello world') - error,"bad std::string+std::vector" -endif - - -pv = pyvector({1, "hello", (1,2)}); - -if (pv(1) != "hello") - error -endif - - -iv = IntVector(5); -for i=0:5, - iv(i) = i -endif - -iv(1:3) = []; -if (iv(1) != 3) - error -endif - -# Overloading checks -if (overloaded1(iv) != "vector") - error -endif - -if (overloaded1(dv) != "vector") - error -endif - -if (overloaded2(iv) != "vector") - error -endif - -if (overloaded2(dv) != "vector") - error -endif - -if (overloaded3(iv) != "vector *") - error -endif - -if (overloaded3(None) != "vector *") - error -endif - -if (overloaded3(100) != "int") - error -endif - diff --git a/Examples/test-suite/octave/multi_import_runme.m b/Examples/test-suite/octave/multi_import_runme.m index a6138736c..08149aae4 100644 --- a/Examples/test-suite/octave/multi_import_runme.m +++ b/Examples/test-suite/octave/multi_import_runme.m @@ -1,5 +1,5 @@ -multi_import_a -multi_import_b +multi_import_a; +multi_import_b; x = multi_import_b.XXX(); if (x.testx() != 0) 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/octave/overload_template_runme.m b/Examples/test-suite/octave/overload_template_runme.m index b38dc73e1..d7b1cbb65 100644 --- a/Examples/test-suite/octave/overload_template_runme.m +++ b/Examples/test-suite/octave/overload_template_runme.m @@ -1,8 +1,8 @@ overload_template 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/octave/wrapmacro_runme.m b/Examples/test-suite/octave/wrapmacro_runme.m index 4f42883d8..5069f2cca 100644 --- a/Examples/test-suite/octave/wrapmacro_runme.m +++ b/Examples/test-suite/octave/wrapmacro_runme.m @@ -2,7 +2,7 @@ wrapmacro a = 2; b = -1; -wrapmacro.max(a,b); -wrapmacro.max(a/7.0, -b*256); +wrapmacro.maximum(a,b); +wrapmacro.maximum(a/7.0, -b*256); wrapmacro.GUINT16_SWAP_LE_BE_CONSTANT(1); diff --git a/Examples/test-suite/operator_overload_break.i b/Examples/test-suite/operator_overload_break.i index 0893da786..9c6927bb0 100644 --- a/Examples/test-suite/operator_overload_break.i +++ b/Examples/test-suite/operator_overload_break.i @@ -12,7 +12,6 @@ %rename(PlusPlusPostfix) operator++(int); #endif - %{ #include using namespace std; @@ -56,7 +55,7 @@ public: Op& operator++() {k++; return *this;} - void Print() {std::cerr << k << std::endl;} + void PrintK() {std::cerr << k << std::endl;} int k; }; diff --git a/Examples/test-suite/overload_template.i b/Examples/test-suite/overload_template.i index a889dbfda..dee6ab91e 100644 --- a/Examples/test-suite/overload_template.i +++ b/Examples/test-suite/overload_template.i @@ -3,7 +3,7 @@ #ifdef SWIGLUA // lua only has one numeric type, so most of the overloads shadow each other creating warnings %warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) foo; -%warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) max; +%warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) maximum; %warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) specialization; %warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) overload; %warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) space::nsoverload; @@ -11,12 +11,6 @@ %warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) barT; #endif -%{ -#ifdef max -#undef max -#endif -%} - %inline %{ int foo() { @@ -29,15 +23,15 @@ template } template - T max(T a, T b) { return (a > b) ? a : b; } + T maximum(T a, T b) { return (a > b) ? a : b; } %} %template(foo) foo; %template(foo) foo; -%template(max) max; -%template(max) max; +%template(maximum) maximum; +%template(maximum) maximum; // Mix template overloading with plain function overload // Mix 1 diff --git a/Examples/test-suite/perl5/Makefile.in b/Examples/test-suite/perl5/Makefile.in index 3fee35bcb..67eaf5c9a 100644 --- a/Examples/test-suite/perl5/Makefile.in +++ b/Examples/test-suite/perl5/Makefile.in @@ -15,6 +15,7 @@ CPP_TEST_CASES += \ li_cdata \ li_cstring \ li_cdata_carrays \ + li_reference \ C_TEST_CASES += \ li_cdata \ @@ -26,6 +27,9 @@ include $(srcdir)/../common.mk # Overridden variables here # none! +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: $(setup) @@ -45,10 +49,9 @@ include $(srcdir)/../common.mk # Runs the testcase. A testcase is only run if # a file is found which has _runme.pl appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(PERL) $(TEST_RUNNER) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ; ) \ - fi; \ - + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(PERL) $(TEST_RUNNER) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi # Clean: remove the generated .pm file %.clean: diff --git a/Examples/test-suite/perl5/enum_thorough_runme.pl b/Examples/test-suite/perl5/enum_thorough_runme.pl index 80a2ccae9..66e719275 100644 --- a/Examples/test-suite/perl5/enum_thorough_runme.pl +++ b/Examples/test-suite/perl5/enum_thorough_runme.pl @@ -1,7 +1,7 @@ # an adaptation of ../java/enum_thorough_runme.java use strict; use warnings; -use Test::More tests => 272; +use Test::More tests => 298; BEGIN { use_ok('enum_thorough') } require_ok('enum_thorough'); @@ -348,17 +348,51 @@ SKIP: { $i->{MemberInstance} = $enum_thorough::Instances::memberinstance3; is($i->{MemberInstance}, $enum_thorough::Instances::memberinstance3, "MemberInstance 1"); } +# ignore enum item tests start +{ + is(enum_thorough::ignoreATest($enum_thorough::IgnoreTest::ignoreA_zero), 0, "ignoreATest 0"); + is(enum_thorough::ignoreATest($enum_thorough::IgnoreTest::ignoreA_three), 3, "ignoreATest 3"); + is(enum_thorough::ignoreATest($enum_thorough::IgnoreTest::ignoreA_ten), 10, "ignoreATest 10"); + is(enum_thorough::ignoreATest($enum_thorough::IgnoreTest::ignoreA_eleven), 11, "ignoreATest 11"); + is(enum_thorough::ignoreATest($enum_thorough::IgnoreTest::ignoreA_thirteen), 13, "ignoreATest 13"); + is(enum_thorough::ignoreATest($enum_thorough::IgnoreTest::ignoreA_fourteen), 14, "ignoreATest 14"); + is(enum_thorough::ignoreATest($enum_thorough::IgnoreTest::ignoreA_twenty), 20, "ignoreATest 20"); + is(enum_thorough::ignoreATest($enum_thorough::IgnoreTest::ignoreA_thirty), 30, "ignoreATest 30"); + is(enum_thorough::ignoreATest($enum_thorough::IgnoreTest::ignoreA_thirty_two), 32, "ignoreATest 32"); + is(enum_thorough::ignoreATest($enum_thorough::IgnoreTest::ignoreA_thirty_three), 33, "ignoreATest 33"); +} +{ + is(enum_thorough::ignoreBTest($enum_thorough::IgnoreTest::ignoreB_eleven), 11, "ignoreBTest 11"); + is(enum_thorough::ignoreBTest($enum_thorough::IgnoreTest::ignoreB_twelve), 12, "ignoreBTest 12"); + is(enum_thorough::ignoreBTest($enum_thorough::IgnoreTest::ignoreB_thirty_one), 31, "ignoreBTest 31"); + is(enum_thorough::ignoreBTest($enum_thorough::IgnoreTest::ignoreB_thirty_two), 32, "ignoreBTest 32"); + is(enum_thorough::ignoreBTest($enum_thorough::IgnoreTest::ignoreB_forty_one), 41, "ignoreBTest 41"); + is(enum_thorough::ignoreBTest($enum_thorough::IgnoreTest::ignoreB_forty_two), 42, "ignoreBTest 42"); +} +{ + is(enum_thorough::ignoreCTest($enum_thorough::IgnoreTest::ignoreC_ten), 10, "ignoreCTest 10"); + is(enum_thorough::ignoreCTest($enum_thorough::IgnoreTest::ignoreC_twelve), 12, "ignoreCTest 12"); + is(enum_thorough::ignoreCTest($enum_thorough::IgnoreTest::ignoreC_thirty), 30, "ignoreCTest 30"); + is(enum_thorough::ignoreCTest($enum_thorough::IgnoreTest::ignoreC_thirty_two), 32, "ignoreCTest 32"); + is(enum_thorough::ignoreCTest($enum_thorough::IgnoreTest::ignoreC_forty), 40, "ignoreCTest 40"); + is(enum_thorough::ignoreCTest($enum_thorough::IgnoreTest::ignoreC_forty_two), 42, "ignoreCTest 42"); +} +{ + is(enum_thorough::ignoreDTest($enum_thorough::IgnoreTest::ignoreD_twenty_one), 21, "ignoreDTest 21"); + is(enum_thorough::ignoreDTest($enum_thorough::IgnoreTest::ignoreD_twenty_two), 22, "ignoreDTest 22"); +} +{ + is(enum_thorough::ignoreETest($enum_thorough::IgnoreTest::ignoreE_zero), 0, "ignoreETest 0"); + is(enum_thorough::ignoreETest($enum_thorough::IgnoreTest::ignoreE_twenty_one), 21, "ignoreETest 21"); + is(enum_thorough::ignoreETest($enum_thorough::IgnoreTest::ignoreE_twenty_two), 22, "ignoreETest 22"); +} +# ignore enum item tests end { is(enum_thorough::repeatTest($enum_thorough::one), 1, "repeatTest 1"); is(enum_thorough::repeatTest($enum_thorough::initial), 1, "repeatTest 2"); is(enum_thorough::repeatTest($enum_thorough::two), 2, "repeatTest 3"); is(enum_thorough::repeatTest($enum_thorough::three), 3, "repeatTest 4"); -{ local $TODO = "overzealous keyword guarding"; - ok(defined($enum_thorough::last), "found enum value"); -SKIP: { - skip "enum value not in expected package", 1 unless defined $enum_thorough::last; - is(enum_thorough::repeatTest($enum_thorough::last), 3, "repeatTest 5"); -}} + is(enum_thorough::repeatTest($enum_thorough::llast), 3, "repeatTest 5"); is(enum_thorough::repeatTest($enum_thorough::end), 3, "repeatTest 6"); } @@ -368,8 +402,8 @@ SKIP: { is(enum_thorough::speedTest4($enum_thorough::SpeedClass::slow), $enum_thorough::SpeedClass::slow, "speedTest Global 4"); is(enum_thorough::speedTest5($enum_thorough::SpeedClass::slow), - $enum_thorough::SpeedClass::slow, "speedTest Global 5 failed"); + $enum_thorough::SpeedClass::slow, "speedTest Global 5"); is(enum_thorough::speedTest4($enum_thorough::SpeedClass::fast), - $enum_thorough::SpeedClass::fast, "speedTest Global 4 failed"); + $enum_thorough::SpeedClass::fast, "speedTest Global 4"); is(enum_thorough::speedTest5($enum_thorough::SpeedClass::fast), - $enum_thorough::SpeedClass::fast, "speedTest Global 5 failed"); + $enum_thorough::SpeedClass::fast, "speedTest Global 5"); diff --git a/Examples/test-suite/perl5/li_reference_runme.pl b/Examples/test-suite/perl5/li_reference_runme.pl new file mode 100644 index 000000000..afbd9e088 --- /dev/null +++ b/Examples/test-suite/perl5/li_reference_runme.pl @@ -0,0 +1,36 @@ +use strict; +use warnings; +use Test::More tests => 68; +BEGIN { use_ok('li_reference') } +require_ok('li_reference'); + +sub chk { my($type, $call, $v1, $v2) = @_; + $li_reference::FrVal = $v1; + my $v = $v2; + eval { $call->(\$v) }; + is($@, '', "$type check"); + is($li_reference::ToVal, $v2, "$type out"); + is($v, $v1, "$type in"); +} +chk("double*", \&li_reference::PDouble, 12.2, 18.6); +chk("double&", \&li_reference::RDouble, 32.5, 64.8); +chk("float*", \&li_reference::PFloat, 64.5, 96.0); +chk("float&", \&li_reference::RFloat, 98.5, 6.25); +chk("int*", \&li_reference::PInt, 1887, 3356); +chk("int&", \&li_reference::RInt, 2622, 9867); +chk("short*", \&li_reference::PShort, 4752, 3254); +chk("short&", \&li_reference::RShort, 1898, 5757); +chk("long*", \&li_reference::PLong, 6687, 7132); +chk("long&", \&li_reference::RLong, 8346, 4398); +chk("uint*", \&li_reference::PUInt, 6853, 5529); +chk("uint&", \&li_reference::RUInt, 5483, 7135); +chk("ushort*", \&li_reference::PUShort, 9960, 9930); +chk("ushort&", \&li_reference::RUShort, 1193, 4178); +chk("ulong*", \&li_reference::PULong, 7960, 4788); +chk("ulong&", \&li_reference::RULong, 8829, 1603); +chk("uchar*", \&li_reference::PUChar, 110, 239); +chk("uchar&", \&li_reference::RUChar, 15, 97); +chk("char*", \&li_reference::PChar, -7, 118); +chk("char&", \&li_reference::RChar, -3, -107); +chk("bool*", \&li_reference::PBool, 0, 1); +chk("bool&", \&li_reference::RBool, 1, 0); diff --git a/Examples/test-suite/perl5/wrapmacro_runme.pl b/Examples/test-suite/perl5/wrapmacro_runme.pl index f0345e469..8e0154057 100755 --- a/Examples/test-suite/perl5/wrapmacro_runme.pl +++ b/Examples/test-suite/perl5/wrapmacro_runme.pl @@ -9,6 +9,6 @@ require_ok('wrapmacro'); my $a = 2; my $b = -1; -is(wrapmacro::max($a,$b), 2); -is(wrapmacro::max($a/7.0, -$b*256), 256); +is(wrapmacro::maximum($a,$b), 2); +is(wrapmacro::maximum($a/7.0, -$b*256), 256); is(wrapmacro::GUINT16_SWAP_LE_BE_CONSTANT(1), 256); diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index b8aeaaa11..963051258 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -8,36 +8,23 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ -#CPP_TEST_CASES += \ -# php_namewarn_rename \ +CPP_TEST_CASES += \ + php_namewarn_rename \ include $(srcdir)/../common.mk # Overridden variables here TARGETPREFIX =# Should be php_ for Windows, empty otherwise -makecpptests: - @bash -ec 'for test in $(CPP_TEST_CASES) ; do $(MAKE) clean && $(MAKE) $${test}.cpptest; done' - -maketests: makecpptests makectests - -makectests: - @bash -ec 'for test in $(C_TEST_CASES) ; do $($(MAKE)) clean && $(MAKE) $${test}.cpptest; done' - -runcpptests: - @bash -ec 'for test in $(CPP_TEST_CASES) ; do if [ -f $${test}_runme.php ] ; then $(MAKE) clean && $(MAKE) $${test}.cpptest; fi ; done' - -runctests: - @bash -ec 'for test in $(C_TEST_CASES) ; do if [ -f $${test}_runme.php ] ; then $(MAKE) clean && $(MAKE) $${test}.cpptest; fi; done' - -runtests: runcpptests runctests +# Custom tests - tests with additional commandline options +prefix.cpptest: SWIGOPT += -prefix Project # write out tests without a _runme.php missingcpptests: - @bash -ec 'for test in $(CPP_TEST_CASES) ; do test -f $${test}_runme.php || echo $${test}; done' + for test in $(CPP_TEST_CASES) ; do test -f $${test}_runme.php || echo $${test}; done missingctests: - @bash -ec 'for test in $(C_TEST_CASES) ; do test -f $${test}_runme.php || echo $${test}; done' + for test in $(C_TEST_CASES) ; do test -f $${test}_runme.php || echo $${test}; done missingtests: missingcpptests missingctests @@ -57,12 +44,14 @@ missingtests: missingcpptests missingctests +$(swig_and_compile_multi_cpp) +$(run_testcase) -# Runs the testcase. A testcase is only run if -# a file is found which has _runme.php appended after the testcase name. +# Runs the testcase. Tries to run testcase_runme.php, and if that's not +# found, runs testcase.php, except for multicpptests. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHPSCRIPT=$(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) RUNTOOL=$(RUNTOOL) php_run;) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHPSCRIPT=$(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) RUNTOOL=$(RUNTOOL) php_run; \ + elif [ -f $(srcdir)/$(SCRIPTPREFIX)$*.php -a ! -f $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list ]; then \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHPSCRIPT=$(srcdir)/$(SCRIPTPREFIX)$*.php RUNTOOL=$(RUNTOOL) php_run; \ + fi # Clean: remove the generated .php file %.clean: diff --git a/Examples/test-suite/php/add_link_runme.php b/Examples/test-suite/php/add_link_runme.php index 4d8c31d5e..7523bd604 100644 --- a/Examples/test-suite/php/add_link_runme.php +++ b/Examples/test-suite/php/add_link_runme.php @@ -1,5 +1,4 @@ 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 92de96920..c208b7518 100644 --- a/Examples/test-suite/php/arrays_scope_runme.php +++ b/Examples/test-suite/php/arrays_scope_runme.php @@ -1,15 +1,14 @@ diff --git a/Examples/test-suite/php/class_ignore_runme.php b/Examples/test-suite/php/class_ignore_runme.php index 861576026..d5ce36217 100644 --- a/Examples/test-suite/php/class_ignore_runme.php +++ b/Examples/test-suite/php/class_ignore_runme.php @@ -1,5 +1,4 @@ diff --git a/Examples/test-suite/php/director_abstract_runme.php b/Examples/test-suite/php/director_abstract_runme.php new file mode 100644 index 000000000..ca3d676da --- /dev/null +++ b/Examples/test-suite/php/director_abstract_runme.php @@ -0,0 +1,62 @@ +ping(), "MyFoo::ping()", "MyFoo::ping failed"); + +check::equal($a->pong(), "Foo::pong();MyFoo::ping()", "MyFoo::pong failed"); + +class MyExample1 extends Example1 { + function Color($r, $g, $b) { + return $r; + } +} + +class MyExample2 extends Example1 { + function Color($r, $g, $b) { + return $g; + } +} + +class MyExample3 extends Example1 { + function Color($r, $g, $b) { + return $b; + } +} + +$me1 = new MyExample1(); +check::equal($me1->Color(1, 2, 3), 1, "Example1_get_color failed"); + +$me2 = new MyExample2(1, 2); +check::equal($me2->Color(1, 2, 3), 2, "Example2_get_color failed"); + +$me3 = new MyExample3(); +check::equal($me3->Color(1, 2, 3), 3, "Example3_get_color failed"); + +$class = new ReflectionClass('Example1'); +check::equal($class->isAbstract(), true, "Example1 abstractness failed"); + +$class = new ReflectionClass('Example2'); +check::equal($class->isAbstract(), true, "Example2 abstractness failed"); + +$class = new ReflectionClass('Example3_i'); +check::equal($class->isAbstract(), true, "Example3_i abstractness failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php/director_basic_runme.php b/Examples/test-suite/php/director_basic_runme.php new file mode 100644 index 000000000..de6b50502 --- /dev/null +++ b/Examples/test-suite/php/director_basic_runme.php @@ -0,0 +1,58 @@ +ping(), "PhpFoo::ping()", "ping failed"); + +check::equal($a->pong(), "Foo::pong();PhpFoo::ping()", "pong failed"); + +$b = new Foo(); + +check::equal($b->ping(), "Foo::ping()", "ping failed"); + +check::equal($b->pong(), "Foo::pong();Foo::ping()", "pong failed"); + +$a = new A1(1); + +check::equal($a->rg(2), 2, "rg failed"); + +class PhpClass extends MyClass { + function vmethod($b) { + $b->x = $b->x + 31; + return $b; + } +} + +$b = new Bar(3); +$d = new MyClass(); +$c = new PhpClass(); + +$cc = MyClass::get_self($c); +$dd = MyClass::get_self($d); + +$bc = $cc->cmethod($b); +$bd = $dd->cmethod($b); + +$cc->method($b); + +check::equal($bc->x, 34, "bc failed"); +check::equal($bd->x, 16, "bd failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php/director_classic_runme.php b/Examples/test-suite/php/director_classic_runme.php new file mode 100644 index 000000000..d2da1b1ba --- /dev/null +++ b/Examples/test-suite/php/director_classic_runme.php @@ -0,0 +1,150 @@ +id(); + if ($debug) + print $ret . "\n"; + check::equal($ret, $expected, "#1 failed"); + + # Polymorphic call from C++ + $caller = new Caller(); + $caller->setCallback($person); + $ret = $caller->call(); + if ($debug) + print $ret . "\n"; + check::equal($ret, $expected, "#2 failed"); + + # Polymorphic call of object created in target language and passed to + # C++ and back again + $baseclass = $caller->baseClass(); + $ret = $baseclass->id(); + if ($debug) + print $ret . "\n"; + # TODO: Currently we do not track the dynamic type of returned + # objects, so in case it's possible that the dynamic type is not equal + # to the static type, we skip this check. + if (get_parent_class($person) === false) + check::equal($ret, $expected, "#3 failed"); + + $caller->resetCallback(); + if ($debug) + print "----------------------------------------\n"; +} + +$person = new Person(); +mycheck($person, "Person"); +unset($person); + +$person = new Child(); +mycheck($person, "Child"); +unset($person); + +$person = new GrandChild(); +mycheck($person, "GrandChild"); +unset($person); + +$person = new TargetLangPerson(); +mycheck($person, "TargetLangPerson"); +unset($person); + +$person = new TargetLangChild(); +mycheck($person, "TargetLangChild"); +unset($person); + +$person = new TargetLangGrandChild(); +mycheck($person, "TargetLangGrandChild"); +unset($person); + +# Semis - don't override id() in target language +$person = new TargetLangSemiPerson(); +mycheck($person, "Person"); +unset($person); + +$person = new TargetLangSemiChild(); +mycheck($person, "Child"); +unset($person); + +$person = new TargetLangSemiGrandChild(); +mycheck($person, "GrandChild"); +unset($person); + +# Orphans - don't override id() in C++ +$person = new OrphanPerson(); +mycheck($person, "Person"); +unset($person); + +$person = new OrphanChild(); +mycheck($person, "Child"); +unset($person); + +$person = new TargetLangOrphanPerson(); +mycheck($person, "TargetLangOrphanPerson"); +unset($person); + +$person = new TargetLangOrphanChild(); +mycheck($person, "TargetLangOrphanChild"); +unset($person); + +check::done(); +?> diff --git a/Examples/test-suite/php/director_default_runme.php b/Examples/test-suite/php/director_default_runme.php new file mode 100644 index 000000000..f97fc7425 --- /dev/null +++ b/Examples/test-suite/php/director_default_runme.php @@ -0,0 +1,20 @@ + diff --git a/Examples/test-suite/php/director_detect_runme.php b/Examples/test-suite/php/director_detect_runme.php new file mode 100644 index 000000000..cc19c0302 --- /dev/null +++ b/Examples/test-suite/php/director_detect_runme.php @@ -0,0 +1,55 @@ +val = $val; + } + + function get_value() { + $this->val = $this->val + 1; + return $this->val; + } + + function get_class() { + $this->val = $this->val + 1; + return new A(); + } + + function just_do_it() { + $this->val = $this->val + 1; + } + + /* clone is a reserved keyword */ + function clone_() { + return new MyBar($this->val); + } +} + +$b = new MyBar(); + +$f = $b->baseclass(); + +$v = $f->get_value(); +$a = $f->get_class(); +$f->just_do_it(); + +$c = $b->clone_(); +$vc = $c->get_value(); + +check::equal($v, 3, "f: Bad virtual detection"); +check::equal($b->val, 5, "b: Bad virtual detection"); +check::equal($vc, 6, "c: Bad virtual detection"); + +check::done(); +?> diff --git a/Examples/test-suite/php/director_enum_runme.php b/Examples/test-suite/php/director_enum_runme.php new file mode 100644 index 000000000..8f6487a28 --- /dev/null +++ b/Examples/test-suite/php/director_enum_runme.php @@ -0,0 +1,25 @@ +say_hi(director_enum::hello), $b->say_hello(director_enum::hi), "say failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php/director_exception_runme.php b/Examples/test-suite/php/director_exception_runme.php new file mode 100644 index 000000000..33e6e9b52 --- /dev/null +++ b/Examples/test-suite/php/director_exception_runme.php @@ -0,0 +1,78 @@ +msg = $a . $b; + } +} + +class MyFoo extends Foo { + function ping() { + throw new Exception("MyFoo::ping() EXCEPTION"); + } +} + +class MyFoo2 extends Foo { + function ping() { + return true; + } +} + +class MyFoo3 extends Foo { + function ping() { + throw new MyException("foo", "bar"); + } +} + +# Check that the Exception raised by MyFoo.ping() is returned by +# MyFoo.pong(). +$ok = 0; +$a = new MyFoo(); +# TODO: Currently we do not track the dynamic type of returned +# objects, so we skip the launder() call. +#$b = director_exception::launder($a); +$b = $a; +try { + $b->pong(); +} catch (Exception $e) { + $ok = 1; + check::equal($e->getMessage(), "MyFoo::ping() EXCEPTION", "Unexpected error message #1"); +} +check::equal($ok, 1, "Got no exception while expected one #1"); + +# Check that the director can return an exception which requires two +# arguments to the constructor, without mangling it. +$ok = 0; +$a = new MyFoo3(); +#$b = director_exception::launder($a); +$b = $a; +try { + $b->pong(); +} catch (Exception $e) { + $ok = 1; + check::equal($e->msg, "foobar", "Unexpected error message #2"); +} +check::equal($ok, 1, "Got no exception while expected one #2"); + +try { + throw new Exception2(); +} catch (Exception2 $e2) { +} + +try { + throw new Exception1(); +} catch (Exception1 $e1) { +} + +check::done(); +?> diff --git a/Examples/test-suite/php/director_extend_runme.php b/Examples/test-suite/php/director_extend_runme.php new file mode 100644 index 000000000..f283aefbe --- /dev/null +++ b/Examples/test-suite/php/director_extend_runme.php @@ -0,0 +1,24 @@ +dummy(), 666, "1st call"); +check::equal($m->dummy(), 666, "2st call"); // Locked system + +check::done(); +?> diff --git a/Examples/test-suite/php/director_finalizer_runme.php b/Examples/test-suite/php/director_finalizer_runme.php new file mode 100644 index 000000000..0fcddfd8b --- /dev/null +++ b/Examples/test-suite/php/director_finalizer_runme.php @@ -0,0 +1,61 @@ +orStatus(2); + if (method_exists(parent, "__destruct")) { + parent::__destruct(); + } + } +} + +resetStatus(); + +$a = new MyFoo(); +unset($a); + +check::equal(getStatus(), 3, "getStatus() failed #1"); + +resetStatus(); + +$a = new MyFoo(); +launder($a); + +check::equal(getStatus(), 0, "getStatus() failed #2"); + +unset($a); + +check::equal(getStatus(), 3, "getStatus() failed #3"); + +resetStatus(); + +$a = new MyFoo(); +$a->thisown = 0; +deleteFoo($a); +unset($a); + +check::equal(getStatus(), 3, "getStatus() failed #4"); + +resetStatus(); + +$a = new MyFoo(); +$a->thisown = 0; +deleteFoo(launder($a)); +unset($a); + +check::equal(getStatus(), 3, "getStatus() failed #5"); + +resetStatus(); + +check::done(); +?> diff --git a/Examples/test-suite/php/director_frob_runme.php b/Examples/test-suite/php/director_frob_runme.php new file mode 100644 index 000000000..548b0b804 --- /dev/null +++ b/Examples/test-suite/php/director_frob_runme.php @@ -0,0 +1,19 @@ +abs_method(); + +check::equal($s, "Bravo::abs_method()", "s failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php/director_nested_runme.php b/Examples/test-suite/php/director_nested_runme.php new file mode 100644 index 000000000..4965e94f7 --- /dev/null +++ b/Examples/test-suite/php/director_nested_runme.php @@ -0,0 +1,74 @@ +step(), "Bar::step;Foo::advance;Bar::do_advance;A::do_step;", "Bad A virtual resolution"); + +class B extends FooBar_int { + function do_advance() { + return "B::do_advance;" . $this->do_step(); + } + + function do_step() { + return "B::do_step;"; + } + + function get_value() { + return 1; + } +} + +$b = new B(); + +check::equal($b->step(), "Bar::step;Foo::advance;B::do_advance;B::do_step;", "Bad B virtual resolution"); + +class C extends FooBar_int { + function do_advance() { + return "C::do_advance;" . parent::do_advance(); + } + + function do_step() { + return "C::do_step;"; + } + + function get_value() { + return 2; + } + + function get_name() { + return parent::get_name() . " hello"; + } +} + +$cc = new C(); +# TODO: Currently we do not track the dynamic type of returned +# objects, so we skip the get_self() call. +#$c = Foobar_int::get_self($cc); +$c = $cc; +$c->advance(); + +check::equal($c->get_name(), "FooBar::get_name hello", "get_name failed"); + +check::equal($c->name(), "FooBar::get_name hello", "name failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php/director_profile_runme.php b/Examples/test-suite/php/director_profile_runme.php new file mode 100644 index 000000000..c72421341 --- /dev/null +++ b/Examples/test-suite/php/director_profile_runme.php @@ -0,0 +1,53 @@ +fi($a); #1 + $a = $b->fi($a); #2 + $a = $b->fi($a); #3 + $a = $b->fi($a); #4 + $a = $b->fi($a); #5 + $a = $b->fi($a); #6 + $a = $b->fi($a); #7 + $a = $b->fi($a); #8 + $a = $b->fi($a); #9 + $a = $b->fi($a); #10 + $a = $b->fi($a); #1 + $a = $b->fi($a); #2 + $a = $b->fi($a); #3 + $a = $b->fi($a); #4 + $a = $b->fi($a); #5 + $a = $b->fi($a); #6 + $a = $b->fi($a); #7 + $a = $b->fi($a); #8 + $a = $b->fi($a); #9 + $a = $b->fi($a); #20 + $i -= 1; +} + +print $a . "\n"; + +check::done(); +?> diff --git a/Examples/test-suite/php/director_protected_runme.php b/Examples/test-suite/php/director_protected_runme.php new file mode 100644 index 000000000..73bcba1fd --- /dev/null +++ b/Examples/test-suite/php/director_protected_runme.php @@ -0,0 +1,54 @@ +create(); +$fb = new FooBar(); +$fb2 = new FooBar2(); + +check::equal($fb->used(), "Foo::pang();Bar::pong();Foo::pong();FooBar::ping();", "bad FooBar::used"); + +check::equal($fb2->used(), "FooBar2::pang();Bar::pong();Foo::pong();FooBar2::ping();", "bad FooBar2::used"); + +check::equal($b->pong(), "Bar::pong();Foo::pong();Bar::ping();", "bad Bar::pong"); + +check::equal($f->pong(), "Bar::pong();Foo::pong();Bar::ping();", "bad Foo::pong"); + +check::equal($fb->pong(), "Bar::pong();Foo::pong();FooBar::ping();", "bad FooBar::pong"); + +$method = new ReflectionMethod('Bar', 'ping'); +check::equal($method->isProtected(), true, "Boo::ping should be protected"); + +$method = new ReflectionMethod('Foo', 'ping'); +check::equal($method->isProtected(), true, "Foo::ping should be protected"); + +$method = new ReflectionMethod('FooBar', 'pang'); +check::equal($method->isProtected(), true, "FooBar::pang should be protected"); + +check::done(); +?> diff --git a/Examples/test-suite/php/director_stl_runme.php b/Examples/test-suite/php/director_stl_runme.php new file mode 100644 index 000000000..29addd261 --- /dev/null +++ b/Examples/test-suite/php/director_stl_runme.php @@ -0,0 +1,60 @@ +tping("hello"); +$a->tpong("hello"); + +# TODO: automatic conversion between PHP arrays and std::pair or +# std::vector is not yet implemented. +/*$p = array(1, 2); +$a->pident($p); +$v = array(3, 4); +$a->vident($v); + +$a->tpident($p); +$a->tvident($v); + +$v1 = array(3, 4); +$v2 = array(5, 6); + +$a->tvsecond($v1, $v2); + +$vs = array("hi", "hello"); +$vs; +$a->tvidents($vs);*/ + +check::done(); +?> diff --git a/Examples/test-suite/php/director_string_runme.php b/Examples/test-suite/php/director_string_runme.php new file mode 100644 index 000000000..5ac583f78 --- /dev/null +++ b/Examples/test-suite/php/director_string_runme.php @@ -0,0 +1,34 @@ +smem = "hello"; + } +} + +$b = new B("hello"); + +$b->get(0); +check::equal($b->get_first(),"hello world!", "get_first failed"); + +$b->call_process_func(); + +check::equal($b->smem, "hello", "smem failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php/director_thread_runme.php b/Examples/test-suite/php/director_thread_runme.php new file mode 100644 index 000000000..8df25d969 --- /dev/null +++ b/Examples/test-suite/php/director_thread_runme.php @@ -0,0 +1,29 @@ +val = $this->val - 1; + } +} + +$d = new Derived(); +$d->run(); + +if ($d->val >= 0) { + check::fail($d->val); +} + +$d->stop(); + +check::done(); +?> diff --git a/Examples/test-suite/php/director_unroll_runme.php b/Examples/test-suite/php/director_unroll_runme.php new file mode 100644 index 000000000..626b1f07d --- /dev/null +++ b/Examples/test-suite/php/director_unroll_runme.php @@ -0,0 +1,29 @@ +set($a); +$c = $b->get(); + +check::equal($a->this, $c->this, "this failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php/enum_scope_template_runme.php b/Examples/test-suite/php/enum_scope_template_runme.php index 7cea23911..85ba467b7 100644 --- a/Examples/test-suite/php/enum_scope_template_runme.php +++ b/Examples/test-suite/php/enum_scope_template_runme.php @@ -1,14 +1,12 @@ _foo,"1==spam->_foo"); check::equal(2,$spam->_bar,"2==spam->_bar"); -check::equal(3,$spam->_baz,"3==spam->_baz"); +// multiple inheritance not supported in PHP +check::equal(null,$spam->_baz,"null==spam->_baz"); check::equal(4,$spam->_spam,"4==spam->_spam"); check::done(); diff --git a/Examples/test-suite/php/evil_diamond_runme.php b/Examples/test-suite/php/evil_diamond_runme.php index a6ef211b1..a587ca359 100644 --- a/Examples/test-suite/php/evil_diamond_runme.php +++ b/Examples/test-suite/php/evil_diamond_runme.php @@ -1,5 +1,4 @@ diff --git a/Examples/test-suite/php/li_carrays_runme.php b/Examples/test-suite/php/li_carrays_runme.php index babf8443b..fbe5cc793 100644 --- a/Examples/test-suite/php/li_carrays_runme.php +++ b/Examples/test-suite/php/li_carrays_runme.php @@ -1,15 +1,22 @@ setitem(0, 7); +$d->setitem(5, $d->getitem(0) + 3); +check::equal($d->getitem(0) + $d->getitem(5), 17., "7+10==17"); check::done(); ?> diff --git a/Examples/test-suite/php/li_factory_runme.php b/Examples/test-suite/php/li_factory_runme.php new file mode 100644 index 000000000..6623e2a8c --- /dev/null +++ b/Examples/test-suite/php/li_factory_runme.php @@ -0,0 +1,22 @@ +radius(); +check::equal($r, 1.5, "r failed"); + +$point = Geometry::create(Geometry::POINT); +$w = $point->width(); +check::equal($w, 1.0, "w failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php/li_std_string_runme.php b/Examples/test-suite/php/li_std_string_runme.php index c7270df3d..ad62247e1 100644 --- a/Examples/test-suite/php/li_std_string_runme.php +++ b/Examples/test-suite/php/li_std_string_runme.php @@ -1,5 +1,4 @@ makeMore(); +check::equal(get_class($bar), "Foo", "regular failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php/overload_rename_runme.php b/Examples/test-suite/php/overload_rename_runme.php new file mode 100644 index 000000000..dce4c6cb3 --- /dev/null +++ b/Examples/test-suite/php/overload_rename_runme.php @@ -0,0 +1,19 @@ + diff --git a/Examples/test-suite/php/pointer_reference_runme.php b/Examples/test-suite/php/pointer_reference_runme.php new file mode 100644 index 000000000..782760a37 --- /dev/null +++ b/Examples/test-suite/php/pointer_reference_runme.php @@ -0,0 +1,15 @@ +value, 10, "pointer_reference::get() failed"); + +$ss = new Struct(20); +pointer_reference::set($ss); +$i = Struct::instance(); +check::equal($i->value, 20, "pointer_reference::set() failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php/prefix_runme.php b/Examples/test-suite/php/prefix_runme.php new file mode 100644 index 000000000..ead064f5b --- /dev/null +++ b/Examples/test-suite/php/prefix_runme.php @@ -0,0 +1,18 @@ +get_self(); + +check::done(); +?> diff --git a/Examples/test-suite/php/primitive_ref_runme.php b/Examples/test-suite/php/primitive_ref_runme.php new file mode 100644 index 000000000..ab23fb1cc --- /dev/null +++ b/Examples/test-suite/php/primitive_ref_runme.php @@ -0,0 +1,25 @@ + diff --git a/Examples/test-suite/php/rename_scope_runme.php b/Examples/test-suite/php/rename_scope_runme.php index 33925a6db..df620d796 100644 --- a/Examples/test-suite/php/rename_scope_runme.php +++ b/Examples/test-suite/php/rename_scope_runme.php @@ -1,17 +1,16 @@ diff --git a/Examples/test-suite/php/smart_pointer_rename_runme.php b/Examples/test-suite/php/smart_pointer_rename_runme.php index a1759cb95..26692dde5 100644 --- a/Examples/test-suite/php/smart_pointer_rename_runme.php +++ b/Examples/test-suite/php/smart_pointer_rename_runme.php @@ -1,12 +1,11 @@ > 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 b8bd8944c..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 \ @@ -89,6 +88,9 @@ include $(srcdir)/../common.mk LIBS = -L. VALGRIND_OPT += --suppressions=pythonswig.supp +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: $(setup) @@ -122,28 +124,27 @@ py3_runme = $(srcdir)/$(SCRIPTPREFIX)$*$(PY3SCRIPTSUFFIX) ifeq (,$(PY3)) run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - $(run_python);)\ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + $(run_python);\ + fi else run_testcase = \ - if [ -f $(py2_runme) ]; then ( \ - $(MAKE) -f $(srcdir)/Makefile $(py3_runme) && \ - $(run_python);) \ - elif [ -f $(py3_runme) ]; then ( \ - $(run_python);) \ - fi; + if [ -f $(py2_runme) ]; then \ + $(MAKE) -f $(srcdir)/Makefile $(py3_runme) && $(run_python); \ + elif [ -f $(py3_runme) ]; then \ + $(run_python); \ + fi endif # Clean: remove the generated .py file %.clean: - @rm -f hugemod.h hugemod_a.i hugemod_b.i hugemod_a.py hugemod_b.py hugemod_runme.py @rm -f $*.py; @#We only remove the _runme3.py if it is generated by 2to3 from a _runme.py. - @if [ -f $(py2_runme) ]; then (rm -f $(py3_runme) $(py3_runme).bak;) fi; + @if [ -f $(py2_runme) ]; then rm -f $(py3_runme) $(py3_runme).bak; fi clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile python_clean + rm -f hugemod.h hugemod_a.i hugemod_b.i hugemod_a.py hugemod_b.py hugemod_runme.py cvsignore: @echo '*wrap* *.pyc *.so *.dll *.exp *.lib' @@ -166,3 +167,4 @@ hugemod: $(MAKE) hugemod_b.cpptest sh -c "time $(PYTHON) $(hugemod_runme)" sh -c "time $(PYTHON) $(hugemod_runme)" + 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/overload_template_runme.py b/Examples/test-suite/python/overload_template_runme.py index 3fd77f339..c1337ba6a 100644 --- a/Examples/test-suite/python/overload_template_runme.py +++ b/Examples/test-suite/python/overload_template_runme.py @@ -1,8 +1,8 @@ from overload_template 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/special_variable_macros_runme.py b/Examples/test-suite/python/special_variable_macros_runme.py new file mode 100644 index 000000000..07e60dfa2 --- /dev/null +++ b/Examples/test-suite/python/special_variable_macros_runme.py @@ -0,0 +1,16 @@ +import special_variable_macros + +name = special_variable_macros.Name() +if special_variable_macros.testFred(name) != "none": + raise "test failed" +if special_variable_macros.testJack(name) != "$specialname": + raise "test failed" +if special_variable_macros.testJill(name) != "jilly": + raise "test failed" +if special_variable_macros.testMary(name) != "SWIGTYPE_p_NameWrap": + raise "test failed" +if special_variable_macros.testJim(name) != "multiname num": + raise "test failed" +if special_variable_macros.testJohn(special_variable_macros.PairIntBool(10, False)) != 123: + raise "test failed" + 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/python/template_typedef_import_runme.py b/Examples/test-suite/python/template_typedef_import_runme.py index 48d88eda0..5c0b0b936 100644 --- a/Examples/test-suite/python/template_typedef_import_runme.py +++ b/Examples/test-suite/python/template_typedef_import_runme.py @@ -1,4 +1,3 @@ -import string from template_typedef_cplx2 import * from template_typedef_import import * diff --git a/Examples/test-suite/python/wrapmacro_runme.py b/Examples/test-suite/python/wrapmacro_runme.py index e7a5a3771..0272afd5d 100644 --- a/Examples/test-suite/python/wrapmacro_runme.py +++ b/Examples/test-suite/python/wrapmacro_runme.py @@ -2,6 +2,6 @@ import wrapmacro a = 2 b = -1 -wrapmacro.max(a,b) -wrapmacro.max(a/7.0, -b*256) +wrapmacro.maximum(a,b) +wrapmacro.maximum(a/7.0, -b*256) wrapmacro.GUINT16_SWAP_LE_BE_CONSTANT(1) diff --git a/Examples/test-suite/r/Makefile.in b/Examples/test-suite/r/Makefile.in index 98d1f9571..32d046679 100644 --- a/Examples/test-suite/r/Makefile.in +++ b/Examples/test-suite/r/Makefile.in @@ -16,6 +16,10 @@ CPP_TEST_CASES = r_double_delete include $(srcdir)/../common.mk # Overridden variables here +# none! + +# Custom tests - tests with additional commandline options +# none! # Rules for the different types of tests %.cpptest: @@ -38,20 +42,19 @@ include $(srcdir)/../common.mk # Run the runme if it exists. If not just load the R wrapper to # check for syntactic correctness run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" \ - $(RUNTOOL) $(RUNR) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ;) \ + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" $(RUNTOOL) $(RUNR) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ else \ - ($(RUNTOOL) $(RUNR) $(srcdir)/$(SCRIPTPREFIX)$*$(WRAPSUFFIX);) \ - fi; + $(RUNTOOL) $(RUNR) $(srcdir)/$(SCRIPTPREFIX)$*$(WRAPSUFFIX); \ + fi run_multitestcase = \ for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX) ]; then ( \ + if [ -f $(srcdir)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX) ]; then \ env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" \ - $(RUNTOOL) $(RUNR) $(srcdir)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX) ;) \ + $(RUNTOOL) $(RUNR) $(srcdir)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX); \ else \ - ($(RUNTOOL) $(RUNR) $(srcdir)/$(SCRIPTPREFIX)$${f}$(WRAPSUFFIX);) \ + $(RUNTOOL) $(RUNR) $(srcdir)/$(SCRIPTPREFIX)$${f}$(WRAPSUFFIX); \ fi; \ done # Clean @@ -60,10 +63,10 @@ clean: %.clean: @rm -f $*.R $*_wrap.so $*_wrap.cpp $*_wrap.c $*_wrap.o $*_runme.Rout $*.Rout - @if [ -f $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list ]; then ( \ + @if [ -f $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list ]; then \ for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ rm -f $${f}.R $${f}.Rout ; \ - done ) \ + done \ fi diff --git a/Examples/test-suite/rename_scope.i b/Examples/test-suite/rename_scope.i index 6bea35b0e..9a09949c4 100644 --- a/Examples/test-suite/rename_scope.i +++ b/Examples/test-suite/rename_scope.i @@ -7,7 +7,7 @@ enum Polarization { UnaryPolarization, BinaryPolarization }; template - struct Interface + struct Interface_ { }; } @@ -15,9 +15,9 @@ namespace oss { - // Interface - %template(Interface_UP) Interface; - %template(Interface_BP) Interface; + // Interface_ + %template(Interface_UP) Interface_; + %template(Interface_BP) Interface_; } %inline @@ -27,7 +27,7 @@ namespace oss namespace interfaces { template - struct Natural : Interface

          + struct Natural : Interface_

          { int test(void) { return 1; } }; diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index d50b478be..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 \ @@ -38,12 +37,10 @@ include $(srcdir)/../common.mk # Overridden variables here SWIGOPT += -w801 -noautorename -features autodoc=4 - -# Rules for the different types of tests - -# make sure -autorename is true for the naming test +# Custom tests - tests with additional commandline options ruby_naming.cpptest: SWIGOPT += -autorename +# Rules for the different types of tests %.cpptest: $(setup) +$(swig_and_compile_cpp) @@ -62,9 +59,9 @@ ruby_naming.cpptest: SWIGOPT += -autorename # Runs the testcase. A testcase is only run if # a file is found which has _runme.rb appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(RUBY) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(RUBY) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi # Clean %.clean: diff --git a/Examples/test-suite/ruby/li_std_vector_runme.rb b/Examples/test-suite/ruby/li_std_vector_runme.rb index 484f1888e..8bcad2d19 100755 --- a/Examples/test-suite/ruby/li_std_vector_runme.rb +++ b/Examples/test-suite/ruby/li_std_vector_runme.rb @@ -98,6 +98,13 @@ sv[1] = Li_std_vector::Struct.new EOF +bv = BoolVector.new(2) +[true, false, true, true].each { |i| bv.push(i) } +0.upto(bv.size-1) { |i| bv[i] = !bv[i] } +bv_check = [true, true, false, true, false, false] +for i in 0..bv.size-1 do + swig_assert(bv_check[i] == bv[i], binding, "bv[#{i}]") +end swig_assert_each_line(<<'EOF', binding) lv = LanguageVector.new diff --git a/Examples/test-suite/ruby/overload_template_runme.rb b/Examples/test-suite/ruby/overload_template_runme.rb index bcbddf512..b099fd3ea 100755 --- a/Examples/test-suite/ruby/overload_template_runme.rb +++ b/Examples/test-suite/ruby/overload_template_runme.rb @@ -13,5 +13,5 @@ require 'overload_template' f = Overload_template.foo() -a = Overload_template.max(3,4) -b = Overload_template.max(3.4,5.2) +a = Overload_template.maximum(3,4) +b = Overload_template.maximum(3.4,5.2) diff --git a/Examples/test-suite/ruby/primitive_types_runme.rb b/Examples/test-suite/ruby/primitive_types_runme.rb index 9fde5b3dd..0024c9696 100644 --- a/Examples/test-suite/ruby/primitive_types_runme.rb +++ b/Examples/test-suite/ruby/primitive_types_runme.rb @@ -50,6 +50,9 @@ end raise RuntimeError if fail != 1 +# Test a number which won't fit in a 32 bit integer and is represented +# as a FIXNUM by Ruby. +raise RuntimeError if val_double(51767811298) != 51767811298 raise RuntimeError if val_double_2(1.0) != 4.0 raise RuntimeError if val_double_2(1) != 4 diff --git a/Examples/test-suite/special_variable_macros.i b/Examples/test-suite/special_variable_macros.i new file mode 100644 index 000000000..f27bbd619 --- /dev/null +++ b/Examples/test-suite/special_variable_macros.i @@ -0,0 +1,179 @@ +%module special_variable_macros + +// test $typemap() special variable function +// these tests are not typical of how $typemap() should be used, but it checks that it is mostly working + +%inline %{ +struct Name { + Name(const char *n="none") : name(n) {} + const char *getName() const { return name; }; + Name *getNamePtr() { return this; }; +private: + const char *name; +}; +struct NameWrap { + NameWrap(const char *n="casternone") : name(n) {} + Name *getNamePtr() { return &name; }; +private: + Name name; +}; +%} + +// check $1 and $input get expanded properly when used from $typemap() +%typemap(in) Name *GENERIC ($*1_type temp) +%{ + /*%typemap(in) Name *GENERIC start */ + temp = Name("$specialname"); + (void)$input; + $1 = ($1_ltype) &temp; + /*%typemap(in) Name *GENERIC end */ +%} + +// This would never be done in real code, it is just a test of what madness can be done. +// Note that the special variable substitutions $*1_type, $descriptor etc are for NameWrap +// even when used within the Name typemap via $typemap. I can't think of any useful use cases +// for this behaviour in the C/C++ typemaps, but it is possible. +%typemap(in) NameWrap *NAMEWRAP ($*1_type temp) +%{ + /*%typemap(in) NameWrap *NAMEWRAP start */ + temp = $*1_ltype("$descriptor"); + (void)$input; + $1 = temp.getNamePtr(); + /*%typemap(in) NameWrap *NAMEWRAP end */ +%} + + +////////////////////////////////////////////////////////////////////////////////////// + +// This should use Name *GENERIC typemap which ignores passed in Name * and instead uses a newly a newly constructed Name +// held in a typemap variable with name="$specialname" +%typemap(in) Name *jack { +// %typemap(in) Name *jack start +$typemap(in, Name *GENERIC) +// %typemap(in) Name *jack end +} + +// as above, but also perform variable substitution +%typemap(in) Name *jill { +// %typemap(in) Name *jill start +$typemap(in, Name *GENERIC, specialname=jilly) +// %typemap(in) Name *jill end +} + +%typemap(in) Name *mary { +// %typemap(in) Name *mary start +$typemap(in, NameWrap *NAMEWRAP) +// %typemap(in) Name *mary end +} + +%inline %{ +const char * testFred(Name *fred) { + return fred->getName(); +} +const char * testJack(Name *jack) { + return jack->getName(); +} +const char * testJill(Name *jill) { + return jill->getName(); +} +const char * testMary(Name *mary) { + return mary->getName(); +} +%} + +////////////////////////////////////////////////////////////////////////////////////// +// Multi-arg typemap lookup +// One would never do something like this in reality, it just checks $typemap with multi-arg typemaps +%typemap(in) (Name *multiname, int num)($*1_type temp_name, $2_ltype temp_count) +%{ + /*%typemap(in) (Name *multiname, int num) start */ + temp_name = $*1_ltype("multiname num"); + temp_count = (int)strlen(temp_name.getNamePtr()->getName()); + (void)$input; + $1 = temp_name.getNamePtr(); + $2 = temp_count + 100; + /*%typemap(in) (Name *multiname, int num) end */ +%} + +%typemap(in) (Name *jim, int count) { +// %typemap(in) Name *jim start +$typemap(in, (Name *multiname, int num)) +// %typemap(in) Name *jim end +} + +%inline %{ +const char * testJim(Name *jim, int count) { + if (count != (int)strlen(jim->getNamePtr()->getName()) + 100) + return "size check failed"; + else + return jim->getName(); +} +%} + +////////////////////////////////////////////////////////////////////////////////////// +// Template types with more than one template parameter + +// check $1 and $input get expanded properly when used from $typemap() +%typemap(in) Space::Pair PAIR_INT_BOOL ($1_type temp) +%{ + /*%typemap(in) Name *GENERIC start */ + temp = Space::Pair(123, true); + (void)$input; + $1 = ($1_ltype)temp; + /*%typemap(in) Name *GENERIC end */ +%} + +%typemap(in) Space::Pair john { +// %typemap(in) Name *john start +$typemap(in, Space::Pair PAIR_INT_BOOL) +// %typemap(in) Name *john end +} + +%inline %{ +namespace Space { + template struct Pair { + Pair(T1 f, T2 s) : first(f), second(s) {} + Pair() {} + T1 first; + T2 second; + }; + int testJohn(Space::Pair john) { + return john.first; + } +} +%} +%template(PairIntBool) Space::Pair; + +////////////////////////////////////////////////////////////////////////////////////// +// A real use case for $typemap + +#if defined(SWIGCSHARP) +%typemap(cscode) Space::RenameMe %{ + public static NewName factory(String s) { + //below should expand to: + //return new NewName( new Name(s) ); + return new $typemap(cstype, Space::RenameMe)( new $typemap(cstype, Name)(s) ); + } +%} +#elif defined(SWIGJAVA) +%typemap(javacode) Space::RenameMe %{ + public static NewName factory(String s) { + //below should expand to: + //return new NewName( new Name(s) ); + return new $typemap(jstype, Space::RenameMe)( new $typemap(jstype, Name)(s) ); + } +%} +#endif + +%rename(NewName) Space::RenameMe; +%inline %{ +namespace Space { + struct RenameMe { + RenameMe(Name n) : storedName(n) {} + Name getStoredName() { return storedName; } + private: + Name storedName; + }; +} +%} + 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/symbol_clash.i b/Examples/test-suite/symbol_clash.i new file mode 100644 index 000000000..f0aef1398 --- /dev/null +++ b/Examples/test-suite/symbol_clash.i @@ -0,0 +1,28 @@ +%module symbol_clash + +// ::Vector and ::Text::Vector were incorrectly clashing in the target language symbol tables + +#if defined(SWIGJAVA) || defined(SWIGCSHARP) + +#if defined(SWIGJAVA) +%include "enumtypeunsafe.swg" +#elif defined(SWIGCSHARP) +%include "enumsimple.swg" +#endif + +%inline %{ +class Vector +{ +}; + +namespace Text +{ + enum Preference + { + Raster, + Vector + }; +} +%} + +#endif diff --git a/Examples/test-suite/tcl/Makefile.in b/Examples/test-suite/tcl/Makefile.in index 7c4b7ed61..49d2a7826 100644 --- a/Examples/test-suite/tcl/Makefile.in +++ b/Examples/test-suite/tcl/Makefile.in @@ -23,6 +23,9 @@ include $(srcdir)/../common.mk # Overridden variables here # none! +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: $(setup) @@ -42,9 +45,9 @@ include $(srcdir)/../common.mk # Runs the testcase. A testcase is only run if # a file is found which has _runme.tcl appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(TCLSH) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(TCLSH) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi # Clean %.clean: 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_default.i b/Examples/test-suite/template_default.i index 2f6ffd5ba..d771ef09e 100644 --- a/Examples/test-suite/template_default.i +++ b/Examples/test-suite/template_default.i @@ -1,8 +1,7 @@ %module template_default - - %warnfilter(SWIGWARN_RUBY_WRONG_NAME) ns1::Traits::c; /* Ruby, wrong constant name */ + namespace ns1 { namespace ns2 { @@ -154,8 +153,8 @@ namespace ns1 { %} -%template(Do) ns1::ns4::D; -%template(Bo) ns1::ns4::Base >; +%template(Doo) ns1::ns4::D; +%template(Boo) ns1::ns4::Base >; diff --git a/Examples/test-suite/template_default2.i b/Examples/test-suite/template_default2.i index 1e0b6240d..9ba0455f1 100644 --- a/Examples/test-suite/template_default2.i +++ b/Examples/test-suite/template_default2.i @@ -8,7 +8,7 @@ enum Polarization { UnaryPolarization, BinaryPolarization }; template - struct Interface + struct Interface_tpl { }; @@ -19,7 +19,7 @@ template > // **** problem here ***** + class Base = Interface_tpl

          > // **** problem here ***** struct Module : Base { }; @@ -29,12 +29,12 @@ namespace oss { - %template(Interface_UP) Interface; + %template(Interface_UP) Interface_tpl; // This works %template(Module_UP1) Module >; + Interface_tpl >; // These don't %template(Module_UP2) Module; diff --git a/Examples/test-suite/template_default_qualify.i b/Examples/test-suite/template_default_qualify.i index bcba1a44e..640011b2c 100644 --- a/Examples/test-suite/template_default_qualify.i +++ b/Examples/test-suite/template_default_qualify.i @@ -12,14 +12,14 @@ enum Polarization { UnaryPolarization, BinaryPolarization }; template - struct Interface + struct Interface_ { }; namespace modules { - template > + template > // *** problem here **** struct Module : base { @@ -35,7 +35,7 @@ namespace oss { - %template(Interface_UP) Interface; + %template(Interface_UP) Interface_; namespace modules { %template(Module_etraits) Module; diff --git a/Examples/test-suite/template_enum_ns_inherit.i b/Examples/test-suite/template_enum_ns_inherit.i index 8992eef6d..c617b5716 100644 --- a/Examples/test-suite/template_enum_ns_inherit.i +++ b/Examples/test-suite/template_enum_ns_inherit.i @@ -6,7 +6,7 @@ enum Polarization { UnaryPolarization, BinaryPolarization }; template - struct Interface + struct Interface_ { }; @@ -21,8 +21,8 @@ namespace oss { - %template(Interface_UP) Interface; - %template(Module_UPIUP) Module >; + %template(Interface_UP) Interface_; + %template(Module_UPIUP) Module >; } %inline %{ @@ -31,18 +31,18 @@ namespace oss namespace hello { struct HInterface1 : - Interface // this works (with fullns qualification) + Interface_ // this works (with fullns qualification) { }; struct HInterface2 : - Interface // this doesn't work + Interface_ // this doesn't work { }; - struct HModule1 : Module > { + struct HModule1 : Module > { }; } } -%} \ No newline at end of file +%} diff --git a/Examples/test-suite/template_enum_typedef.i b/Examples/test-suite/template_enum_typedef.i index 9752d0858..38444594e 100644 --- a/Examples/test-suite/template_enum_typedef.i +++ b/Examples/test-suite/template_enum_typedef.i @@ -9,7 +9,7 @@ enum Polarization { UnaryPolarization, BinaryPolarization }; template - struct Interface + struct Interface_ { }; @@ -25,7 +25,7 @@ typedef Traits traits; static const Polarization P = traits::pmode; - void get(Interface

          arg) { }; // Here P is only replace by traits::pmode + void get(Interface_

          arg) { }; // Here P is only replace by traits::pmode }; } @@ -34,6 +34,6 @@ namespace oss { - %template(Interface_UP) Interface; + %template(Interface_UP) Interface_; %template(Module_UP) Module; } diff --git a/Examples/test-suite/template_methods.i b/Examples/test-suite/template_methods.i index efd7e3707..8524d5b44 100644 --- a/Examples/test-suite/template_methods.i +++ b/Examples/test-suite/template_methods.i @@ -5,6 +5,8 @@ %warnfilter(SWIGWARN_LANG_TEMPLATE_METHOD_IGNORE) convolve1(); %warnfilter(SWIGWARN_LANG_TEMPLATE_METHOD_IGNORE) convolve3(); +%include + /////////////////// %ignore convolve1(float a); @@ -76,3 +78,23 @@ struct Klass { %template(KlassTMethodBool) Klass::tmethod; %template(KlassStaticTMethodBool) Klass::statictmethod; +//////////////////////////////////////////////////////////////////////////// + +%inline %{ + class ComponentProperties{ + public: + ComponentProperties() {} + ~ComponentProperties() {} + + template void adda(std::string key, T1 val) {} + template void adda(std::string key1, T1 val1, std::string key2, T2 val2) {} + template void adda(std::string key1, T1 val1, std::string key2, T2 val2, std::string key3, T3 val3) {} + }; +%} + +%extend ComponentProperties { + %template(adda) adda; + %template(adda) adda; // ERROR OCCURS HERE + %template(adda) adda; +} + 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_ns4.i b/Examples/test-suite/template_ns4.i index 34489c473..f5c134852 100644 --- a/Examples/test-suite/template_ns4.i +++ b/Examples/test-suite/template_ns4.i @@ -8,13 +8,13 @@ }; template - struct Function + struct Function_ { char *test() { return (char *) "test"; } }; template - struct ArithFunction : Function + struct ArithFunction : Function_ { }; @@ -40,7 +40,7 @@ }; template - class Class : public ArithFunction< typename traits::arg_type, + class Class_ : public ArithFunction< typename traits::arg_type, typename traits::res_type > { }; @@ -49,7 +49,7 @@ typename traits::base make_Class() { - return Class(); + return Class_(); } @@ -58,9 +58,9 @@ %{ namespace hello { - template struct Function ; + template struct Function_ ; template struct ArithFunction ; - template class Class ; + template class Class_ ; } %} @@ -69,9 +69,9 @@ // This complains only when using a namespace // %template() traits; - %template(Function_DD) Function ; + %template(Function_DD) Function_ ; %template(ArithFunction_DD) ArithFunction ; - %template(Class_DD) Class ; + %template(Class_DD) Class_ ; %template(make_Class_DD) make_Class ; } 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/throw_exception.i b/Examples/test-suite/throw_exception.i index 9a0ddabde..c1ad945fb 100644 --- a/Examples/test-suite/throw_exception.i +++ b/Examples/test-suite/throw_exception.i @@ -8,6 +8,9 @@ %warnfilter(SWIGWARN_RUBY_WRONG_NAME) Namespace::enum1; %warnfilter(SWIGWARN_RUBY_WRONG_NAME) Namespace::enum2; +#ifdef SWIGPHP +%warnfilter(SWIGWARN_PARSE_KEYWORD) Namespace; +#endif // Tests SWIG's automatic exception mechanism diff --git a/Examples/test-suite/typemap_global_scope.i b/Examples/test-suite/typemap_global_scope.i new file mode 100644 index 000000000..92170363f --- /dev/null +++ b/Examples/test-suite/typemap_global_scope.i @@ -0,0 +1,215 @@ +%module typemap_global_scope + +// Test global scope operator :: for typemaps. Previously SWIG would not use a typemap that did not specify the global scope +// operator for a type that did have it, and vice-versa. + +%typemap(in) SWIGTYPE "_this_will_not_compile_SWIGTYPE_ \"$type\"" +%typemap(in) const SWIGTYPE & "_this_will_not_compile_const_SWIGTYPE_REF_ \"$type\"" +%typemap(in) enum SWIGTYPE "_this_will_not_compile_enum_SWIGTYPE_ \"$type\"" +%typemap(in) const enum SWIGTYPE & "_this_will_not_compile_const_enum_SWIGTYPE_REF_ \"$type\"" + +///////////////////////////////////////////////////////////////////// +// Structs +///////////////////////////////////////////////////////////////////// + +%typemap(in) Test1, ::Test2, Space::Test3, ::Space::Test4 "/*in typemap for $type*/" +%typemap(in) const Test1 &, const ::Test2 &, const Space::Test3 &, const ::Space::Test4 & "/*in typemap for $type*/" +%inline %{ +struct Test1 {}; +struct Test2 {}; +namespace Space { + struct Test3 {}; + struct Test4 {}; +} +%} + +%inline %{ +void test1a(Test1 t, const Test1 &tt) {} +void test1b(::Test1 t, const ::Test1 &tt) {} + +void test2a(Test2 t, const Test2 &tt) {} +void test2b(::Test2 t, const ::Test2 &tt) {} + +void test3a(Space::Test3 t, const Space::Test3 &tt) {} +void test3b(::Space::Test3 t, const ::Space::Test3 &tt) {} +namespace Space { + void test3c(Space::Test3 t, const Space::Test3 &tt) {} + void test3d(::Space::Test3 t, const ::Space::Test3 &tt) {} + void test3e(Test3 t, const Test3 &tt) {} +} + +void test4a(Space::Test4 t, const Space::Test4 &tt) {} +void test4b(::Space::Test4 t, const ::Space::Test4 &tt) {} +namespace Space { + void test4c(Space::Test4 t, const Space::Test4 &tt) {} + void test4d(::Space::Test4 t, const ::Space::Test4 &tt) {} + void test4e(Test4 t, const Test4 &tt) {} +} +%} + +///////////////////////////////////////////////////////////////////// +// Templates +///////////////////////////////////////////////////////////////////// + +%inline %{ +struct XX {}; +%} + +%typemap(in) TemplateTest1< ::XX >, ::TemplateTest2< ::XX >, Space::TemplateTest3< ::XX >, ::Space::TemplateTest4< ::XX > "/* in typemap for $type */" +%typemap(in) const TemplateTest1< XX > &, const ::TemplateTest2< XX > &, const Space::TemplateTest3< XX > &, const ::Space::TemplateTest4< XX > & "/* in typemap for $type */" +%inline %{ +template struct TemplateTest1 { T m_t; }; +template struct TemplateTest2 { T m_t; }; +namespace Space { + template struct TemplateTest3 { T m_t; }; + template struct TemplateTest4 { T m_t; }; +} +%} + +%template(TemplateTest1XX) TemplateTest1< ::XX >; +%template(TemplateTest2XX) TemplateTest2< ::XX >; +%template(TemplateTest3XX) Space::TemplateTest3< ::XX >; +%template(TemplateTest4XX) Space::TemplateTest4< ::XX >; + +%inline %{ +void test_template_1a(TemplateTest1< ::XX > t, const TemplateTest1< ::XX > &tt) {} +void test_template_1b(::TemplateTest1< ::XX > t, const ::TemplateTest1< ::XX > &tt) {} + +void test_template_2a(TemplateTest2< ::XX > t, const TemplateTest2< ::XX > &tt) {} +void test_template_2b(::TemplateTest2< ::XX > t, const ::TemplateTest2< ::XX > &tt) {} + +void test_template_3a(Space::TemplateTest3< ::XX > t, const Space::TemplateTest3< ::XX > &tt) {} +void test_template_3b(::Space::TemplateTest3< ::XX > t, const ::Space::TemplateTest3< ::XX > &tt) {} +namespace Space { + void test_template_3c(Space::TemplateTest3< ::XX > t, const Space::TemplateTest3< ::XX > &tt) {} + void test_template_3d(::Space::TemplateTest3< ::XX > t, const ::Space::TemplateTest3< ::XX > &tt) {} + void test_template_3e(TemplateTest3< ::XX > t, const TemplateTest3< ::XX > &tt) {} +} + +void test_template_4a(Space::TemplateTest4< ::XX > t, const Space::TemplateTest4< ::XX > &tt) {} +void test_template_4b(::Space::TemplateTest4< ::XX > t, const ::Space::TemplateTest4< ::XX > &tt) {} +namespace Space { + void test_template_4c(Space::TemplateTest4< ::XX > t, const Space::TemplateTest4< ::XX > &tt) {} + void test_template_4d(::Space::TemplateTest4< ::XX > t, const ::Space::TemplateTest4< ::XX > &tt) {} + void test_template_4e(TemplateTest4< ::XX > t, const TemplateTest4< ::XX > &tt) {} +} +%} + +///////////////////////////////////////////////////////////////////// +// Enums +///////////////////////////////////////////////////////////////////// + +%typemap(in) Enum1, ::Enum2, Space::Enum3, ::Space::Enum4 "/*in typemap for $type*/" +%typemap(in) const Enum1 &, const ::Enum2 &, const Space::Enum3 &, const ::Space::Enum4 & "/*in typemap for $type*/" +%inline %{ +enum Enum1 { enum_1 }; +enum Enum2 { enum_2 }; +namespace Space { + enum Enum3 { enum_3 }; + enum Enum4 { enum_4 }; +} +%} + +%inline %{ +void test_enum_1a(Enum1 t, const Enum1 &tt) {} +void test_enum_1b(::Enum1 t, const ::Enum1 &tt) {} + +void test_enum_2a(Enum2 t, const Enum2 &tt) {} +void test_enum_2b(::Enum2 t, const ::Enum2 &tt) {} + +void test_enum_3a(Space::Enum3 t, const Space::Enum3 &tt) {} +void test_enum_3b(::Space::Enum3 t, const ::Space::Enum3 &tt) {} +namespace Space { + void test_enum_3c(Space::Enum3 t, const Space::Enum3 &tt) {} + void test_enum_3d(::Space::Enum3 t, const ::Space::Enum3 &tt) {} + void test_enum_3e(Enum3 t, const Enum3 &tt) {} +} + +void test_enum_4a(Space::Enum4 t, const Space::Enum4 &tt) {} +void test_enum_4b(::Space::Enum4 t, const ::Space::Enum4 &tt) {} +namespace Space { + void test_enum_4c(Space::Enum4 t, const Space::Enum4 &tt) {} + void test_enum_4d(::Space::Enum4 t, const ::Space::Enum4 &tt) {} + void test_enum_4e(Enum4 t, const Enum4 &tt) {} +} +%} + +#if 0 +///////////////////////////////////////////////////////////////////// +// Enums with enum specified in typemap +///////////////////////////////////////////////////////////////////// + +%typemap(in) enum Mune1, enum ::Mune2, enum Space::Mune3, enum ::Space::Mune4 "/*in typemap for $type*/" +%typemap(in) const enum Mune1 &, const enum ::Mune2 &, const enum Space::Mune3 &, const enum ::Space::Mune4 & "/*in typemap for $type*/" +%inline %{ +enum Mune1 { mune_1 }; +enum Mune2 { mune_2 }; +namespace Space { + enum Mune3 { mune_3 }; + enum Mune4 { mune_4 }; +} +%} + +%inline %{ +void test_mune_1a(Mune1 t, const Mune1 &tt) {} +void test_mune_1b(::Mune1 t, const ::Mune1 &tt) {} + +void test_mune_2a(Mune2 t, const Mune2 &tt) {} +void test_mune_2b(::Mune2 t, const ::Mune2 &tt) {} + +void test_mune_3a(Space::Mune3 t, const Space::Mune3 &tt) {} +void test_mune_3b(::Space::Mune3 t, const ::Space::Mune3 &tt) {} +namespace Space { + void test_mune_3c(Space::Mune3 t, const Space::Mune3 &tt) {} + void test_mune_3d(::Space::Mune3 t, const ::Space::Mune3 &tt) {} + void test_mune_3e(Mune3 t, const Mune3 &tt) {} +} + +void test_mune_4a(Space::Mune4 t, const Space::Mune4 &tt) {} +void test_mune_4b(::Space::Mune4 t, const ::Space::Mune4 &tt) {} +namespace Space { + void test_mune_4c(Space::Mune4 t, const Space::Mune4 &tt) {} + void test_mune_4d(::Space::Mune4 t, const ::Space::Mune4 &tt) {} + void test_mune_4e(Mune4 t, const Mune4 &tt) {} +} +%} + +///////////////////////////////////////////////////////////////////// +// Enums with enum specified in type +///////////////////////////////////////////////////////////////////// + +%typemap(in) Nemu1, ::Nemu2, Space::Nemu3, ::Space::Nemu4 "/*in typemap for $type*/" +%typemap(in) const Nemu1 &, const ::Nemu2 &, const Space::Nemu3 &, const ::Space::Nemu4 & "/*in typemap for $type*/" +%inline %{ +enum Nemu1 { nemu_1 }; +enum Nemu2 { nemu_2 }; +namespace Space { + enum Nemu3 { nemu_3 }; + enum Nemu4 { nemu_4 }; +} +%} + +%inline %{ +void test_nemu_1a(enum Nemu1 t, const enum Nemu1 &tt) {} +void test_nemu_1b(enum ::Nemu1 t, const enum ::Nemu1 &tt) {} + +void test_nemu_2a(enum Nemu2 t, const enum Nemu2 &tt) {} +void test_nemu_2b(enum ::Nemu2 t, const enum ::Nemu2 &tt) {} + +void test_nemu_3a(enum Space::Nemu3 t, const enum Space::Nemu3 &tt) {} +void test_nemu_3b(enum ::Space::Nemu3 t, const enum ::Space::Nemu3 &tt) {} +namespace Space { + void test_nemu_3c(enum Space::Nemu3 t, const enum Space::Nemu3 &tt) {} + void test_nemu_3d(enum ::Space::Nemu3 t, const enum ::Space::Nemu3 &tt) {} + void test_nemu_3e(enum Nemu3 t, const enum Nemu3 &tt) {} +} + +void test_nemu_4a(enum Space::Nemu4 t, const enum Space::Nemu4 &tt) {} +void test_nemu_4b(enum ::Space::Nemu4 t, const enum ::Space::Nemu4 &tt) {} +namespace Space { + void test_nemu_4c(enum Space::Nemu4 t, const enum Space::Nemu4 &tt) {} + void test_nemu_4d(enum ::Space::Nemu4 t, const enum ::Space::Nemu4 &tt) {} + void test_nemu_4e(enum Nemu4 t, const enum Nemu4 &tt) {} +} +%} +#endif diff --git a/Examples/test-suite/typemap_out_optimal.i b/Examples/test-suite/typemap_out_optimal.i index 8bac2fa89..23cd2ad3f 100644 --- a/Examples/test-suite/typemap_out_optimal.i +++ b/Examples/test-suite/typemap_out_optimal.i @@ -23,10 +23,10 @@ using namespace std; struct XX { - XX() { cout << "XX()" << endl; } + XX() { if (debug) cout << "XX()" << endl; } XX(int i) { if (debug) cout << "XX(" << i << ")" << endl; } - XX(const XX &other) { cout << "XX(const XX &)" << endl; } - XX& operator =(const XX &other) { cout << "operator=(const XX &)" << endl; return *this; } + XX(const XX &other) { if (debug) cout << "XX(const XX &)" << endl; } + XX& operator =(const XX &other) { if (debug) cout << "operator=(const XX &)" << endl; return *this; } ~XX() { if (debug) cout << "~XX()" << endl; } static XX create() { return XX(123); diff --git a/Examples/test-suite/typemap_template.i b/Examples/test-suite/typemap_template.i new file mode 100644 index 000000000..ad35371cc --- /dev/null +++ b/Examples/test-suite/typemap_template.i @@ -0,0 +1,34 @@ +%module typemap_template + +/* Test bug in 1.3.40 where the presence of a generic/unspecialized typemap caused the incorrect specialized typemap to be used */ + +%typemap(in) SWIGTYPE "/*_this_will_not_compile_SWIGTYPE_ \"$type\" */ " +%typemap(in) const SWIGTYPE & "/*_this_will_not_compile_const_SWIGTYPE_REF_\"$type\" */ " + +%typemap(in) const TemplateTest1 & {$1 = (TemplateTest1 *)0; /* in typemap generic for $type */} +%typemap(in) const TemplateTest1< ZZ > & {$1 = (TemplateTest1 *)0; /* in typemap ZZ for $type */} +%typemap(in) const TemplateTest1< int > & {$1 = (TemplateTest1 *)0; /* in typemap int for $type */} + +%inline %{ +template struct TemplateTest1 { + void setT(const TemplateTest1& t) {} +}; +%} + +%inline %{ + struct YY {}; + struct ZZ {}; +%} + + +%template(TTYY) TemplateTest1< YY >; +%template(TTZZ) TemplateTest1< ZZ >; +%template(TTint) TemplateTest1< int >; + +%inline %{ + void extratest(const TemplateTest1< YY > &t, + const TemplateTest1< ZZ > &tt, + const TemplateTest1< int > &ttt) + {} +%} + diff --git a/Examples/test-suite/uffi/Makefile.in b/Examples/test-suite/uffi/Makefile.in index c09153d9e..d6b948b5d 100644 --- a/Examples/test-suite/uffi/Makefile.in +++ b/Examples/test-suite/uffi/Makefile.in @@ -11,10 +11,14 @@ top_builddir = @top_builddir@ include $(srcdir)/../common.mk +# Overridden variables here # no C++ tests for now CPP_TEST_CASES = #C_TEST_CASES += +# Custom tests - tests with additional commandline options +# none! + # Rules for the different types of tests %.cpptest: $(setup) @@ -34,9 +38,9 @@ CPP_TEST_CASES = # Runs the testcase. A testcase is only run if # a file is found which has _runme.lisp appended after the testcase name. run_testcase = \ - if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(UFFIBIN) -batch -s $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \ - fi; + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(UFFIBIN) -batch -s $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + fi # Clean: (does nothing, we dont generate extra uffi code) %.clean: 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_base.i b/Examples/test-suite/valuewrapper_base.i index 1698c3e03..63471bbc8 100644 --- a/Examples/test-suite/valuewrapper_base.i +++ b/Examples/test-suite/valuewrapper_base.i @@ -10,9 +10,9 @@ }; template - struct Interface : Base + struct Interface_ : Base { - Interface(const Base& b) { }; + Interface_(const Base& b) { }; }; template @@ -23,6 +23,6 @@ namespace oss { // Interface - %template(Interface_BP) Interface; - %template(make_Interface_BP) make >; + %template(Interface_BP) Interface_; + %template(make_Interface_BP) make >; } 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/Examples/test-suite/wallkw.i b/Examples/test-suite/wallkw.i new file mode 100644 index 000000000..0ac383bcd --- /dev/null +++ b/Examples/test-suite/wallkw.i @@ -0,0 +1,16 @@ +%module wallkw + +// test the -Wallkw option + +%warnfilter(SWIGWARN_PARSE_KEYWORD) clone; // 'clone' is a php keyword, renamed as 'c_clone' +%warnfilter(SWIGWARN_PARSE_KEYWORD) delegate; // 'delegate' is a C# keyword, renaming to '_delegate' +%warnfilter(SWIGWARN_PARSE_KEYWORD) pass; // 'pass' is a python keyword, renaming to '_pass' +%warnfilter(SWIGWARN_PARSE_KEYWORD) alias; // 'alias' is a ruby keyword, renaming to 'C_alias' + +%inline %{ +const char * clone() { return "clone"; } +const char * delegate() { return "delegate"; } +const char * pass() { return "pass"; } +const char * alias() { return "alias"; } +%} + diff --git a/Examples/test-suite/wrapmacro.i b/Examples/test-suite/wrapmacro.i index 5353e7706..bd5e48b15 100644 --- a/Examples/test-suite/wrapmacro.i +++ b/Examples/test-suite/wrapmacro.i @@ -21,7 +21,8 @@ typedef unsigned short guint16; (guint16) ((guint16) (val) >> 8) | \ (guint16) ((guint16) (val) << 8))) -#define max(a,b) ((a) > (b) ? (a) : (b)) +/* Don't use max(), it's a builtin function for PHP. */ +#define maximum(a,b) ((a) > (b) ? (a) : (b)) %} @@ -41,8 +42,8 @@ type SWIGMACRO_##name(lparams) { /* Here, wrapping the macros */ %wrapmacro(guint16, GUINT16_SWAP_LE_BE_CONSTANT, guint16 val, val); -%wrapmacro(size_t, max, PLIST(size_t a, const size_t& b), PLIST(a, b)); -%wrapmacro(double, max, PLIST(double a, double b), PLIST(a, b)); +%wrapmacro(size_t, maximum, PLIST(size_t a, const size_t& b), PLIST(a, b)); +%wrapmacro(double, maximum, PLIST(double a, double b), PLIST(a, b)); /* Maybe in the future, a swig directive will make this easier: diff --git a/Lib/allkw.swg b/Lib/allkw.swg index 2a2fe18d8..fb76ff287 100644 --- a/Lib/allkw.swg +++ b/Lib/allkw.swg @@ -19,7 +19,7 @@ %include %include %include -%include +%include %include %include %include diff --git a/Lib/cdata.i b/Lib/cdata.i index 41e8f86ce..1abaf357b 100644 --- a/Lib/cdata.i +++ b/Lib/cdata.i @@ -76,5 +76,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/csharp/boost_shared_ptr.i b/Lib/csharp/boost_shared_ptr.i index 2cb687356..52ac510ce 100644 --- a/Lib/csharp/boost_shared_ptr.i +++ b/Lib/csharp/boost_shared_ptr.i @@ -1,7 +1,9 @@ %include +// Language specific macro implementing all the customisations for handling the smart pointer %define SWIG_SHARED_PTR_TYPEMAPS(PROXYCLASS, CONST, TYPE...) +// %naturalvar is as documented for member variables %naturalvar TYPE; %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; @@ -10,6 +12,7 @@ //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" +// Typemap customisations... // plain value %typemap(in, canthrow=1) CONST TYPE ($&1_type argp = 0) %{ diff --git a/Lib/csharp/std_map.i b/Lib/csharp/std_map.i index a30b6fa70..24efbe26f 100644 --- a/Lib/csharp/std_map.i +++ b/Lib/csharp/std_map.i @@ -1,25 +1,14 @@ /* ----------------------------------------------------------------------------- * std_map.i * - * SWIG typemaps for std::map + * SWIG typemaps for std::map< K, T > * * The C# wrapper is made to look and feel like a C# System.Collections.Generic.IDictionary<>. * * Using this wrapper is fairly simple. For example, to create a map from integers to doubles use: * * %include - * %template(Map_Int_Double) std::map - * - * Very often the C# generated code will not compile as the C++ template type is not the same as the C# - * proxy type, so use the SWIG_STD_MAP_SPECIALIZED or SWIG_STD_MAP_SPECIALIZED_SIMPLE macros. For example: - * - * SWIG_STD_MAP_SPECIALIZED(MyCppKeyClass, MyCppValueClass, MyCsKeyClass, MyCsValueClass) - * %template(Map_MyCppKeyClass_MyCppValueClass) std::map; - * - * Or if the C# class names are the same as the C++ class names, you can use: - * - * SWIG_STD_MAP_SPECIALIZED_SIMPLE(MyKeyClass, MyValueClass) - * %template(Map_MyCppKeyClass_MyCppValueClass) std::map; + * %template(MapIntDouble) std::map * * Notes: * 1) For .NET 1 compatibility, define SWIG_DOTNET_1 when compiling the C# code. In this case @@ -36,69 +25,13 @@ #include %} -// A minimal implementation to be used when no specialization exists. -%define SWIG_STD_MAP_MINIMAL_INTERNAL(K, T) - public: - map(); - map(const map &other); +/* K is the C++ key type, T is the C++ value type */ +%define SWIG_STD_MAP_INTERNAL(K, T) - typedef K key_type; - typedef T mapped_type; - typedef size_t size_type; - size_type size() const; - bool empty() const; - %rename(Clear) clear; - void clear(); - %extend { - const mapped_type& getitem(const key_type& key) throw (std::out_of_range) { - std::map::iterator iter = $self->find(key); - if (iter != $self->end()) - return iter->second; - else - throw std::out_of_range("key not found"); - } - - void setitem(const key_type& key, const mapped_type& x) { - (*$self)[key] = x; - } - - bool ContainsKey(const key_type& key) { - std::map::iterator iter = $self->find(key); - return iter != $self->end(); - } - - void Add(const key_type& key, const mapped_type& val) throw (std::out_of_range) { - std::map::iterator iter = $self->find(key); - if (iter != $self->end()) - throw std::out_of_range("key already exists"); - $self->insert(std::pair(key, val)); - } - - bool Remove(const key_type& key) { - std::map::iterator iter = $self->find(key); - if (iter != $self->end()) { - $self->erase(iter); - return true; - } - return false; - } - - } - -%enddef - -/* The specialized std::map implementation - * K is the C++ key type - * T is the C++ value type - * CSKEYTYPE is the C# key type - * CSVALUETYPE is the C# value type - */ -%define SWIG_STD_MAP_SPECIALIZED_INTERNAL(K, T, CSKEYTYPE, CSVALUETYPE) -// add typemaps here -%typemap(csinterfaces) std::map "IDisposable \n#if !SWIG_DOTNET_1\n , System.Collections.Generic.IDictionary\n#endif\n"; +%typemap(csinterfaces) std::map< K, T > "IDisposable \n#if !SWIG_DOTNET_1\n , System.Collections.Generic.IDictionary<$typemap(cstype, K), $typemap(cstype, T)>\n#endif\n"; %typemap(cscode) std::map %{ - public CSVALUETYPE this[CSKEYTYPE key] { + public $typemap(cstype, T) this[$typemap(cstype, K) key] { get { return getitem(key); } @@ -108,12 +41,12 @@ } } - public bool TryGetValue(CSKEYTYPE key, out CSVALUETYPE value) { + public bool TryGetValue($typemap(cstype, K) key, out $typemap(cstype, T) value) { if (this.ContainsKey(key)) { value = this[key]; return true; } - value = default(CSVALUETYPE); + value = default($typemap(cstype, T)); return false; } @@ -131,9 +64,9 @@ #if !SWIG_DOTNET_1 - public System.Collections.Generic.ICollection Keys { + public System.Collections.Generic.ICollection<$typemap(cstype, K)> Keys { get { - System.Collections.Generic.ICollection keys = new System.Collections.Generic.List(); + System.Collections.Generic.ICollection<$typemap(cstype, K)> keys = new System.Collections.Generic.List<$typemap(cstype, K)>(); IntPtr iter = create_iterator_begin(); try { while (true) { @@ -145,21 +78,21 @@ } } - public System.Collections.Generic.ICollection Values { + public System.Collections.Generic.ICollection<$typemap(cstype, T)> Values { get { - System.Collections.Generic.ICollection vals = new System.Collections.Generic.List(); - foreach (System.Collections.Generic.KeyValuePair pair in this) { + System.Collections.Generic.ICollection<$typemap(cstype, T)> vals = new System.Collections.Generic.List<$typemap(cstype, T)>(); + foreach (System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> pair in this) { vals.Add(pair.Value); } return vals; } } - public void Add(System.Collections.Generic.KeyValuePair item) { + public void Add(System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> item) { Add(item.Key, item.Value); } - public bool Remove(System.Collections.Generic.KeyValuePair item) { + public bool Remove(System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> item) { if (Contains(item)) { return Remove(item.Key); } else { @@ -167,7 +100,7 @@ } } - public bool Contains(System.Collections.Generic.KeyValuePair item) { + public bool Contains(System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> item) { if (this[item.Key] == item.Value) { return true; } else { @@ -175,11 +108,11 @@ } } - public void CopyTo(System.Collections.Generic.KeyValuePair[] array) { + public void CopyTo(System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>[] array) { CopyTo(array, 0); } - public void CopyTo(System.Collections.Generic.KeyValuePair[] array, int arrayIndex) { + public void CopyTo(System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException("array"); if (arrayIndex < 0) @@ -189,14 +122,14 @@ if (arrayIndex+this.Count > array.Length) throw new ArgumentException("Number of elements to copy is too large."); - System.Collections.Generic.IList keyList = new System.Collections.Generic.List(this.Keys); + System.Collections.Generic.IList<$typemap(cstype, K)> keyList = new System.Collections.Generic.List<$typemap(cstype, K)>(this.Keys); for (int i = 0; i < keyList.Count; i++) { - CSKEYTYPE currentKey = keyList[i]; - array.SetValue(new System.Collections.Generic.KeyValuePair(currentKey, this[currentKey]), arrayIndex+i); + $typemap(cstype, K) currentKey = keyList[i]; + array.SetValue(new System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>(currentKey, this[currentKey]), arrayIndex+i); } } - System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { + System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { return new $csclassnameEnumerator(this); } @@ -214,24 +147,24 @@ /// collection but not when one of the elements of the collection is modified as it is a bit /// tricky to detect unmanaged code that modifies the collection under our feet. public sealed class $csclassnameEnumerator : System.Collections.IEnumerator, - System.Collections.Generic.IEnumerator> + System.Collections.Generic.IEnumerator> { private $csclassname collectionRef; - private System.Collections.Generic.IList keyCollection; + private System.Collections.Generic.IList<$typemap(cstype, K)> keyCollection; private int currentIndex; private object currentObject; private int currentSize; public $csclassnameEnumerator($csclassname collection) { collectionRef = collection; - keyCollection = new System.Collections.Generic.List(collection.Keys); + keyCollection = new System.Collections.Generic.List<$typemap(cstype, K)>(collection.Keys); currentIndex = -1; currentObject = null; currentSize = collectionRef.Count; } // Type-safe iterator Current - public System.Collections.Generic.KeyValuePair Current { + public System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> Current { get { if (currentIndex == -1) throw new InvalidOperationException("Enumeration not started."); @@ -239,7 +172,7 @@ throw new InvalidOperationException("Enumeration finished."); if (currentObject == null) throw new InvalidOperationException("Collection modified."); - return (System.Collections.Generic.KeyValuePair)currentObject; + return (System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>)currentObject; } } @@ -255,8 +188,8 @@ bool moveOkay = (currentIndex+1 < size) && (size == currentSize); if (moveOkay) { currentIndex++; - CSKEYTYPE currentKey = keyCollection[currentIndex]; - currentObject = new System.Collections.Generic.KeyValuePair(currentKey, collectionRef[currentKey]); + $typemap(cstype, K) currentKey = keyCollection[currentIndex]; + currentObject = new System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>(currentKey, collectionRef[currentKey]); } else { currentObject = null; } @@ -282,7 +215,7 @@ public: map(); - map(const map &other); + map(const map< K, T > &other); typedef K key_type; typedef T mapped_type; @@ -293,7 +226,7 @@ void clear(); %extend { const mapped_type& getitem(const key_type& key) throw (std::out_of_range) { - std::map::iterator iter = $self->find(key); + std::map< K,T >::iterator iter = $self->find(key); if (iter != $self->end()) return iter->second; else @@ -305,19 +238,19 @@ } bool ContainsKey(const key_type& key) { - std::map::iterator iter = $self->find(key); + std::map< K, T >::iterator iter = $self->find(key); return iter != $self->end(); } void Add(const key_type& key, const mapped_type& val) throw (std::out_of_range) { - std::map::iterator iter = $self->find(key); + std::map< K, T >::iterator iter = $self->find(key); if (iter != $self->end()) throw std::out_of_range("key already exists"); - $self->insert(std::pair(key, val)); + $self->insert(std::pair< K, T >(key, val)); } bool Remove(const key_type& key) { - std::map::iterator iter = $self->find(key); + std::map< K, T >::iterator iter = $self->find(key); if (iter != $self->end()) { $self->erase(iter); return true; @@ -326,15 +259,15 @@ } // create_iterator_begin() and get_next_key() work together to provide a collection of keys to C# - %apply void *VOID_INT_PTR { std::map::iterator *std::map::create_iterator_begin } - %apply void *VOID_INT_PTR { std::map::iterator *swigiterator } + %apply void *VOID_INT_PTR { std::map< K, T >::iterator *create_iterator_begin } + %apply void *VOID_INT_PTR { std::map< K, T >::iterator *swigiterator } - std::map::iterator *create_iterator_begin() { - return new std::map::iterator($self->begin()); + std::map< K, T >::iterator *create_iterator_begin() { + return new std::map< K, T >::iterator($self->begin()); } - const key_type& get_next_key(std::map::iterator *swigiterator) throw (std::out_of_range) { - std::map::iterator iter = *swigiterator; + const key_type& get_next_key(std::map< K, T >::iterator *swigiterator) throw (std::out_of_range) { + std::map< K, T >::iterator iter = *swigiterator; if (iter == $self->end()) { delete swigiterator; throw std::out_of_range("no more map elements"); @@ -345,275 +278,32 @@ } -%csmethodmodifiers std::map::size "private" -%csmethodmodifiers std::map::getitem "private" -%csmethodmodifiers std::map::setitem "private" -%csmethodmodifiers std::map::create_iterator_begin "private" -%csmethodmodifiers std::map::get_next_key "private" - %enddef - -// Main specialization macros -%define SWIG_STD_MAP_SPECIALIZED(K, T, CSKEY, CSVAL) -namespace std { - template<> class map { - SWIG_STD_MAP_SPECIALIZED_INTERNAL(K, T, CSKEY, CSVAL) - }; -} -%enddef - -%define SWIG_STD_MAP_SPECIALIZED_SIMPLE(K, T) - SWIG_STD_MAP_SPECIALIZED(K, T, K, T) -%enddef - -// Old macros (deprecated) -%define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) -#warning specialize_std_map_on_key ignored - macro is deprecated, please use SWIG_STD_MAP_MINIMAL_INTERNAL in Lib/csharp/std_map.i -%enddef - -%define specialize_std_map_on_value(T,CHECK,CONVERT_FROM,CONVERT_TO) -#warning specialize_std_map_on_value ignored - macro is deprecated, please use SWIG_STD_MAP_MINIMAL_INTERNAL in Lib/csharp/std_map.i -%enddef - -%define specialize_std_map_on_both(K,CHECK_K,CONVERT_K_FROM,CONVERT_K_TO, T,CHECK_T,CONVERT_T_FROM,CONVERT_T_TO) -#warning specialize_std_map_on_both ignored - macro is deprecated, please use SWIG_STD_MAP_MINIMAL_INTERNAL in Lib/csharp/std_map.i -%enddef +%csmethodmodifiers std::map::size "private" +%csmethodmodifiers std::map::getitem "private" +%csmethodmodifiers std::map::setitem "private" +%csmethodmodifiers std::map::create_iterator_begin "private" +%csmethodmodifiers std::map::get_next_key "private" // Default implementation namespace std { template class map { - SWIG_STD_MAP_MINIMAL_INTERNAL(K, T) + SWIG_STD_MAP_INTERNAL(K, T) }; } -// specializations for built-ins -SWIG_STD_MAP_SPECIALIZED(std::string, std::string, string, string) -SWIG_STD_MAP_SPECIALIZED(std::string, bool, string, bool) -SWIG_STD_MAP_SPECIALIZED(std::string, int, string, int) -SWIG_STD_MAP_SPECIALIZED(std::string, unsigned long long, string, ulong) -SWIG_STD_MAP_SPECIALIZED(std::string, unsigned long, string, uint) -SWIG_STD_MAP_SPECIALIZED(std::string, unsigned short, string, ushort) -SWIG_STD_MAP_SPECIALIZED(std::string, long long, string, long) -SWIG_STD_MAP_SPECIALIZED(std::string, unsigned int, string, uint) -SWIG_STD_MAP_SPECIALIZED(std::string, unsigned char, string, byte) -SWIG_STD_MAP_SPECIALIZED(std::string, signed char, string, sbyte) -SWIG_STD_MAP_SPECIALIZED(std::string, double, string, double) -SWIG_STD_MAP_SPECIALIZED(std::string, short, string, short) -SWIG_STD_MAP_SPECIALIZED(std::string, float, string, float) -SWIG_STD_MAP_SPECIALIZED(std::string, char, string, char) -SWIG_STD_MAP_SPECIALIZED(std::string, long, string, int) -SWIG_STD_MAP_SPECIALIZED(bool, std::string, bool, string) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(bool, bool) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(bool, int) -SWIG_STD_MAP_SPECIALIZED(bool, unsigned long long, bool, ulong) -SWIG_STD_MAP_SPECIALIZED(bool, unsigned long, bool, uint) -SWIG_STD_MAP_SPECIALIZED(bool, unsigned short, bool, ushort) -SWIG_STD_MAP_SPECIALIZED(bool, long long, bool, long) -SWIG_STD_MAP_SPECIALIZED(bool, unsigned int, bool, uint) -SWIG_STD_MAP_SPECIALIZED(bool, unsigned char, bool, byte) -SWIG_STD_MAP_SPECIALIZED(bool, signed char, bool, sbyte) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(bool, double) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(bool, short) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(bool, float) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(bool, char) -SWIG_STD_MAP_SPECIALIZED(bool, long, bool, int) -SWIG_STD_MAP_SPECIALIZED(int, std::string, int, string) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(int, bool) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(int, int) -SWIG_STD_MAP_SPECIALIZED(int, unsigned long long, int, ulong) -SWIG_STD_MAP_SPECIALIZED(int, unsigned long, int, uint) -SWIG_STD_MAP_SPECIALIZED(int, unsigned short, int, ushort) -SWIG_STD_MAP_SPECIALIZED(int, long long, int, long) -SWIG_STD_MAP_SPECIALIZED(int, unsigned int, int, uint) -SWIG_STD_MAP_SPECIALIZED(int, unsigned char, int, byte) -SWIG_STD_MAP_SPECIALIZED(int, signed char, int, sbyte) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(int, double) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(int, short) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(int, float) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(int, char) -SWIG_STD_MAP_SPECIALIZED(int, long, int, int) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, std::string, ulong, string) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, bool, ulong, bool) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, int, ulong, int) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, unsigned long long, ulong, ulong) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, unsigned long, ulong, uint) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, unsigned short, ulong, ushort) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, long long, ulong, long) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, unsigned int, ulong, uint) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, unsigned char, ulong, byte) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, signed char, ulong, sbyte) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, double, ulong, double) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, short, ulong, short) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, float, ulong, float) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, char, ulong, char) -SWIG_STD_MAP_SPECIALIZED(unsigned long long, long, ulong, int) -SWIG_STD_MAP_SPECIALIZED(unsigned long, std::string, uint, string) -SWIG_STD_MAP_SPECIALIZED(unsigned long, bool, uint, bool) -SWIG_STD_MAP_SPECIALIZED(unsigned long, int, uint, int) -SWIG_STD_MAP_SPECIALIZED(unsigned long, unsigned long long, uint, ulong) -SWIG_STD_MAP_SPECIALIZED(unsigned long, unsigned long, uint, uint) -SWIG_STD_MAP_SPECIALIZED(unsigned long, unsigned short, uint, ushort) -SWIG_STD_MAP_SPECIALIZED(unsigned long, long long, uint, long) -SWIG_STD_MAP_SPECIALIZED(unsigned long, unsigned int, uint, uint) -SWIG_STD_MAP_SPECIALIZED(unsigned long, unsigned char, uint, byte) -SWIG_STD_MAP_SPECIALIZED(unsigned long, signed char, uint, sbyte) -SWIG_STD_MAP_SPECIALIZED(unsigned long, double, uint, double) -SWIG_STD_MAP_SPECIALIZED(unsigned long, short, uint, short) -SWIG_STD_MAP_SPECIALIZED(unsigned long, float, uint, float) -SWIG_STD_MAP_SPECIALIZED(unsigned long, char, uint, char) -SWIG_STD_MAP_SPECIALIZED(unsigned long, long, uint, int) -SWIG_STD_MAP_SPECIALIZED(unsigned short, std::string, ushort, string) -SWIG_STD_MAP_SPECIALIZED(unsigned short, bool, ushort, bool) -SWIG_STD_MAP_SPECIALIZED(unsigned short, int, ushort, int) -SWIG_STD_MAP_SPECIALIZED(unsigned short, unsigned long long, ushort, ulong) -SWIG_STD_MAP_SPECIALIZED(unsigned short, unsigned long, ushort, uint) -SWIG_STD_MAP_SPECIALIZED(unsigned short, unsigned short, ushort, ushort) -SWIG_STD_MAP_SPECIALIZED(unsigned short, long long, ushort, long) -SWIG_STD_MAP_SPECIALIZED(unsigned short, unsigned int, ushort, uint) -SWIG_STD_MAP_SPECIALIZED(unsigned short, unsigned char, ushort, byte) -SWIG_STD_MAP_SPECIALIZED(unsigned short, signed char, ushort, sbyte) -SWIG_STD_MAP_SPECIALIZED(unsigned short, double, ushort, double) -SWIG_STD_MAP_SPECIALIZED(unsigned short, short, ushort, short) -SWIG_STD_MAP_SPECIALIZED(unsigned short, float, ushort, float) -SWIG_STD_MAP_SPECIALIZED(unsigned short, char, ushort, char) -SWIG_STD_MAP_SPECIALIZED(unsigned short, long, ushort, int) -SWIG_STD_MAP_SPECIALIZED(long long, std::string, long, string) -SWIG_STD_MAP_SPECIALIZED(long long, bool, long, bool) -SWIG_STD_MAP_SPECIALIZED(long long, int, long, int) -SWIG_STD_MAP_SPECIALIZED(long long, unsigned long long, long, ulong) -SWIG_STD_MAP_SPECIALIZED(long long, unsigned long, long, uint) -SWIG_STD_MAP_SPECIALIZED(long long, unsigned short, long, ushort) -SWIG_STD_MAP_SPECIALIZED(long long, long long, long, long) -SWIG_STD_MAP_SPECIALIZED(long long, unsigned int, long, uint) -SWIG_STD_MAP_SPECIALIZED(long long, unsigned char, long, byte) -SWIG_STD_MAP_SPECIALIZED(long long, signed char, long, sbyte) -SWIG_STD_MAP_SPECIALIZED(long long, double, long, double) -SWIG_STD_MAP_SPECIALIZED(long long, short, long, short) -SWIG_STD_MAP_SPECIALIZED(long long, float, long, float) -SWIG_STD_MAP_SPECIALIZED(long long, char, long, char) -SWIG_STD_MAP_SPECIALIZED(long long, long, long, int) -SWIG_STD_MAP_SPECIALIZED(unsigned int, std::string, uint, string) -SWIG_STD_MAP_SPECIALIZED(unsigned int, bool, uint, bool) -SWIG_STD_MAP_SPECIALIZED(unsigned int, int, uint, int) -SWIG_STD_MAP_SPECIALIZED(unsigned int, unsigned long long, uint, ulong) -SWIG_STD_MAP_SPECIALIZED(unsigned int, unsigned long, uint, uint) -SWIG_STD_MAP_SPECIALIZED(unsigned int, unsigned short, uint, ushort) -SWIG_STD_MAP_SPECIALIZED(unsigned int, long long, uint, long) -SWIG_STD_MAP_SPECIALIZED(unsigned int, unsigned int, uint, uint) -SWIG_STD_MAP_SPECIALIZED(unsigned int, unsigned char, uint, byte) -SWIG_STD_MAP_SPECIALIZED(unsigned int, signed char, uint, sbyte) -SWIG_STD_MAP_SPECIALIZED(unsigned int, double, uint, double) -SWIG_STD_MAP_SPECIALIZED(unsigned int, short, uint, short) -SWIG_STD_MAP_SPECIALIZED(unsigned int, float, uint, float) -SWIG_STD_MAP_SPECIALIZED(unsigned int, char, uint, char) -SWIG_STD_MAP_SPECIALIZED(unsigned int, long, uint, int) -SWIG_STD_MAP_SPECIALIZED(unsigned char, std::string, byte, string) -SWIG_STD_MAP_SPECIALIZED(unsigned char, bool, byte, bool) -SWIG_STD_MAP_SPECIALIZED(unsigned char, int, byte, int) -SWIG_STD_MAP_SPECIALIZED(unsigned char, unsigned long long, byte, ulong) -SWIG_STD_MAP_SPECIALIZED(unsigned char, unsigned long, byte, uint) -SWIG_STD_MAP_SPECIALIZED(unsigned char, unsigned short, byte, ushort) -SWIG_STD_MAP_SPECIALIZED(unsigned char, long long, byte, long) -SWIG_STD_MAP_SPECIALIZED(unsigned char, unsigned int, byte, uint) -SWIG_STD_MAP_SPECIALIZED(unsigned char, unsigned char, byte, byte) -SWIG_STD_MAP_SPECIALIZED(unsigned char, signed char, byte, sbyte) -SWIG_STD_MAP_SPECIALIZED(unsigned char, double, byte, double) -SWIG_STD_MAP_SPECIALIZED(unsigned char, short, byte, short) -SWIG_STD_MAP_SPECIALIZED(unsigned char, float, byte, float) -SWIG_STD_MAP_SPECIALIZED(unsigned char, char, byte, char) -SWIG_STD_MAP_SPECIALIZED(unsigned char, long, byte, int) -SWIG_STD_MAP_SPECIALIZED(signed char, std::string, sbyte, string) -SWIG_STD_MAP_SPECIALIZED(signed char, bool, sbyte, bool) -SWIG_STD_MAP_SPECIALIZED(signed char, int, sbyte, int) -SWIG_STD_MAP_SPECIALIZED(signed char, unsigned long long, sbyte, ulong) -SWIG_STD_MAP_SPECIALIZED(signed char, unsigned long, sbyte, uint) -SWIG_STD_MAP_SPECIALIZED(signed char, unsigned short, sbyte, ushort) -SWIG_STD_MAP_SPECIALIZED(signed char, long long, sbyte, long) -SWIG_STD_MAP_SPECIALIZED(signed char, unsigned int, sbyte, uint) -SWIG_STD_MAP_SPECIALIZED(signed char, unsigned char, sbyte, byte) -SWIG_STD_MAP_SPECIALIZED(signed char, signed char, sbyte, sbyte) -SWIG_STD_MAP_SPECIALIZED(signed char, double, sbyte, double) -SWIG_STD_MAP_SPECIALIZED(signed char, short, sbyte, short) -SWIG_STD_MAP_SPECIALIZED(signed char, float, sbyte, float) -SWIG_STD_MAP_SPECIALIZED(signed char, char, sbyte, char) -SWIG_STD_MAP_SPECIALIZED(signed char, long, sbyte, int) -SWIG_STD_MAP_SPECIALIZED(double, std::string, double, string) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(double, bool) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(double, int) -SWIG_STD_MAP_SPECIALIZED(double, unsigned long long, double, ulong) -SWIG_STD_MAP_SPECIALIZED(double, unsigned long, double, uint) -SWIG_STD_MAP_SPECIALIZED(double, unsigned short, double, ushort) -SWIG_STD_MAP_SPECIALIZED(double, long long, double, long) -SWIG_STD_MAP_SPECIALIZED(double, unsigned int, double, uint) -SWIG_STD_MAP_SPECIALIZED(double, unsigned char, double, byte) -SWIG_STD_MAP_SPECIALIZED(double, signed char, double, sbyte) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(double, double) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(double, short) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(double, float) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(double, char) -SWIG_STD_MAP_SPECIALIZED(double, long, double, int) -SWIG_STD_MAP_SPECIALIZED(short, std::string, short, string) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(short, bool) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(short, int) -SWIG_STD_MAP_SPECIALIZED(short, unsigned long long, short, ulong) -SWIG_STD_MAP_SPECIALIZED(short, unsigned long, short, uint) -SWIG_STD_MAP_SPECIALIZED(short, unsigned short, short, ushort) -SWIG_STD_MAP_SPECIALIZED(short, long long, short, long) -SWIG_STD_MAP_SPECIALIZED(short, unsigned int, short, uint) -SWIG_STD_MAP_SPECIALIZED(short, unsigned char, short, byte) -SWIG_STD_MAP_SPECIALIZED(short, signed char, short, sbyte) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(short, double) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(short, short) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(short, float) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(short, char) -SWIG_STD_MAP_SPECIALIZED(short, long, short, int) -SWIG_STD_MAP_SPECIALIZED(float, std::string, float, string) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(float, bool) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(float, int) -SWIG_STD_MAP_SPECIALIZED(float, unsigned long long, float, ulong) -SWIG_STD_MAP_SPECIALIZED(float, unsigned long, float, uint) -SWIG_STD_MAP_SPECIALIZED(float, unsigned short, float, ushort) -SWIG_STD_MAP_SPECIALIZED(float, long long, float, long) -SWIG_STD_MAP_SPECIALIZED(float, unsigned int, float, uint) -SWIG_STD_MAP_SPECIALIZED(float, unsigned char, float, byte) -SWIG_STD_MAP_SPECIALIZED(float, signed char, float, sbyte) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(float, double) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(float, short) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(float, float) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(float, char) -SWIG_STD_MAP_SPECIALIZED(float, long, float, int) -SWIG_STD_MAP_SPECIALIZED(char, std::string, char, string) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(char, bool) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(char, int) -SWIG_STD_MAP_SPECIALIZED(char, unsigned long long, char, ulong) -SWIG_STD_MAP_SPECIALIZED(char, unsigned long, char, uint) -SWIG_STD_MAP_SPECIALIZED(char, unsigned short, char, ushort) -SWIG_STD_MAP_SPECIALIZED(char, long long, char, long) -SWIG_STD_MAP_SPECIALIZED(char, unsigned int, char, uint) -SWIG_STD_MAP_SPECIALIZED(char, unsigned char, char, byte) -SWIG_STD_MAP_SPECIALIZED(char, signed char, char, sbyte) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(char, double) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(char, short) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(char, float) -SWIG_STD_MAP_SPECIALIZED_SIMPLE(char, char) -SWIG_STD_MAP_SPECIALIZED(char, long, char, int) -SWIG_STD_MAP_SPECIALIZED(long, std::string, int, string) -SWIG_STD_MAP_SPECIALIZED(long, bool, int, bool) -SWIG_STD_MAP_SPECIALIZED(long, int, int, int) -SWIG_STD_MAP_SPECIALIZED(long, unsigned long long, int, ulong) -SWIG_STD_MAP_SPECIALIZED(long, unsigned long, int, uint) -SWIG_STD_MAP_SPECIALIZED(long, unsigned short, int, ushort) -SWIG_STD_MAP_SPECIALIZED(long, long long, int, long) -SWIG_STD_MAP_SPECIALIZED(long, unsigned int, int, uint) -SWIG_STD_MAP_SPECIALIZED(long, unsigned char, int, byte) -SWIG_STD_MAP_SPECIALIZED(long, signed char, int, sbyte) -SWIG_STD_MAP_SPECIALIZED(long, double, int, double) -SWIG_STD_MAP_SPECIALIZED(long, short, int, short) -SWIG_STD_MAP_SPECIALIZED(long, float, int, float) -SWIG_STD_MAP_SPECIALIZED(long, char, int, char) -SWIG_STD_MAP_SPECIALIZED(long, long, int, int) -// add specializations here +// Legacy macros (deprecated) +%define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) +#warning specialize_std_map_on_key ignored - macro is deprecated and no longer necessary +%enddef +%define specialize_std_map_on_value(T,CHECK,CONVERT_FROM,CONVERT_TO) +#warning specialize_std_map_on_value ignored - macro is deprecated and no longer necessary +%enddef + +%define specialize_std_map_on_both(K,CHECK_K,CONVERT_K_FROM,CONVERT_K_TO, T,CHECK_T,CONVERT_T_FROM,CONVERT_T_TO) +#warning specialize_std_map_on_both ignored - macro is deprecated and no longer necessary +%enddef diff --git a/Lib/csharp/std_vector.i b/Lib/csharp/std_vector.i index 673cced89..57abe614d 100644 --- a/Lib/csharp/std_vector.i +++ b/Lib/csharp/std_vector.i @@ -1,23 +1,20 @@ /* ----------------------------------------------------------------------------- * std_vector.i * - * SWIG typemaps for std::vector + * SWIG typemaps for std::vector * C# implementation * The C# wrapper is made to look and feel like a C# System.Collections.Generic.List<> collection. * For .NET 1 compatibility, define SWIG_DOTNET_1 when compiling the C# code; then the C# wrapper is - * made to look and feel like a typesafe C# System.Collections.ArrayList. All the methods in IList - * are defined, but we don't derive from IList as this is a typesafe collection and the C++ operator== - * must always be defined for the collection type (which it isn't). - * - * Very often the C# generated code will not compile as the C++ template type is not the same as the C# - * proxy type, so use the SWIG_STD_VECTOR_SPECIALIZE or SWIG_STD_VECTOR_SPECIALIZE_MINIMUM macro, eg - * - * SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(Klass, SomeNamespace::Klass) - * %template(VectKlass) std::vector; + * made to look and feel like a typesafe C# System.Collections.ArrayList. * * Note that IEnumerable<> is implemented in the proxy class which is useful for using LINQ with - * C++ std::vector wrappers. IEnumerable<> is replaced by IList<> wherever we are confident that the - * required C++ operator== is available for correct compilation. + * C++ std::vector wrappers. The IList<> interface is also implemented to provide enhanced functionality + * whenever we are confident that the required C++ operator== is available. This is the case for when + * T is a primitive type or a pointer. If T does define an operator==, then use the SWIG_STD_VECTOR_ENHANCED + * macro to obtain this enhanced functionality, for example: + * + * SWIG_STD_VECTOR_ENHANCED(SomeNamespace::Klass) + * %template(VectKlass) std::vector; * * Warning: heavy macro usage in this file. Use swig -E to get a sane view on the real file contents! * ----------------------------------------------------------------------------- */ @@ -28,14 +25,13 @@ %include // MACRO for use within the std::vector class body -// CSTYPE and CTYPE respectively correspond to the types in the cstype and ctype typemaps -%define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CSINTERFACE, CONST_REFERENCE_TYPE, CSTYPE, CTYPE...) -%typemap(csinterfaces) std::vector "IDisposable, System.Collections.IEnumerable\n#if !SWIG_DOTNET_1\n , System.Collections.Generic.CSINTERFACE\n#endif\n"; +%define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CSINTERFACE, CONST_REFERENCE_TYPE, CTYPE...) +%typemap(csinterfaces) std::vector "IDisposable, System.Collections.IEnumerable\n#if !SWIG_DOTNET_1\n , System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n#endif\n"; %typemap(cscode) std::vector %{ public $csclassname(System.Collections.ICollection c) : this() { if (c == null) throw new ArgumentNullException("c"); - foreach (CSTYPE element in c) { + foreach ($typemap(cstype, CTYPE) element in c) { this.Add(element); } } @@ -52,7 +48,7 @@ } } - public CSTYPE this[int index] { + public $typemap(cstype, CTYPE) this[int index] { get { return getitem(index); } @@ -87,7 +83,7 @@ #if SWIG_DOTNET_1 public void CopyTo(System.Array array) #else - public void CopyTo(CSTYPE[] array) + public void CopyTo($typemap(cstype, CTYPE)[] array) #endif { CopyTo(0, array, 0, this.Count); @@ -96,7 +92,7 @@ #if SWIG_DOTNET_1 public void CopyTo(System.Array array, int arrayIndex) #else - public void CopyTo(CSTYPE[] array, int arrayIndex) + public void CopyTo($typemap(cstype, CTYPE)[] array, int arrayIndex) #endif { CopyTo(0, array, arrayIndex, this.Count); @@ -105,7 +101,7 @@ #if SWIG_DOTNET_1 public void CopyTo(int index, System.Array array, int arrayIndex, int count) #else - public void CopyTo(int index, CSTYPE[] array, int arrayIndex, int count) + public void CopyTo(int index, $typemap(cstype, CTYPE)[] array, int arrayIndex, int count) #endif { if (array == null) @@ -125,7 +121,7 @@ } #if !SWIG_DOTNET_1 - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { + System.Collections.Generic.IEnumerator<$typemap(cstype, CTYPE)> System.Collections.Generic.IEnumerable<$typemap(cstype, CTYPE)>.GetEnumerator() { return new $csclassnameEnumerator(this); } #endif @@ -145,7 +141,7 @@ /// tricky to detect unmanaged code that modifies the collection under our feet. public sealed class $csclassnameEnumerator : System.Collections.IEnumerator #if !SWIG_DOTNET_1 - , System.Collections.Generic.IEnumerator + , System.Collections.Generic.IEnumerator<$typemap(cstype, CTYPE)> #endif { private $csclassname collectionRef; @@ -161,7 +157,7 @@ } // Type-safe iterator Current - public CSTYPE Current { + public $typemap(cstype, CTYPE) Current { get { if (currentIndex == -1) throw new InvalidOperationException("Enumeration not started."); @@ -169,7 +165,7 @@ throw new InvalidOperationException("Enumeration finished."); if (currentObject == null) throw new InvalidOperationException("Collection modified."); - return (CSTYPE)currentObject; + return ($typemap(cstype, CTYPE))currentObject; } } @@ -323,14 +319,13 @@ } %enddef -%define SWIG_STD_VECTOR_MINIMUM(CSTYPE, CTYPE...) -SWIG_STD_VECTOR_MINIMUM_INTERNAL(IEnumerable, const value_type&, CSTYPE, CTYPE) +%define SWIG_STD_VECTOR_MINIMUM(CTYPE...) +SWIG_STD_VECTOR_MINIMUM_INTERNAL(IEnumerable, const value_type&, CTYPE) %enddef // Extra methods added to the collection class if operator== is defined for the class being wrapped -// CSTYPE and CTYPE respectively correspond to the types in the cstype and ctype typemaps // The class will then implement IList<>, which adds extra functionality -%define SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CSTYPE, CTYPE...) +%define SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CTYPE...) %extend { bool Contains(const value_type& value) { return std::find($self->begin(), $self->end(), value) != $self->end(); @@ -360,23 +355,24 @@ SWIG_STD_VECTOR_MINIMUM_INTERNAL(IEnumerable, const value_type&, CSTYPE, CTYPE) } %enddef -// Macros for std::vector class specializations -// CSTYPE and CTYPE respectively correspond to the types in the cstype and ctype typemaps -%define SWIG_STD_VECTOR_SPECIALIZE(CSTYPE, CTYPE...) +// Macros for std::vector class specializations/enhancements +%define SWIG_STD_VECTOR_ENHANCED(CTYPE...) namespace std { template<> class vector { - SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, const value_type&, CSTYPE, CTYPE) - SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CSTYPE, CTYPE) + SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, const value_type&, CTYPE) + SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CTYPE) }; } %enddef +// Legacy macros +%define SWIG_STD_VECTOR_SPECIALIZE(CSTYPE, CTYPE...) +#warning SWIG_STD_VECTOR_SPECIALIZE macro deprecated, please see csharp/std_vector.i and switch to SWIG_STD_VECTOR_ENHANCED +SWIG_STD_VECTOR_ENHANCED(CTYPE) +%enddef + %define SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(CSTYPE, CTYPE...) -namespace std { - template<> class vector { - SWIG_STD_VECTOR_MINIMUM(CSTYPE, CTYPE) - }; -} +#warning SWIG_STD_VECTOR_SPECIALIZE_MINIMUM macro deprecated, it is no longer required %enddef %{ @@ -396,36 +392,38 @@ namespace std { // primary (unspecialized) class template for std::vector // does not require operator== to be defined template class vector { - SWIG_STD_VECTOR_MINIMUM(T, T) + SWIG_STD_VECTOR_MINIMUM(T) }; // specializations for pointers template class vector { - SWIG_STD_VECTOR_MINIMUM(T, T*) + SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, const value_type&, T*) + SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(T*) }; template class vector { - SWIG_STD_VECTOR_MINIMUM(T, const T*) + SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, const value_type&, const T*) + SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(const T*) }; // bool is a bit different in the C++ standard template<> class vector { - SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, bool, bool, bool) - SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(bool, bool) + SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, bool, bool) + SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(bool) }; } // template specializations for std::vector // these provide extra collections methods as operator== is defined -SWIG_STD_VECTOR_SPECIALIZE(char, char) -SWIG_STD_VECTOR_SPECIALIZE(sbyte, signed char) -SWIG_STD_VECTOR_SPECIALIZE(byte, unsigned char) -SWIG_STD_VECTOR_SPECIALIZE(short, short) -SWIG_STD_VECTOR_SPECIALIZE(ushort, unsigned short) -SWIG_STD_VECTOR_SPECIALIZE(int, int) -SWIG_STD_VECTOR_SPECIALIZE(uint, unsigned int) -SWIG_STD_VECTOR_SPECIALIZE(int, long) -SWIG_STD_VECTOR_SPECIALIZE(uint, unsigned long) -SWIG_STD_VECTOR_SPECIALIZE(long, long long) -SWIG_STD_VECTOR_SPECIALIZE(ulong, unsigned long long) -SWIG_STD_VECTOR_SPECIALIZE(float, float) -SWIG_STD_VECTOR_SPECIALIZE(double, double) -SWIG_STD_VECTOR_SPECIALIZE(string, std::string) // also requires a %include +SWIG_STD_VECTOR_ENHANCED(char) +SWIG_STD_VECTOR_ENHANCED(signed char) +SWIG_STD_VECTOR_ENHANCED(unsigned char) +SWIG_STD_VECTOR_ENHANCED(short) +SWIG_STD_VECTOR_ENHANCED(unsigned short) +SWIG_STD_VECTOR_ENHANCED(int) +SWIG_STD_VECTOR_ENHANCED(unsigned int) +SWIG_STD_VECTOR_ENHANCED(long) +SWIG_STD_VECTOR_ENHANCED(unsigned long) +SWIG_STD_VECTOR_ENHANCED(long long) +SWIG_STD_VECTOR_ENHANCED(unsigned long long) +SWIG_STD_VECTOR_ENHANCED(float) +SWIG_STD_VECTOR_ENHANCED(double) +SWIG_STD_VECTOR_ENHANCED(std::string) // also requires a %include diff --git a/Lib/exception.i b/Lib/exception.i index 7297a77f5..2bc86b458 100644 --- a/Lib/exception.i +++ b/Lib/exception.i @@ -259,9 +259,15 @@ SWIGINTERN void SWIG_CSharpException(int code, const char *msg) { /* rethrow the unknown exception */ +#ifdef SWIGCSHARP +%typemap(throws,noblock=1, canthrow=1) (...) { + SWIG_exception(SWIG_RuntimeError,"unknown exception"); +} +#else %typemap(throws,noblock=1) (...) { SWIG_exception(SWIG_RuntimeError,"unknown exception"); } +#endif #endif /* __cplusplus */ diff --git a/Lib/java/boost_intrusive_ptr.i b/Lib/java/boost_intrusive_ptr.i index 48f6c317b..9b9e1755f 100644 --- a/Lib/java/boost_intrusive_ptr.i +++ b/Lib/java/boost_intrusive_ptr.i @@ -1,13 +1,16 @@ %include +// Language specific macro implementing all the customisations for handling the smart pointer %define SWIG_INTRUSIVE_PTR_TYPEMAPS(PROXYCLASS, CONST, TYPE...) +// %naturalvar is as documented for member variables %naturalvar TYPE; %naturalvar SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >; -// destructor mods +// destructor wrapper customisation %feature("unref") TYPE "(void)arg1; delete smartarg1;" +// Typemap customisations... %typemap(in) CONST TYPE ($&1_type argp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ // plain value diff --git a/Lib/java/boost_shared_ptr.i b/Lib/java/boost_shared_ptr.i index 75762f84f..38262f20c 100644 --- a/Lib/java/boost_shared_ptr.i +++ b/Lib/java/boost_shared_ptr.i @@ -1,15 +1,18 @@ %include +// Language specific macro implementing all the customisations for handling the smart pointer %define SWIG_SHARED_PTR_TYPEMAPS(PROXYCLASS, CONST, TYPE...) +// %naturalvar is as documented for member variables %naturalvar TYPE; %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; -// destructor mods +// destructor wrapper customisation %feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" +// Typemap customisations... // plain value %typemap(in) CONST TYPE ($&1_type argp = 0) %{ diff --git a/Lib/lua/luarun.swg b/Lib/lua/luarun.swg index 4c9aa5144..b4e979531 100644 --- a/Lib/lua/luarun.swg +++ b/Lib/lua/luarun.swg @@ -76,7 +76,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/boost_shared_ptr.i b/Lib/octave/boost_shared_ptr.i index 7ae4dda9f..2a3c1532f 100644 --- a/Lib/octave/boost_shared_ptr.i +++ b/Lib/octave/boost_shared_ptr.i @@ -1,17 +1,22 @@ %include +// Language specific macro implementing all the customisations for handling the smart pointer %define SWIG_SHARED_PTR_TYPEMAPS(PROXYCLASS, CONST, TYPE...) +// %naturalvar is as documented for member variables %naturalvar TYPE; %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; -// destructor mods +// destructor wrapper customisation %feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" +// Feature to adapt the code generated in the swigregister functions for smart pointers %feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > } +// Typemap customisations... + // plain value %typemap(in) CONST TYPE (void *argp, int res = 0) { int newmem = 0; diff --git a/Lib/octave/octrun.swg b/Lib/octave/octrun.swg index c48310e27..be2dc9653 100644 --- a/Lib/octave/octrun.swg +++ b/Lib/octave/octrun.swg @@ -1,4 +1,18 @@ +#include +#ifndef OCTAVE_API_VERSION_NUMBER + + // 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 SWIGRUNTIME bool SWIG_check_num_args(const char *func_name, int num_args, int max_args, int min_args, int varargs) { if (num_args > max_args && !varargs) @@ -105,27 +119,35 @@ namespace Swig { typedef std::map < void *, Director * > rtdir_map; - SWIGINTERN rtdir_map &get_rtdir_map() { + SWIGINTERN rtdir_map* get_rtdir_map() { static swig_module_info *module = 0; if (!module) module = SWIG_GetModule(0); - assert(module); + if (!module) + return 0; if (!module->clientdata) module->clientdata = new rtdir_map; - return *(rtdir_map *) module->clientdata; + return (rtdir_map *) module->clientdata; } SWIGINTERNINLINE void set_rtdir(void *vptr, Director *d) { - get_rtdir_map()[vptr] = d; + rtdir_map* rm = get_rtdir_map(); + if (rm) + (*rm)[vptr] = d; } SWIGINTERNINLINE void erase_rtdir(void *vptr) { - get_rtdir_map().erase(vptr); + rtdir_map* rm = get_rtdir_map(); + if (rm) + (*rm).erase(vptr); } SWIGINTERNINLINE Director *get_rtdir(void *vptr) { - rtdir_map::const_iterator pos = get_rtdir_map().find(vptr); - Director *rtdir = (pos != get_rtdir_map().end())? pos->second : 0; + rtdir_map* rm = get_rtdir_map(); + if (!rm) + return 0; + rtdir_map::const_iterator pos = rm->find(vptr); + Director *rtdir = (pos != rm->end())? pos->second : 0; return rtdir; } } @@ -439,9 +461,15 @@ 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 OCTAVE_API_VERSION_NUMBER<37 link_to_global_variable(curr_sym_tab->lookup(it->first, true)); +#else + symbol_table::varref(it->first); + symbol_table::mark_global(it->first); +#endif set_global_value(it->first, it->second.second); +#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(); @@ -450,6 +478,7 @@ namespace Swig { sr->document(h); } } +#endif } } } @@ -1352,6 +1381,11 @@ 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 OCTAVE_API_VERSION_NUMBER<37 link_to_global_variable(curr_sym_tab->lookup(module_var, true)); +#else + symbol_table::varref(module_var); + symbol_table::mark_global(module_var); +#endif set_global_value(module_var, ov); } diff --git a/Lib/octave/octruntime.swg b/Lib/octave/octruntime.swg index 82a17285a..e19b781c2 100644 --- a/Lib/octave/octruntime.swg +++ b/Lib/octave/octruntime.swg @@ -72,11 +72,33 @@ DEFUN_DLD (SWIG_name,args,nargout,SWIG_name_d) { module_ns->install_global(); module_ns->decref(); +#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); + symbol_table::mark_global(SWIG_name_d); +#endif set_global_value(SWIG_name_d,Swig::swig_value_ref(module_ns)); +#if OCTAVE_API_VERSION_NUMBER>=37 + mlock(); +#endif + return octave_value_list(); } +// workaround bug in octave where installing global variable of custom type and then +// exiting without explicitly clearing the variable causes octave to segfault. +#if OCTAVE_API_VERSION_NUMBER>=37 +struct oct_file_unload { + ~oct_file_unload() { + string_vector vars = symbol_table::global_variable_names(); + for (int i = 0; i < vars.length(); i++) + symbol_table::clear_global(vars[i]); + } +}; +static oct_file_unload __unload; +#endif + %} diff --git a/Lib/octave/octtypemaps.swg b/Lib/octave/octtypemaps.swg index 7934f90bd..26a52197f 100644 --- a/Lib/octave/octtypemaps.swg +++ b/Lib/octave/octtypemaps.swg @@ -32,7 +32,7 @@ #define SWIG_SetConstant(name, obj) SWIG_Octave_SetConstant(module_ns,name,obj) // raise -#define SWIG_Octave_Raise(obj, type, desc) error("c++-side threw an exception") +#define SWIG_Octave_Raise(OBJ, TYPE, DESC) error("C++ side threw an exception of type " TYPE) #define SWIG_Raise(obj, type, desc) SWIG_Octave_Raise(obj, type, desc) // Include the unified typemap library diff --git a/Lib/perl5/noembed.h b/Lib/perl5/noembed.h index 55c3752aa..572465490 100644 --- a/Lib/perl5/noembed.h +++ b/Lib/perl5/noembed.h @@ -7,6 +7,9 @@ #ifdef do_close #undef do_close #endif +#ifdef do_exec + #undef do_exec +#endif #ifdef scalar #undef scalar #endif diff --git a/Lib/perl5/perlrun.swg b/Lib/perl5/perlrun.swg index 6fb2968f0..ecb1f5cd2 100644 --- a/Lib/perl5/perlrun.swg +++ b/Lib/perl5/perlrun.swg @@ -18,6 +18,7 @@ /* for raw pointers */ #define SWIG_ConvertPtr(obj, pp, type, flags) SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags) +#define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own) #define SWIG_NewPointerObj(p, type, flags) SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags) /* for raw packed data */ @@ -234,10 +235,14 @@ SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) { /* Function for getting a pointer value */ SWIGRUNTIME int -SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) { +SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags, int *own) { swig_cast_info *tc; void *voidptr = (void *)0; SV *tsv = 0; + + if (own) + *own = 0; + /* If magical, apply more magic */ if (SvGMAGICAL(sv)) mg_get(sv); @@ -287,7 +292,11 @@ SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info * { int newmemory = 0; *ptr = SWIG_TypeCast(tc,voidptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ + if (newmemory == SWIG_CAST_NEW_MEMORY) { + assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ + if (own) + *own = *own | SWIG_CAST_NEW_MEMORY; + } } } else { *ptr = voidptr; @@ -302,7 +311,7 @@ SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info * */ 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); /* @@ -317,9 +326,14 @@ SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info * return SWIG_OK; } +SWIGRUNTIME int +SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) { + return SWIG_Perl_ConvertPtrAndOwn(sv, ptr, _t, flags, 0); +} + SWIGRUNTIME void SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) { - if (ptr && (flags & SWIG_SHADOW)) { + if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) { SV *self; SV *obj=newSV(0); HV *hash=newHV(); @@ -328,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/perl5/reference.i b/Lib/perl5/reference.i index 06712bbd5..fdc9c1320 100644 --- a/Lib/perl5/reference.i +++ b/Lib/perl5/reference.i @@ -199,6 +199,35 @@ as follows : $1 = &dvalue; } +%typemap(typecheck) int *REFERENCE, int &REFERENCE, + short *REFERENCE, short &REFERENCE, + long *REFERENCE, long &REFERENCE, + signed char *REFERENCE, signed char &REFERENCE, + bool *REFERENCE, bool &REFERENCE +{ + $1 = SvROK($input) && SvIOK(SvRV($input)); +} +%typemap(typecheck) double *REFERENCE, double &REFERENCE, + float *REFERENCE, float &REFERENCE +{ + $1 = SvROK($input); + if($1) { + SV *tmpsv = SvRV($input); + $1 = SvNOK(tmpsv) || SvIOK(tmpsv); + } +} +%typemap(typecheck) unsigned int *REFERENCE, unsigned int &REFERENCE, + unsigned short *REFERENCE, unsigned short &REFERENCE, + unsigned long *REFERENCE, unsigned long &REFERENCE, + unsigned char *REFERENCE, unsigned char &REFERENCE +{ + $1 = SvROK($input); + if($1) { + SV *tmpsv = SvRV($input); + $1 = SvUOK(tmpsv) || SvIOK(tmpsv); + } +} + %typemap(argout) double *REFERENCE, double &REFERENCE, float *REFERENCE, float &REFERENCE { @@ -211,7 +240,7 @@ as follows : %typemap(argout) int *REFERENCE, int &REFERENCE, short *REFERENCE, short &REFERENCE, long *REFERENCE, long &REFERENCE, - signed char *REFERENCE, unsigned char &REFERENCE, + signed char *REFERENCE, signed char &REFERENCE, bool *REFERENCE, bool &REFERENCE { SV *tempsv; diff --git a/Lib/php/const.i b/Lib/php/const.i index 08096c98b..afd7d02b9 100644 --- a/Lib/php/const.i +++ b/Lib/php/const.i @@ -48,3 +48,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 new file mode 100644 index 000000000..b28f6dbd9 --- /dev/null +++ b/Lib/php/director.swg @@ -0,0 +1,198 @@ +/* ----------------------------------------------------------------------------- + * 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. + * + * director.swg + * + * This file contains support for director classes that proxy + * method calls from C++ to PHP extensions. + * ----------------------------------------------------------------------------- */ + +#ifndef SWIG_DIRECTOR_PHP_HEADER_ +#define SWIG_DIRECTOR_PHP_HEADER_ + +#ifdef __cplusplus + +#include +#include + +/* + Use -DSWIG_DIRECTOR_STATIC if you prefer to avoid the use of the + 'Swig' namespace. This could be useful for multi-modules projects. +*/ +#ifdef SWIG_DIRECTOR_STATIC +/* Force anonymous (static) namespace */ +#define Swig +#endif + +namespace Swig { + /* memory handler */ + struct GCItem + { + virtual ~GCItem() {} + + virtual int get_own() const + { + return 0; + } + }; + + struct GCItem_var + { + GCItem_var(GCItem *item = 0) : _item(item) + { + } + + GCItem_var& operator=(GCItem *item) + { + GCItem *tmp = _item; + _item = item; + delete tmp; + return *this; + } + + ~GCItem_var() + { + delete _item; + } + + GCItem * operator->() const + { + return _item; + } + + private: + GCItem *_item; + }; + + struct GCItem_Object : GCItem + { + GCItem_Object(int own) : _own(own) + { + } + + virtual ~GCItem_Object() + { + } + + int get_own() const + { + return _own; + } + + private: + int _own; + }; + + template + struct GCItem_T : GCItem + { + GCItem_T(Type *ptr) : _ptr(ptr) + { + } + + virtual ~GCItem_T() + { + delete _ptr; + } + + private: + Type *_ptr; + }; + + class Director { + protected: + zval *swig_self; + typedef std::map ownership_map; + mutable ownership_map owner; + public: + Director(zval* self) : swig_self(self) { + } + + ~Director() { + for (ownership_map::iterator i = owner.begin(); i != owner.end(); i++) { + owner.erase(i); + } + } + + bool is_overriden_method(char *cname, char *lc_fname) { + zval classname; + zend_class_entry **ce; + zend_function *mptr; + int name_len = strlen(lc_fname); + + ZVAL_STRING(&classname, cname, 0); + if (zend_lookup_class(Z_STRVAL_P(&classname), Z_STRLEN_P(&classname), &ce TSRMLS_CC) != SUCCESS) { + return false; + } + if (zend_hash_find(&(*ce)->function_table, lc_fname, name_len + 1, (void**) &mptr) != SUCCESS) { + return false; + } + // common.scope points to the declaring class + return strcmp(mptr->common.scope->name, cname); + } + + template + void swig_acquire_ownership(Type *vptr) const + { + if (vptr) { + owner[vptr] = new GCItem_T(vptr); + } + } + }; + + /* base class for director exceptions */ + class DirectorException { + protected: + std::string swig_msg; + public: + DirectorException(int code, const char *hdr, const char* msg) + : swig_msg(hdr) + { + if (strlen(msg)) { + swig_msg += " "; + swig_msg += msg; + } + SWIG_ErrorCode() = code; + SWIG_ErrorMsg() = swig_msg.c_str(); + } + + static void raise(int code, const char *hdr, const char* msg) + { + throw DirectorException(code, hdr, msg); + } + }; + + /* attempt to call a pure virtual method via a director method */ + class DirectorPureVirtualException : public Swig::DirectorException + { + public: + DirectorPureVirtualException(const char* msg) + : DirectorException(E_ERROR, "SWIG director pure virtual method called", msg) + { + } + + static void raise(const char *msg) + { + throw DirectorPureVirtualException(msg); + } + }; + /* any php exception that occurs during a director method call */ + class DirectorMethodException : public Swig::DirectorException + { + public: + DirectorMethodException(const char* msg = "") + : DirectorException(E_ERROR, "SWIG director method error", msg) + { + } + + static void raise(const char *msg) + { + throw DirectorMethodException(msg); + } + }; +} + +#endif /* __cplusplus */ + +#endif diff --git a/Lib/php/factory.i b/Lib/php/factory.i new file mode 100644 index 000000000..c4e082dd2 --- /dev/null +++ b/Lib/php/factory.i @@ -0,0 +1,109 @@ +/* + Implement a more natural wrap for factory methods, for example, if + you have: + + ---- geometry.h -------- + struct Geometry { + enum GeomType{ + POINT, + CIRCLE + }; + + virtual ~Geometry() {} + virtual int draw() = 0; + + // + // Factory method for all the Geometry objects + // + static Geometry *create(GeomType i); + }; + + struct Point : Geometry { + int draw() { return 1; } + double width() { return 1.0; } + }; + + struct Circle : Geometry { + int draw() { return 2; } + double radius() { return 1.5; } + }; + + // + // Factory method for all the Geometry objects + // + Geometry *Geometry::create(GeomType type) { + switch (type) { + case POINT: return new Point(); + case CIRCLE: return new Circle(); + default: return 0; + } + } + ---- geometry.h -------- + + + You can use the %factory with the Geometry::create method as follows: + + %newobject Geometry::create; + %factory(Geometry *Geometry::create, Point, Circle); + %include "geometry.h" + + and Geometry::create will return a 'Point' or 'Circle' instance + instead of the plain 'Geometry' type. For example, in python: + + circle = Geometry.create(Geometry.CIRCLE) + r = circle.radius() + + where circle is a Circle proxy instance. + + NOTES: remember to fully qualify all the type names and don't + use %factory inside a namespace declaration, ie, instead of + + namespace Foo { + %factory(Geometry *Geometry::create, Point, Circle); + } + + use + + %factory(Foo::Geometry *Foo::Geometry::create, Foo::Point, Foo::Circle); + + +*/ + +/* for loop for macro with one argument */ +%define %_formacro_1(macro, arg1,...)macro(arg1) +#if #__VA_ARGS__ != "__fordone__" +%_formacro_1(macro, __VA_ARGS__) +#endif +%enddef + +/* for loop for macro with one argument */ +%define %formacro_1(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef +%define %formacro(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef + +/* for loop for macro with two arguments */ +%define %_formacro_2(macro, arg1, arg2, ...)macro(arg1, arg2) +#if #__VA_ARGS__ != "__fordone__" +%_formacro_2(macro, __VA_ARGS__) +#endif +%enddef + +/* for loop for macro with two arguments */ +%define %formacro_2(macro,...)%_formacro_2(macro, __VA_ARGS__, __fordone__)%enddef + +%define %_factory_dispatch(Type) +if (!dcast) { + Type *dobj = dynamic_cast($1); + if (dobj) { + dcast = 1; + SWIG_SetPointerZval(return_value, SWIG_as_voidptr(dobj),$descriptor(Type *), $owner); + } +}%enddef + +%define %factory(Method,Types...) +%typemap(out) Method { + int dcast = 0; + %formacro(%_factory_dispatch, Types) + if (!dcast) { + SWIG_SetPointerZval(return_value, SWIG_as_voidptr($1),$descriptor, $owner); + } +}%enddef diff --git a/Lib/php/globalvar.i b/Lib/php/globalvar.i index 34bd5f994..3463691d5 100644 --- a/Lib/php/globalvar.i +++ b/Lib/php/globalvar.i @@ -102,6 +102,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; @@ -213,6 +223,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, @@ -325,4 +344,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 99181472d..feeb9c5df 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -52,6 +52,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); @@ -61,6 +65,8 @@ %pass_by_val(double, CONVERT_FLOAT_IN); %pass_by_val(char *, CONVERT_STRING_IN); +%typemap(in) char *& = const char *&; +%typemap(directorout) char *& = const char *&; // char array can be in/out, though the passed string may not be big enough... // so we have to size it @@ -86,6 +92,14 @@ $1 = *tmp; } +%typemap(directorout) SWIGTYPE ($&1_ltype tmp) +{ + if(SWIG_ConvertPtr(*$input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) { + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); + } + $result = *tmp; +} + %typemap(in) SWIGTYPE *, SWIGTYPE [] { @@ -101,6 +115,14 @@ } } +%typemap(in) SWIGTYPE *& ($*ltype temp) +{ + if(SWIG_ConvertPtr(*$input, (void **) &temp, $*1_descriptor, 0) < 0) { + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $*1_descriptor"); + } + $1 = &temp; +} + %typemap(in) SWIGTYPE *DISOWN { if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) { @@ -173,22 +195,124 @@ 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 &, + const unsigned short &, + const long &, + const unsigned long &, + const signed char &, + const unsigned char &, + const bool &, + const size_t &, + const enum SWIGTYPE & +{ + 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, + unsigned short, + long, + unsigned long, + signed char, + unsigned char, + size_t, + enum SWIGTYPE +{ + ZVAL_LONG($input,$1_name); +} + %typemap(out) bool { ZVAL_BOOL(return_value,($1)?1:0); } +%typemap(out) const bool & +{ + ZVAL_BOOL(return_value,(*$1)?1:0); +} + +%typemap(directorin) bool +{ + ZVAL_BOOL($input,($1_name)?1:0); +} + %typemap(out) float, double { ZVAL_DOUBLE(return_value,$1); } +%typemap(out) const float &, + const double & +{ + ZVAL_DOUBLE(return_value,*$1); +} + +%typemap(directorin) float, + double +{ + ZVAL_DOUBLE($input,$1_name); +} + %typemap(out) char { ZVAL_STRINGL(return_value,&$1, 1, 1); } +%typemap(out) const char & +{ + ZVAL_STRINGL(return_value,&*$1, 1, 1); +} + %typemap(out) char *, char [] { @@ -199,6 +323,15 @@ } } +%typemap(out) char *& +{ + if(!*$1) { + ZVAL_NULL(return_value); + } else { + ZVAL_STRING(return_value, (char *)*$1, 1); + } +} + %typemap(out) SWIGTYPE *, SWIGTYPE [], SWIGTYPE & @@ -206,6 +339,35 @@ SWIG_SetPointerZval(return_value, (void *)$1, $1_descriptor, $owner); %} +%typemap(out) SWIGTYPE *& +%{ + SWIG_SetPointerZval(return_value, (void *)*$1, $*1_descriptor, $owner); +%} + +%typemap(directorin) SWIGTYPE *, + SWIGTYPE [], + SWIGTYPE & +%{ + 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 { @@ -227,6 +389,15 @@ } #endif +%typemap(directorin) SWIGTYPE +{ + SWIG_SetPointerZval($input, SWIG_as_voidptr(&$1_name), $&1_descriptor, 2); +} + +/* Array reference typemaps */ +%apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) } + + %typemap(out) void ""; %typemap(out) char [ANY] @@ -240,7 +411,7 @@ // an argument to be converted from a different PHP type, you must convert // it yourself before passing it (e.g. (string)4.7 or (int)"6"). %define %php_typecheck(_type,_prec,is) -%typemap(typecheck,precedence=_prec) _type +%typemap(typecheck,precedence=_prec) _type, const _type & " $1 = (Z_TYPE_PP($input) == is); " %enddef @@ -250,18 +421,19 @@ %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) %php_typecheck(enum SWIGTYPE,SWIG_TYPECHECK_INT8,IS_LONG) %php_typecheck(bool,SWIG_TYPECHECK_BOOL,IS_BOOL) - -%php_typecheck(char,SWIG_TYPECHECK_CHAR,IS_STRING) -%php_typecheck(char *,SWIG_TYPECHECK_STRING,IS_STRING) -%php_typecheck(char [],SWIG_TYPECHECK_STRING,IS_STRING) - %php_typecheck(float,SWIG_TYPECHECK_FLOAT,IS_DOUBLE) %php_typecheck(double,SWIG_TYPECHECK_BOOL,IS_DOUBLE) +%php_typecheck(char,SWIG_TYPECHECK_CHAR,IS_STRING) + +%typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) char *, char *&, char [] + " $1 = (Z_TYPE_PP($input) == IS_STRING); " %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE { @@ -271,7 +443,8 @@ %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE [], - SWIGTYPE & + SWIGTYPE &, + SWIGTYPE *& { void *tmp; _v = (SWIG_ConvertPtr(*$input, (void**)&tmp, $1_descriptor, 0) >= 0); 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 e7d4f2fda..c40421062 100644 --- a/Lib/php/phpkw.swg +++ b/Lib/php/phpkw.swg @@ -1,25 +1,20 @@ /* ----------------------------------------------------------------------------- * phpkw.swg - * - * The 'keywords' in PHP are global, ie, the following names are fine - * when used as class methods. * ----------------------------------------------------------------------------- */ -#define PHPKW(x) %keywordwarn("'" `x` "' is a php keyword, renamed as 'c_" `x` "'",sourcefmt="%(lower)s", rename="c_%s",fullname=1) `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`; -%keywordwarn("'" `x` "' is a php reserved class name, constructor renamed as 'c_" `x` "'",%$isconstructor,rename="c_%s") `x`; -%enddef - -#define PHPBN1(x) %builtinwarn("'" `x` "' conflicts with a built-in name in php",sourcefmt="%(lower)s",fullname=1) `x` -#define PHPBN2(x) %builtinwarn("'" `x` "' conflicts with a built-in name in php") "::" `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` /* From http://aspn.activestate.com/ASPN/docs/PHP/reserved.html + http://php.net/manual/en/reserved.keywords.php and reviewed by Olly Betts. @@ -27,76 +22,81 @@ */ /* We classify these as kw since PHP will not run if used globally. */ +/* "You cannot use any of the following words as constants, class names, + * function or method names. Using them as variable names is generally OK, but + * could lead to confusion." + */ /* case insensitive */ +PHPKW(__halt_compiler); +PHPKW(abstract); PHPKW(and); PHPKW(array); PHPKW(as); PHPKW(break); PHPKW(case); -PHPKW(cfunction); /* No longer reserved in PHP5 */ +PHPKW(catch); PHPKW(class); +PHPKW(clone); PHPKW(const); PHPKW(continue); PHPKW(declare); PHPKW(default); -PHPKW(die); +PHPKW(die); // "Language construct" PHPKW(do); -PHPKW(echo); +PHPKW(echo); // "Language construct" PHPKW(else); PHPKW(elseif); -PHPKW(empty); +PHPKW(empty); // "Language construct" PHPKW(enddeclare); PHPKW(endfor); PHPKW(endforeach); PHPKW(endif); PHPKW(endswitch); PHPKW(endwhile); -PHPKW(eval); -PHPKW(exit); +PHPKW(eval); // "Language construct" +PHPKW(exit); // "Language construct" PHPKW(extends); +PHPKW(final); PHPKW(for); PHPKW(foreach); PHPKW(function); PHPKW(global); +PHPKW(goto); // As of PHP5.3 PHPKW(if); -PHPKW(include); -PHPKW(include_once); -PHPKW(isset); -PHPKW(list); +PHPKW(implements); +PHPKW(include); // "Language construct" +PHPKW(include_once); // "Language construct" +PHPKW(instanceof); +PHPKW(interface); +PHPKW(isset); // "Language construct" +PHPKW(list); // "Language construct" +PHPKW(namespace); // As of PHP5.3 PHPKW(new); -// PHPKW(old_function); /* No longer reserved in PHP5 */ PHPKW(or); -PHPKW(print); -PHPKW(require); -PHPKW(require_once); -PHPKW(return); +PHPKW(print); // "Language construct" +PHPKW(private); +PHPKW(protected); +PHPKW(public); +PHPKW(require); // "Language construct" +PHPKW(require_once); // "Language construct" +PHPKW(return); // "Language construct" PHPKW(static); PHPKW(switch); -PHPKW(unset); +PHPKW(throw); +PHPKW(try); +PHPKW(unset); // "Language construct" PHPKW(use); PHPKW(var); PHPKW(while); PHPKW(xor); -PHPKW(__FILE__); -PHPKW(__LINE__); -PHPKW(__FUNCTION__); +// Compile-time constants PHPKW(__CLASS__); - -/* Added in PHP5 */ -PHPKW(__halt_compiler); -PHPKW(abstract); -PHPKW(catch); -PHPKW(clone); -PHPKW(final); -PHPKW(implements); -PHPKW(instanceof); -PHPKW(interface); -PHPKW(private); -PHPKW(protected); -PHPKW(public); -PHPKW(throw); -PHPKW(try); +PHPKW(__DIR__); // As of PHP5.3 +PHPKW(__FILE__); +PHPKW(__FUNCTION__); PHPKW(__METHOD__); +PHPKW(__NAMESPACE__); // As of PHP5.3 +PHPKW(__LINE__); /* We classify these as built-in names since they conflict, but PHP still runs */ @@ -352,107 +352,131 @@ 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); +PHPCN(datetime); + +/* Built-in PHP functions (incomplete). */ +PHPFN(cos); +PHPFN(sin); +PHPFN(tan); +PHPFN(acos); +PHPFN(asin); +PHPFN(atan); +PHPFN(atan2); +PHPFN(cosh); +PHPFN(sinh); +PHPFN(tanh); +PHPFN(exp); +PHPFN(log); +PHPFN(log10); +PHPFN(pow); +PHPFN(sqrt); +PHPFN(ceil); +PHPFN(floor); +PHPFN(fmod); +PHPFN(min); +PHPFN(max); #undef PHPKW #undef PHPBN1 #undef PHPBN2 #undef PHPCN +#undef PHPFN diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index 22f23f729..a48a30b20 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -10,6 +10,7 @@ extern "C" { #include "zend.h" #include "zend_API.h" #include "php.h" +#include "ext/standard/php_string.h" #ifdef ZEND_RAW_FENTRY /* ZEND_RAW_FENTRY was added somewhere between 5.2.0 and 5.2.3 */ @@ -21,9 +22,18 @@ extern "C" { # define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_NAMED_FE(ZN, N, A) #endif +#ifndef Z_SET_ISREF_P +// For PHP < 5.3 +# define Z_SET_ISREF_P(z) (z)->is_ref = 1 +#endif +#ifndef Z_SET_REFCOUNT_P +// For PHP < 5.3 +# define Z_SET_REFCOUNT_P(z, rc) (z)->refcount = (rc) +#endif + #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);\ @@ -72,7 +82,7 @@ static int default_error_code = E_ERROR; /* used to wrap returned objects in so we know whether they are newobject and need freeing, or not */ -typedef struct _swig_object_wrapper { +typedef struct { void * ptr; int newobject; } swig_object_wrapper; @@ -81,6 +91,7 @@ typedef struct _swig_object_wrapper { static ZEND_RSRC_DTOR_FUNC(SWIG_landfill) { (void)rsrc; } #define SWIG_SetPointerZval(a,b,c,d) SWIG_ZTS_SetPointerZval(a,b,c,d TSRMLS_CC) +#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) static void SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject TSRMLS_DC) { @@ -98,7 +109,37 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject value=(swig_object_wrapper *)emalloc(sizeof(swig_object_wrapper)); value->ptr=ptr; value->newobject=newobject; - ZEND_REGISTER_RESOURCE(z, value, *(int *)(type->clientdata)); + if (newobject <= 1) { + /* Just register the pointer as a resource. */ + ZEND_REGISTER_RESOURCE(z, value, *(int *)(type->clientdata)); + } else { + /* + * Wrap the resource in an object, the resource will be accessible + * via the "_cPtr" member. This is currently only used by + * directorin typemaps. + */ + value->newobject = 0; + zval *resource; + MAKE_STD_ZVAL(resource); + ZEND_REGISTER_RESOURCE(resource, value, *(int *)(type->clientdata)); + zend_class_entry **ce = NULL; + zval *classname; + MAKE_STD_ZVAL(classname); + /* _p_Foo -> Foo */ + ZVAL_STRING(classname, (char*)type->name+3, 1); + /* class names are stored in lowercase */ + php_strtolower(Z_STRVAL_PP(&classname), Z_STRLEN_PP(&classname)); + if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &ce TSRMLS_CC) != SUCCESS) { + /* class does not exist */ + object_init(z); + } else { + object_init_ex(z, *ce); + } + Z_SET_REFCOUNT_P(z, 1); + Z_SET_ISREF_P(z); + zend_hash_update(HASH_OF(z), (char*)"_cPtr", sizeof("_cPtr"), (void*)&resource, sizeof(zval), NULL); + FREE_ZVAL(classname); + } return; } zend_error(E_ERROR, "Type: %s not registered with zend",type->name); @@ -153,7 +194,7 @@ SWIG_ZTS_ConvertResourcePtr(zval *z, swig_type_info *ty, int flags TSRMLS_DC) { char *type_name; value = (swig_object_wrapper *) zend_list_find(z->value.lval, &type); - if ( flags && SWIG_POINTER_DISOWN ) { + if ( flags & SWIG_POINTER_DISOWN ) { value->newobject = 0; } p = value->ptr; @@ -217,3 +258,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 ede5fbe30..cfb82f44c 100644 --- a/Lib/php/std_map.i +++ b/Lib/php/std_map.i @@ -27,8 +27,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) { @@ -52,6 +50,9 @@ namespace std { std::map::iterator i = self->find(key); return i != self->end(); } + bool is_empty() const { + return self->empty(); + } } }; @@ -67,8 +68,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) { @@ -92,6 +91,9 @@ namespace std { std::map::iterator i = self->find(key); return i != self->end(); } + bool is_empty() const { + return self->empty(); + } } }; %enddef @@ -104,8 +106,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) { @@ -129,6 +129,9 @@ namespace std { std::map::iterator i = self->find(key); return i != self->end(); } + bool is_empty() const { + return self->empty(); + } } }; %enddef @@ -142,8 +145,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) { @@ -167,6 +168,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/std_string.i b/Lib/php/std_string.i index 22c953bf5..656765194 100644 --- a/Lib/php/std_string.i +++ b/Lib/php/std_string.i @@ -32,6 +32,11 @@ namespace std { $1.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input)); %} + %typemap(directorout) string %{ + convert_to_string_ex($input); + $result.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input)); + %} + %typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) const string& %{ $1 = ( Z_TYPE_PP($input) == IS_STRING ) ? 1 : 0; %} @@ -40,6 +45,10 @@ namespace std { ZVAL_STRINGL($result, const_cast($1.data()), $1.size(), 1); %} + %typemap(directorin) string %{ + ZVAL_STRINGL($input, const_cast($1_name.data()), $1_name.size(), 1); + %} + %typemap(out) const string & %{ ZVAL_STRINGL($result, const_cast($1->data()), $1->size(), 1); %} @@ -60,6 +69,14 @@ namespace std { $1 = &temp; %} + %typemap(directorout) string & (std::string *temp) %{ + convert_to_string_ex($input); + temp = new std::string; + temp->assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input)); + swig_acquire_ownership(temp); + $result = temp; + %} + %typemap(argout) string & %{ ZVAL_STRINGL(*($input), const_cast($1->data()), $1->size(), 1); %} diff --git a/Lib/php/std_vector.i b/Lib/php/std_vector.i index 4cfc94f74..28c99210c 100644 --- a/Lib/php/std_vector.i +++ b/Lib/php/std_vector.i @@ -1,131 +1,102 @@ /* ----------------------------------------------------------------------------- * std_vector.i - * - * SWIG typemaps for std::vector types * ----------------------------------------------------------------------------- */ %include -// ------------------------------------------------------------------------ -// std::vector -// -// The aim of all that follows would be to integrate std::vector with -// PHP as much as possible, namely, to allow the user to pass and -// be returned PHP lists. -// const declarations are used to guess the intent of the function being -// exported; therefore, the following rationale is applied: -// -// -- f(std::vector), f(const std::vector&), f(const std::vector*): -// the parameter being read-only, either a PHP sequence or a -// previously wrapped std::vector can be passed. -// -- f(std::vector&), f(std::vector*): -// the parameter must be modified; therefore, only a wrapped std::vector -// can be passed. -// -- std::vector f(): -// the vector is returned by copy; therefore, a PHP sequence of T:s -// is returned which is most easily used in other PHP functions -// -- std::vector& f(), std::vector* f(), const std::vector& f(), -// const std::vector* f(): -// the vector is returned by reference; therefore, a wrapped std::vector -// is returned -// ------------------------------------------------------------------------ - %{ #include -#include #include %} -// exported class - namespace std { - - template class vector { - // add generic typemaps here - public: - vector(unsigned int size = 0); - unsigned int size() const; - %rename(is_empty) empty; - bool empty() const; - void clear(); - %rename(push) push_back; - void push_back(const T& x); - %extend { - T pop() throw (std::out_of_range) { - if (self->size() == 0) - throw std::out_of_range("pop from empty vector"); - T x = self->back(); - self->pop_back(); - return x; - } - T& get(int i) throw (std::out_of_range) { - int size = int(self->size()); - if (i>=0 && isize()); - if (i>=0 && i class vector { + public: + typedef size_t size_type; + typedef T value_type; + typedef const value_type& const_reference; + vector(); + vector(size_type n); + size_type size() const; + size_type capacity() const; + void reserve(size_type n); + void clear(); + %rename(push) push_back; + void push_back(const value_type& x); + %extend { + bool is_empty() const { + return $self->empty(); + } + T pop() throw (std::out_of_range) { + if (self->size() == 0) + throw std::out_of_range("pop from empty vector"); + T x = self->back(); + self->pop_back(); + return x; + } + const_reference get(int i) throw (std::out_of_range) { + int size = int(self->size()); + if (i>=0 && isize()); + if (i>=0 && i class vector { - // add specialized typemaps here - public: - vector(unsigned int size = 0); - unsigned int size() const; - %rename(is_empty) empty; - bool empty() const; - void clear(); - %rename(push) push_back; - void push_back(T x); - %extend { - T pop() throw (std::out_of_range) { - if (self->size() == 0) - throw std::out_of_range("pop from empty vector"); - T x = self->back(); - self->pop_back(); - return x; - } - T get(int i) throw (std::out_of_range) { - int size = int(self->size()); - if (i>=0 && isize()); - if (i>=0 && i class vector { + public: + typedef size_t size_type; + typedef bool value_type; + typedef bool const_reference; + vector(); + vector(size_type n); + size_type size() const; + size_type capacity() const; + void reserve(size_type n); + void clear(); + %rename(push) push_back; + void push_back(const value_type& x); + %extend { + bool is_empty() const { + return $self->empty(); + } + bool pop() throw (std::out_of_range) { + if (self->size() == 0) + throw std::out_of_range("pop from empty vector"); + bool x = self->back(); + self->pop_back(); + return x; + } + const_reference get(int i) throw (std::out_of_range) { + int size = int(self->size()); + if (i>=0 && isize()); + if (i>=0 && ivalue.lval; + CONVERT_LONG_LONG_IN(lvalue, long long, $input) $1 = &lvalue; %} %typemap(argout) long long *REFERENCE @@ -125,6 +123,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 { @@ -141,9 +150,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 @@ -157,6 +164,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; @@ -178,11 +196,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 facf54196..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 @@ -33,10 +69,24 @@ %enddef %define %pass_by_val( TYPE, CONVERT_IN ) -%typemap(in) TYPE, const TYPE & +%typemap(in) TYPE %{ CONVERT_IN($1,$1_ltype,$input); %} +%typemap(in) const TYPE & ($*1_ltype temp) +%{ + CONVERT_IN(temp,$*1_ltype,$input); + $1 = &temp; +%} +%typemap(directorout) TYPE +%{ + CONVERT_IN($result,$1_ltype,$input); +%} +%typemap(directorout) const TYPE & ($*1_ltype temp) +%{ + CONVERT_IN(temp,$*1_ltype,$input); + $result = &temp; +%} %enddef %fragment("t_output_helper","header") %{ @@ -49,6 +99,7 @@ t_output_helper( zval **target, zval *o) { } if ( (*target)->type == IS_NULL ) { REPLACE_ZVAL_VALUE(target,o,1); + FREE_ZVAL(o); return; } zval *tmp; diff --git a/Lib/python/boost_shared_ptr.i b/Lib/python/boost_shared_ptr.i index b4c0b5b83..d5dffcda9 100644 --- a/Lib/python/boost_shared_ptr.i +++ b/Lib/python/boost_shared_ptr.i @@ -6,18 +6,23 @@ #define SHARED_PTR_DISOWN 0 #endif +// Language specific macro implementing all the customisations for handling the smart pointer %define SWIG_SHARED_PTR_TYPEMAPS(PROXYCLASS, CONST, TYPE...) +// %naturalvar is as documented for member variables %naturalvar TYPE; %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; -// destructor mods +// destructor wrapper customisation %feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" +// Feature to adapt the code generated in the swigregister functions for smart pointers %feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > } +// Typemap customisations... + // plain value %typemap(in) CONST TYPE (void *argp, int res = 0) { int newmem = 0; diff --git a/Lib/python/director.swg b/Lib/python/director.swg index 82309dbda..a57df7315 100644 --- a/Lib/python/director.swg +++ b/Lib/python/director.swg @@ -234,7 +234,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; @@ -273,12 +273,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) { } @@ -297,7 +297,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) { } @@ -312,7 +312,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 68f5e4b48..d46628551 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -1086,7 +1086,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; } @@ -1160,10 +1160,10 @@ SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { /* here we get the method pointer for callbacks */ const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; - if (desc) { + if (desc) desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; - if (!desc) return SWIG_ERROR; - } + if (!desc) + return SWIG_ERROR; if (ty) { swig_cast_info *tc = SWIG_TypeCheck(desc,ty); if (tc) { diff --git a/Lib/python/std_map.i b/Lib/python/std_map.i index c93ffe61b..074c43180 100644 --- a/Lib/python/std_map.i +++ b/Lib/python/std_map.i @@ -20,11 +20,12 @@ typedef std::map map_type; static int asptr(PyObject *obj, map_type **val) { int res = SWIG_ERROR; + SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (PyDict_Check(obj)) { SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL); %#if PY_VERSION_HEX >= 0x03000000 - /* In Python 3.x the ".items()" method return a dict_items object */ - items = PySequence_Fast(items, ".items() havn't returned a sequence!"); + /* In Python 3.x the ".items()" method returns a dict_items object */ + items = PySequence_Fast(items, ".items() didn't return a sequence!"); %#endif res = traits_asptr_stdseq, std::pair >::asptr(items, val); } else { @@ -32,6 +33,7 @@ res = SWIG_ConvertPtr(obj,(void**)&p,swig::type_info(),0); if (SWIG_IsOK(res) && val) *val = p; } + SWIG_PYTHON_THREAD_END_BLOCK; return res; } }; @@ -47,10 +49,10 @@ if (desc && desc->clientdata) { return SWIG_NewPointerObj(new map_type(map), desc, SWIG_POINTER_OWN); } else { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; size_type size = map.size(); int pysize = (size <= (size_type) INT_MAX) ? (int) size : -1; if (pysize < 0) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_SetString(PyExc_OverflowError, "map size not valid in python"); SWIG_PYTHON_THREAD_END_BLOCK; @@ -62,6 +64,7 @@ swig::SwigVar_PyObject val = swig::from(i->second); PyDict_SetItem(obj, key, val); } + SWIG_PYTHON_THREAD_END_BLOCK; return obj; } } @@ -165,8 +168,8 @@ PyObject* keys() { Map::size_type size = self->size(); int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1; + SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (pysize < 0) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_SetString(PyExc_OverflowError, "map size not valid in python"); SWIG_PYTHON_THREAD_END_BLOCK; @@ -177,14 +180,15 @@ for (int j = 0; j < pysize; ++i, ++j) { PyList_SET_ITEM(keyList, j, swig::from(i->first)); } + SWIG_PYTHON_THREAD_END_BLOCK; return keyList; } PyObject* values() { Map::size_type size = self->size(); int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1; + SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (pysize < 0) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_SetString(PyExc_OverflowError, "map size not valid in python"); SWIG_PYTHON_THREAD_END_BLOCK; @@ -195,14 +199,15 @@ for (int j = 0; j < pysize; ++i, ++j) { PyList_SET_ITEM(valList, j, swig::from(i->second)); } + SWIG_PYTHON_THREAD_END_BLOCK; return valList; } PyObject* items() { Map::size_type size = self->size(); int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1; + SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (pysize < 0) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_SetString(PyExc_OverflowError, "map size not valid in python"); SWIG_PYTHON_THREAD_END_BLOCK; @@ -213,6 +218,7 @@ for (int j = 0; j < pysize; ++i, ++j) { PyList_SET_ITEM(itemList, j, swig::from(*i)); } + SWIG_PYTHON_THREAD_END_BLOCK; return itemList; } 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 60c086f5b..de6289cc5 100644 --- a/Lib/ruby/director.swg +++ b/Lib/ruby/director.swg @@ -173,7 +173,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; @@ -209,12 +209,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) { } @@ -235,7 +235,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) @@ -249,7 +249,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/embed.i b/Lib/ruby/embed.i index ad38190eb..9226ef453 100644 --- a/Lib/ruby/embed.i +++ b/Lib/ruby/embed.i @@ -1,6 +1,6 @@ %wrapper %{ -#include "ruby.h" +#include int main(argc, argv) diff --git a/Lib/ruby/rubycontainer.swg b/Lib/ruby/rubycontainer.swg index c93094aeb..fa4b619f9 100644 --- a/Lib/ruby/rubycontainer.swg +++ b/Lib/ruby/rubycontainer.swg @@ -443,11 +443,10 @@ namespace swig %typemap(out,noblock=1,fragment="RubySequence_Cont") std::pair { $result = rb_ary_new2(2); - RARRAY_PTR($result)[0] = SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).first), - swig::ConstIterator::descriptor(),SWIG_POINTER_OWN); - RARRAY_PTR($result)[1] = SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).second), - swig::ConstIterator::descriptor(),SWIG_POINTER_OWN); - RARRAY_LEN($result) = 2; + rb_ary_push($result, SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).first), + swig::ConstIterator::descriptor(),SWIG_POINTER_OWN)); + rb_ary_push($result, SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).second), + swig::ConstIterator::descriptor(),SWIG_POINTER_OWN)); } // std::map/multimap/set allow returning std::pair< iterator, iterator > from @@ -456,11 +455,10 @@ namespace swig %typemap(out,noblock=1,fragment="RubySequence_Cont") std::pair { $result = rb_ary_new2(2); - RARRAY_PTR($result)[0] = SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).first), - swig::ConstIterator::descriptor(),SWIG_POINTER_OWN); - RARRAY_PTR($result)[1] = SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).second), - swig::ConstIterator::descriptor(),SWIG_POINTER_OWN); - RARRAY_LEN($result) = 2; + rb_ary_push($result, SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).first), + swig::ConstIterator::descriptor(),SWIG_POINTER_OWN)); + rb_ary_push($result, SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).second), + swig::ConstIterator::descriptor(),SWIG_POINTER_OWN)); } @@ -563,7 +561,8 @@ namespace swig { Sequence::const_iterator i = $self->begin(); Sequence::const_iterator e = $self->end(); - VALUE str = rb_str_new2( swig::type_name< Sequence >() ); + const char *type_name = swig::type_name< Sequence >(); + VALUE str = rb_str_new2(type_name); str = rb_str_cat2( str, " [" ); bool comma = false; VALUE tmp; @@ -872,31 +871,8 @@ namespace swig } %enddef -// ..I don't think %swig_sequence_methods_val are really used at all anymore... %define %swig_sequence_methods_val(Sequence...) - %swig_sequence_methods_common(%arg(Sequence)) - %extend { - - VALUE __getitem__(difference_type i) { - VALUE r = Qnil; - try { - r = swig::from< Sequence::value_type >( *(swig::cgetpos(self, i)) ); - } - catch( std::out_of_range ) - { - } - return r; - } - - VALUE __setitem__(difference_type i, value_type x) { - std::size_t len = $self->size(); - if ( i < 0 ) i = len - i; - else if ( static_cast(i) >= len ) - $self->resize( i+1, x ); - else *(swig::getpos(self,i)) = x; - return swig::from< Sequence::value_type >( x ); - } - } + %swig_sequence_methods(%arg(Sequence)) %enddef @@ -950,7 +926,7 @@ namespace swig } catch( std::invalid_argument ) { - rb_raise( rb_eArgError, + rb_raise( rb_eArgError, "%s", Ruby_Format_TypeError( "", swig::type_name(), __FUNCTION__, idx+2, elem )); @@ -977,7 +953,7 @@ namespace swig } catch( std::invalid_argument ) { - rb_raise( rb_eArgError, + rb_raise( rb_eArgError, "%s", Ruby_Format_TypeError( "", swig::type_name(), __FUNCTION__, idx+2, elem )); @@ -1032,7 +1008,7 @@ namespace swig { if (seq) { VALUE lastErr = rb_gv_get("$!"); if (lastErr == Qnil) { - rb_raise(rb_eTypeError, e.what()); + rb_raise(rb_eTypeError, "%s", e.what()); } } return SWIG_ERROR; @@ -1072,7 +1048,7 @@ namespace swig { if (seq) { VALUE lastErr = rb_gv_get("$!"); if (lastErr == Qnil) { - rb_raise(rb_eTypeError, e.what()); + rb_raise(rb_eTypeError, "%s", e.what()); } } return SWIG_ERROR; @@ -1109,9 +1085,8 @@ namespace swig { int i = 0; for (const_iterator it = seq.begin(); it != seq.end(); ++it, ++i) { - RARRAY_PTR(obj)[i] = swig::from< value_type >(*it); + rb_ary_push(obj, swig::from< value_type >(*it)); } - RARRAY_LEN(obj) = size; rb_obj_freeze(obj); // treat as immutable result return obj; } else { diff --git a/Lib/ruby/rubycontainer_extended.swg b/Lib/ruby/rubycontainer_extended.swg index 09be64aee..d2a058586 100644 --- a/Lib/ruby/rubycontainer_extended.swg +++ b/Lib/ruby/rubycontainer_extended.swg @@ -72,7 +72,7 @@ catch ( const std::invalid_argument& ) { rb_raise(rb_eTypeError, - "Yield block did not return a valid element for " #Container); + "Yield block did not return a valid element for " "Container"); } return $self; diff --git a/Lib/ruby/rubyhead.swg b/Lib/ruby/rubyhead.swg index d17fdbaae..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 @@ -10,6 +19,12 @@ #ifdef bind # undef bind #endif +#ifdef close +# undef close +#endif +#ifdef connect +# undef connect +#endif /* Ruby 1.7 defines NUM2LL(), LL2NUM() and ULL2NUM() macros */ diff --git a/Lib/ruby/rubyprimtypes.swg b/Lib/ruby/rubyprimtypes.swg index aff35dcf1..df72e97f4 100644 --- a/Lib/ruby/rubyprimtypes.swg +++ b/Lib/ruby/rubyprimtypes.swg @@ -193,7 +193,7 @@ SWIG_AsVal_dec(unsigned long long)(VALUE obj, unsigned long long *val) } %fragment(SWIG_AsVal_frag(double),"header",fragment="SWIG_ruby_failed") { -%ruby_aux_method(double, NUM2DBL, (type == T_FLOAT ? NUM2DBL(obj) : (type == T_FIXNUM ? (double) FIX2INT(obj) : rb_big2dbl(obj)))) +%ruby_aux_method(double, NUM2DBL, NUM2DBL(obj)) SWIGINTERN int SWIG_AsVal_dec(double)(VALUE obj, double *val) diff --git a/Lib/ruby/rubyrun.swg b/Lib/ruby/rubyrun.swg index ccc997a71..a8afc6a10 100644 --- a/Lib/ruby/rubyrun.swg +++ b/Lib/ruby/rubyrun.swg @@ -42,7 +42,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 @@ -97,7 +97,7 @@ static ID swig_call_id = 0; ++swig_virtual_calls; # define SWIG_RELEASE_STACK --swig_virtual_calls; # define Ruby_DirectorTypeMismatchException(x) \ - rb_raise( rb_eTypeError, x ); return c_result; + rb_raise( rb_eTypeError, "%s", x ); return c_result; static unsigned int swig_virtual_calls = 0; diff --git a/Lib/ruby/std_map.i b/Lib/ruby/std_map.i index cc22fef51..e23f1c31b 100644 --- a/Lib/ruby/std_map.i +++ b/Lib/ruby/std_map.i @@ -345,7 +345,8 @@ { Map::const_iterator i = $self->begin(); Map::const_iterator e = $self->end(); - VALUE str = rb_str_new2( swig::type_name< Map >() ); + const char *type_name = swig::type_name< Map >(); + VALUE str = rb_str_new2( type_name ); str = rb_str_cat2( str, " {" ); bool comma = false; VALUE tmp; diff --git a/Lib/ruby/std_multimap.i b/Lib/ruby/std_multimap.i index 7fec50de1..31795c768 100644 --- a/Lib/ruby/std_multimap.i +++ b/Lib/ruby/std_multimap.i @@ -115,7 +115,8 @@ { MultiMap::iterator i = $self->begin(); MultiMap::iterator e = $self->end(); - VALUE str = rb_str_new2( swig::type_name< MultiMap >() ); + const char *type_name = swig::type_name< MultiMap >(); + VALUE str = rb_str_new2( type_name ); str = rb_str_cat2( str, " {" ); VALUE tmp; while ( i != e ) diff --git a/Lib/ruby/std_pair.i b/Lib/ruby/std_pair.i index cb714e4a8..5b4c8baf2 100644 --- a/Lib/ruby/std_pair.i +++ b/Lib/ruby/std_pair.i @@ -118,13 +118,11 @@ static VALUE from(const std::pair& val) { VALUE obj = rb_ary_new2(2); - RARRAY_PTR(obj)[0] = swig::from< - typename swig::noconst_traits::noconst_type>(val.first); - RARRAY_PTR(obj)[1] = swig::from(val.second); - RARRAY_LEN(obj) = 2; - rb_define_singleton_method(obj, "second", + rb_ary_push(obj, swig::from::noconst_type>(val.first)); + rb_ary_push(obj, swig::from(val.second)); + rb_define_singleton_method(obj, "second", VALUEFUNC(_wrap_pair_second), 0 ); - rb_define_singleton_method(obj, "second=", + rb_define_singleton_method(obj, "second=", VALUEFUNC(_wrap_pair_second_eq), 1 ); rb_obj_freeze(obj); // treat as immutable tuple return obj; @@ -148,7 +146,8 @@ VALUE inspect() const { VALUE tmp; - VALUE str = rb_str_new2( swig::type_name< pair >() ); + const char *type_name = swig::type_name< pair >(); + VALUE str = rb_str_new2( type_name ); str = rb_str_cat2( str, " (" ); tmp = swig::from( $self->first ); tmp = rb_obj_as_string( tmp ); diff --git a/Lib/ruby/std_set.i b/Lib/ruby/std_set.i index 64428abf6..09c4404cf 100644 --- a/Lib/ruby/std_set.i +++ b/Lib/ruby/std_set.i @@ -170,10 +170,9 @@ %typemap(out,noblock=1,fragment="RubyPairBoolOutputIterator") std::pair { $result = rb_ary_new2(2); - RARRAY_PTR($result)[0] = SWIG_NewPointerObj(swig::make_set_nonconst_iterator(%static_cast($1,$type &).first), - swig::Iterator::descriptor(),SWIG_POINTER_OWN); - RARRAY_PTR($result)[1] = SWIG_From(bool)(%static_cast($1,const $type &).second); - RARRAY_LEN($result) = 2; + rb_ary_push($result, SWIG_NewPointerObj(swig::make_set_nonconst_iterator(%static_cast($1,$type &).first), + swig::Iterator::descriptor(),SWIG_POINTER_OWN)); + rb_ary_push($result, SWIG_From(bool)(%static_cast($1,const $type &).second)); } %extend { diff --git a/Lib/shared_ptr.i b/Lib/shared_ptr.i index 709791502..ffff2b40b 100644 --- a/Lib/shared_ptr.i +++ b/Lib/shared_ptr.i @@ -1,3 +1,7 @@ +// The main implementation detail in using this smart pointer of a type is to customise the code generated +// to use a pointer to the smart pointer of the type, rather than the usual pointer to the underlying type. +// So for some type T, shared_ptr * is used rather than T *. + // shared_ptr namespaces could be boost or std or std::tr1 // For example for std::tr1, use: // #define SWIG_SHARED_PTR_NAMESPACE std diff --git a/Lib/std/_std_deque.i b/Lib/std/_std_deque.i index c30523c0d..4234789a8 100644 --- a/Lib/std/_std_deque.i +++ b/Lib/std/_std_deque.i @@ -24,7 +24,7 @@ }; */ -%define %std_deque_methods(T) +%define %std_deque_methods_noempty(T) typedef T &reference; typedef const T& const_reference; @@ -38,7 +38,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); @@ -66,7 +65,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); @@ -74,7 +73,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; @@ -109,15 +108,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 77308e080..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") @@ -152,7 +157,7 @@ #define %clearnaturalvar %feature("naturalvar","") /* valuewrapper directives */ -#define %valuewrapper %feature("valuewrapper",) +#define %valuewrapper %feature("valuewrapper") #define %clearvaluewrapper %feature("valuewrapper","") #define %novaluewrapper %feature("novaluewrapper") #define %clearnovaluewrapper %feature("novaluewrapper","") diff --git a/Lib/tcl/std_vector.i b/Lib/tcl/std_vector.i index 3c8dd24b7..de99a36d0 100644 --- a/Lib/tcl/std_vector.i +++ b/Lib/tcl/std_vector.i @@ -13,17 +13,17 @@ // const declarations are used to guess the intent of the function being // exported; therefore, the following rationale is applied: // -// -- f(std::vector), f(const std::vector&), f(const std::vector*): +// -- f(std::vector< T >), f(const std::vector< T >&), f(const std::vector< T >*): // the parameter being read-only, either a Tcl list or a -// previously wrapped std::vector can be passed. -// -- f(std::vector&), f(std::vector*): +// previously wrapped std::vector< T > can be passed. +// -- f(std::vector< T >&), f(std::vector< T >*): // the parameter must be modified; therefore, only a wrapped std::vector // can be passed. -// -- std::vector f(): +// -- std::vector< T > f(): // the vector is returned by copy; therefore, a Tcl list of T:s // is returned which is most easily used in other Tcl functions procs -// -- std::vector& f(), std::vector* f(), const std::vector& f(), -// const std::vector* f(): +// -- std::vector< T >& f(), std::vector< T >* f(), const std::vector< T >& f(), +// const std::vector< T >* f(): // the vector is returned by reference; therefore, a wrapped std::vector // is returned // ------------------------------------------------------------------------ @@ -82,7 +82,7 @@ int SwigDouble_As(Tcl_Interp *interp, Tcl_Obj *o, Type *val) { namespace std { template class vector { - %typemap(in) vector (std::vector *v) { + %typemap(in) vector< T > (std::vector< T > *v) { Tcl_Obj **listobjv; int nitems; int i; @@ -92,11 +92,11 @@ namespace std { $&1_descriptor, 0) == 0){ $1 = *v; } else { - // It isn't a vector so it should be a list of T's + // It isn't a vector< T > so it should be a list of T's if(Tcl_ListObjGetElements(interp, $input, \ &nitems, &listobjv) == TCL_ERROR) return TCL_ERROR; - $1 = std::vector(); + $1 = std::vector< T >(); for (i = 0; i < nitems; i++) { if ((SWIG_ConvertPtr(listobjv[i],(void **) &temp, $descriptor(T *),0)) != 0) { @@ -110,8 +110,8 @@ namespace std { } } - %typemap(in) const vector* (std::vector *v, std::vector w), - const vector& (std::vector *v, std::vector w) { + %typemap(in) const vector< T >* (std::vector< T > *v, std::vector< T > w), + const vector< T >& (std::vector< T > *v, std::vector< T > w) { Tcl_Obj **listobjv; int nitems; int i; @@ -121,11 +121,11 @@ namespace std { $&1_descriptor, 0) == 0) { $1 = v; } else { - // It isn't a vector so it should be a list of T's + // It isn't a vector< T > so it should be a list of T's if(Tcl_ListObjGetElements(interp, $input, &nitems, &listobjv) == TCL_ERROR) return TCL_ERROR; - w = std::vector(); + w = std::vector< T >(); for (i = 0; i < nitems; i++) { if ((SWIG_ConvertPtr(listobjv[i],(void **) &temp, $descriptor(T *),0)) != 0) { @@ -140,7 +140,7 @@ namespace std { } } - %typemap(out) vector { + %typemap(out) vector< T > { for (unsigned int i=0; i<$1.size(); i++) { T* ptr = new T((($1_type &)$1)[i]); Tcl_ListObjAppendElement(interp, $result, \ @@ -150,18 +150,18 @@ namespace std { } } - %typecheck(SWIG_TYPECHECK_VECTOR) vector { + %typecheck(SWIG_TYPECHECK_VECTOR) vector< T > { Tcl_Obj **listobjv; int nitems; T* temp; - std::vector *v; + std::vector< T > *v; if(SWIG_ConvertPtr($input, (void **) &v, \ $&1_descriptor, 0) == 0) { /* wrapped vector */ $1 = 1; } else { - // It isn't a vector so it should be a list of T's + // It isn't a vector< T > so it should be a list of T's if(Tcl_ListObjGetElements(interp, $input, &nitems, &listobjv) == TCL_ERROR) $1 = 0; @@ -178,19 +178,19 @@ namespace std { } } - %typecheck(SWIG_TYPECHECK_VECTOR) const vector&, - const vector* { + %typecheck(SWIG_TYPECHECK_VECTOR) const vector< T >&, + const vector< T >* { Tcl_Obj **listobjv; int nitems; T* temp; - std::vector *v; + std::vector< T > *v; if(SWIG_ConvertPtr($input, (void **) &v, \ $1_descriptor, 0) == 0){ /* wrapped vector */ $1 = 1; } else { - // It isn't a vector so it should be a list of T's + // It isn't a vector< T > so it should be a list of T's if(Tcl_ListObjGetElements(interp, $input, &nitems, &listobjv) == TCL_ERROR) $1 = 0; @@ -210,7 +210,7 @@ namespace std { public: vector(unsigned int size = 0); vector(unsigned int size, const T& value); - vector(const vector &); + vector(const vector< T > &); unsigned int size() const; bool empty() const; @@ -248,9 +248,9 @@ namespace std { // specializations for built-ins %define specialize_std_vector(T, CONVERT_FROM, CONVERT_TO) - template<> class vector { + template<> class vector< T > { - %typemap(in) vector (std::vector *v){ + %typemap(in) vector< T > (std::vector< T > *v){ Tcl_Obj **listobjv; int nitems; int i; @@ -260,11 +260,11 @@ namespace std { $&1_descriptor, 0) == 0) { $1 = *v; } else { - // It isn't a vector so it should be a list of T's + // It isn't a vector< T > so it should be a list of T's if(Tcl_ListObjGetElements(interp, $input, &nitems, &listobjv) == TCL_ERROR) return TCL_ERROR; - $1 = std::vector(); + $1 = std::vector< T >(); for (i = 0; i < nitems; i++) { if (CONVERT_FROM(interp, listobjv[i], &temp) == TCL_ERROR) return TCL_ERROR; @@ -273,8 +273,8 @@ namespace std { } } - %typemap(in) const vector& (std::vector *v,std::vector w), - const vector* (std::vector *v,std::vector w) { + %typemap(in) const vector< T >& (std::vector< T > *v,std::vector< T > w), + const vector< T >* (std::vector< T > *v,std::vector< T > w) { Tcl_Obj **listobjv; int nitems; int i; @@ -284,11 +284,11 @@ namespace std { $1_descriptor, 0) == 0) { $1 = v; } else { - // It isn't a vector so it should be a list of T's + // It isn't a vector< T > so it should be a list of T's if(Tcl_ListObjGetElements(interp, $input, &nitems, &listobjv) == TCL_ERROR) return TCL_ERROR; - w = std::vector(); + w = std::vector< T >(); for (i = 0; i < nitems; i++) { if (CONVERT_FROM(interp, listobjv[i], &temp) == TCL_ERROR) return TCL_ERROR; @@ -298,25 +298,25 @@ namespace std { } } - %typemap(out) vector { + %typemap(out) vector< T > { for (unsigned int i=0; i<$1.size(); i++) { Tcl_ListObjAppendElement(interp, $result, \ CONVERT_TO((($1_type &)$1)[i])); } } - %typecheck(SWIG_TYPECHECK_VECTOR) vector { + %typecheck(SWIG_TYPECHECK_VECTOR) vector< T > { Tcl_Obj **listobjv; int nitems; T temp; - std::vector *v; + std::vector< T > *v; if(SWIG_ConvertPtr($input, (void **) &v, \ $&1_descriptor, 0) == 0){ /* wrapped vector */ $1 = 1; } else { - // It isn't a vector so it should be a list of T's + // It isn't a vector< T > so it should be a list of T's if(Tcl_ListObjGetElements(interp, $input, &nitems, &listobjv) == TCL_ERROR) $1 = 0; @@ -331,19 +331,19 @@ namespace std { } } - %typecheck(SWIG_TYPECHECK_VECTOR) const vector&, - const vector*{ + %typecheck(SWIG_TYPECHECK_VECTOR) const vector< T >&, + const vector< T >*{ Tcl_Obj **listobjv; int nitems; T temp; - std::vector *v; + std::vector< T > *v; if(SWIG_ConvertPtr($input, (void **) &v, \ $1_descriptor, 0) == 0){ /* wrapped vector */ $1 = 1; } else { - // It isn't a vector so it should be a list of T's + // It isn't a vector< T > so it should be a list of T's if(Tcl_ListObjGetElements(interp, $input, &nitems, &listobjv) == TCL_ERROR) $1 = 0; @@ -361,7 +361,7 @@ namespace std { public: vector(unsigned int size = 0); vector(unsigned int size, const T& value); - vector(const vector &); + vector(const vector< T > &); unsigned int size() const; bool empty() const; diff --git a/Lib/tcl/tclinit.swg b/Lib/tcl/tclinit.swg index 93d984ae2..6910d3c51 100644 --- a/Lib/tcl/tclinit.swg +++ b/Lib/tcl/tclinit.swg @@ -22,6 +22,11 @@ SWIGEXPORT int SWIG_init(Tcl_Interp *); } #endif +/* Compatibility version for TCL stubs */ +#ifndef SWIG_TCL_STUBS_VERSION +#define SWIG_TCL_STUBS_VERSION "8.1" +#endif + %} %init %{ @@ -74,10 +79,18 @@ SWIGEXPORT int SWIG_init(Tcl_Interp *interp) { int i; if (interp == 0) return TCL_ERROR; #ifdef USE_TCL_STUBS - if (Tcl_InitStubs(interp, (char*)"8.1", 0) == NULL) { + /* (char*) cast is required to avoid compiler warning/error for Tcl < 8.4. */ + if (Tcl_InitStubs(interp, (char*)SWIG_TCL_STUBS_VERSION, 0) == NULL) { return TCL_ERROR; } #endif +#ifdef USE_TK_STUBS + /* (char*) cast is required to avoid compiler warning/error. */ + if (Tk_InitStubs(interp, (char*)SWIG_TCL_STUBS_VERSION, 0) == NULL) { + return TCL_ERROR; + } +#endif + Tcl_PkgProvide(interp, (char*)SWIG_name, (char*)SWIG_version); #ifdef SWIG_namespace diff --git a/Lib/tcl/typemaps.i b/Lib/tcl/typemaps.i index 8bee672cc..04a5c78f3 100644 --- a/Lib/tcl/typemaps.i +++ b/Lib/tcl/typemaps.i @@ -1,8 +1,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 5baf7904c..8597b7b0c 100644 --- a/Lib/typemaps/cdata.swg +++ b/Lib/typemaps/cdata.swg @@ -18,7 +18,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); /* ----------------------------------------------------------------------------- @@ -67,7 +67,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 cd79e1498..b37a48331 100644 --- a/Makefile.in +++ b/Makefile.in @@ -182,7 +182,7 @@ java.actionexample: else \ echo $(ACTION)ing Examples/$(LANGUAGE)/java; \ (cd Examples/$(LANGUAGE)/java && $(MAKE) -s $(chk-set-env) $(ACTION)) \ - fi; \ + fi # Checks testcases in the test-suite excluding those which are known to be broken check-test-suite: \ @@ -327,7 +327,7 @@ clean-docs-main: @test -d $(DOCS) || exit 0; cd $(DOCS) && $(MAKE) clean clean-docs-ccache: - @test -z "$(ENABLE_CCACHE)" || (cd $(CCACHE) && $(MAKE) clean-docs) + @# Use distclean-docs-ccache, else a user requires the yodl tools to generate the docs after a clean maintainer-clean: clean-libfiles @cd $(SOURCE) && $(MAKE) maintainer-clean @@ -338,7 +338,7 @@ maintainer-clean: clean-libfiles DISTCLEAN-DEAD = config.status config.log config.cache swig.spec Makefile mkmf.log libtool -distclean: distclean-objects clean-examples 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 @@ -354,6 +354,9 @@ distclean-test-suite: distclean-ccache: test -z "$(ENABLE_CCACHE)" || (cd $(CCACHE) && $(MAKE) -s distclean) +distclean-docs-ccache: + @test -z "$(ENABLE_CCACHE)" || (cd $(CCACHE) && $(MAKE) distclean-docs) + distclean-dead: rm -f $(DISTCLEAN-DEAD) diff --git a/README b/README index e7b79d2d2..8cdc34887 100644 --- a/README +++ b/README @@ -36,6 +36,14 @@ A SWIG FAQ and other hints can be found on the SWIG Wiki: 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. - Improved C# std::vector wrappers. @@ -312,8 +320,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 c17577d8c..ddc5d05dc 100644 --- a/Source/CParse/cparse.h +++ b/Source/CParse/cparse.h @@ -57,7 +57,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 c5ad7b908..23152e884 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -139,7 +139,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); } @@ -261,7 +261,7 @@ void skip_decl(void) { * Lexical scanner. * ------------------------------------------------------------------------- */ -int yylook(void) { +static int yylook(void) { int tok = 0; @@ -416,6 +416,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))); @@ -505,7 +508,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; @@ -531,6 +534,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) @@ -545,6 +549,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 bb644f9db..68c70aa19 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -47,6 +47,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; @@ -214,9 +215,9 @@ Hash *Swig_cparse_features(void) { } static String *feature_identifier_fix(String *s) { - if (SwigType_istemplate(s)) { - String *tp, *ts, *ta, *tq; - tp = SwigType_templateprefix(s); + String *tp = SwigType_istemplate_templateprefix(s); + if (tp) { + String *ts, *ta, *tq; ts = SwigType_templatesuffix(s); ta = SwigType_templateargs(s); tq = Swig_symbol_type_qualify(ta,0); @@ -276,6 +277,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); } @@ -539,6 +548,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 */ @@ -568,7 +579,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; @@ -595,8 +608,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) { @@ -747,14 +760,15 @@ static List *pure_abstract(Node *n) { static String *make_class_name(String *name) { String *nname = 0; + String *prefix; if (Namespaceprefix) { nname= NewStringf("%s::%s", Namespaceprefix, name); } else { nname = NewString(name); } - if (SwigType_istemplate(nname)) { - String *prefix, *args, *qargs; - prefix = SwigType_templateprefix(nname); + prefix = SwigType_istemplate_templateprefix(nname); + if (prefix) { + String *args, *qargs; args = SwigType_templateargs(nname); qargs = Swig_symbol_type_qualify(args,0); Append(prefix,qargs); @@ -817,14 +831,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; } @@ -856,6 +864,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; @@ -869,11 +883,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 */ @@ -976,18 +990,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 */ @@ -997,15 +1009,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; /* @@ -1058,6 +1212,8 @@ static void strip_comments(char *string) { case 5: if (*c == '/') state = 0; + else + state = 1; *c = ' '; break; case 6: @@ -1075,6 +1231,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; @@ -1104,20 +1261,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)); @@ -1166,17 +1315,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); @@ -1467,7 +1617,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) { } decl; Parm *tparms; struct { - String *op; + String *method; Hash *kwargs; } tmap; struct { @@ -1488,7 +1638,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 @@ -1503,7 +1653,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 ARROW %token QUESTIONMARK @@ -1526,7 +1676,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 @@ -1574,7 +1724,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; @@ -1958,8 +2108,8 @@ fragment_directive: FRAGMENT LPAREN fname COMMA kwargs RPAREN HBLOCK { ; /* ------------------------------------------------------------ - %includefile "filename" [option1="xyz", ...] [ declarations ] - %importfile "filename" [option1="xyz", ...] [ declarations ] + %includefile(option1="xyz", ...) "filename" [ declarations ] + %importfile(option1="xyz", ...) "filename" [ declarations ] ------------------------------------------------------------ */ include_directive: includetype options string LBRACKET { @@ -2504,10 +2654,10 @@ varargs_parms : parms { $$ = $1; } typemap_directive : TYPEMAP LPAREN typemap_type RPAREN tm_list stringbrace { $$ = 0; - if ($3.op) { + if ($3.method) { String *code = 0; $$ = new_node("typemap"); - Setattr($$,"method",$3.op); + Setattr($$,"method",$3.method); if ($3.kwargs) { ParmList *kw = $3.kwargs; code = remove_block(kw, $6); @@ -2521,17 +2671,17 @@ typemap_directive : TYPEMAP LPAREN typemap_type RPAREN tm_list stringbrace { } | TYPEMAP LPAREN typemap_type RPAREN tm_list SEMI { $$ = 0; - if ($3.op) { + if ($3.method) { $$ = new_node("typemap"); - Setattr($$,"method",$3.op); + Setattr($$,"method",$3.method); appendChild($$,$5); } } | TYPEMAP LPAREN typemap_type RPAREN tm_list EQUAL typemap_parm SEMI { $$ = 0; - if ($3.op) { + if ($3.method) { $$ = new_node("typemapcopy"); - Setattr($$,"method",$3.op); + Setattr($$,"method",$3.method); Setattr($$,"pattern", Getattr($7,"pattern")); appendChild($$,$5); } @@ -2551,15 +2701,15 @@ typemap_type : kwargs { /* two argument typemap form */ name = Getattr($1,"name"); if (!name || (Strcmp(name,typemap_lang))) { - $$.op = 0; + $$.method = 0; $$.kwargs = 0; } else { - $$.op = Getattr(p,"name"); + $$.method = Getattr(p,"name"); $$.kwargs = nextSibling(p); } } else { /* one-argument typemap-form */ - $$.op = Getattr($1,"name"); + $$.method = Getattr($1,"name"); $$.kwargs = p; } } @@ -2582,11 +2732,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 { @@ -2734,7 +2884,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va Parm *ti = targs; String *tv = Getattr(tp,"value"); if (!tv) tv = Getattr(tp,"type"); - while(pi != tp) { + while(pi != tp && ti && pi) { String *name = Getattr(ti,"name"); String *value = Getattr(pi,"value"); if (!value) value = Getattr(pi,"type"); @@ -2763,7 +2913,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 @@ -2781,8 +2931,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); @@ -2822,10 +2975,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; @@ -2933,7 +3086,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); @@ -3205,7 +3358,7 @@ c_enum_decl : storage_class c_enum_keyword ename c_enum_inherit LBRACE enumlist add_symbols($$); /* Add to tag space */ add_symbols($6); /* Add enum values to id space */ } - | storage_class c_enum_keyword ename c_enum_inherit LBRACE enumlist RBRACE declarator c_decl_tail { + | storage_class c_enum_keyword ename c_enum_inherit LBRACE enumlist RBRACE declarator initializer c_decl_tail { Node *n; SwigType *ty = 0; String *unnamed = 0; @@ -3245,12 +3398,12 @@ c_enum_decl : storage_class c_enum_keyword ename c_enum_inherit LBRACE enumlist if (unnamedinstance) { SwigType *cty = NewString("enum "); Setattr($$,"type",cty); - Setattr($$,"unnamedinstance","1"); - Setattr(n,"unnamedinstance","1"); + SetFlag($$,"unnamedinstance"); + SetFlag(n,"unnamedinstance"); Delete(cty); } - if ($9) { - Node *p = $9; + if ($10) { + Node *p = $10; set_nextSibling(n,p); while (p) { SwigType *cty = Copy(ty); @@ -3344,10 +3497,11 @@ 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) { + String *prefix; List *bases = 0; Node *scope = 0; $$ = new_node("class"); @@ -3396,9 +3550,9 @@ cpp_class_decl : if ($4) { bases = make_inherit_list($3,Getattr($4,"public")); } - if (SwigType_istemplate($3)) { - String *fbase, *tbase, *prefix; - prefix = SwigType_templateprefix($3); + prefix = SwigType_istemplate_templateprefix($3); + if (prefix) { + String *fbase, *tbase; if (Namespaceprefix) { fbase = NewStringf("%s::%s", Namespaceprefix,$3); tbase = NewStringf("%s::%s", Namespaceprefix, prefix); @@ -3409,7 +3563,6 @@ cpp_class_decl : Swig_name_inherit(tbase,fbase); Delete(fbase); Delete(tbase); - Delete(prefix); } if (strcmp($2,"class") == 0) { cplus_mode = CPLUS_PRIVATE; @@ -3460,121 +3613,131 @@ cpp_class_decl : } } class_decl[class_level++] = $$; + Delete(prefix); 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 */ @@ -3613,9 +3776,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; @@ -3631,8 +3795,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); @@ -3702,12 +3866,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); } ; /* ------------------------------------------------------------ @@ -3734,240 +3898,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--; } /* Explicit template instantiation */ @@ -4050,7 +4268,7 @@ templateparameters : templateparameter templateparameterstail { ; templateparameter : templcpptype { - $$ = NewParm(NewString($1), 0); + $$ = NewParmWithoutFileLineInfo(NewString($1), 0); } | parm { $$ = $1; @@ -4473,110 +4691,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; } @@ -4709,7 +4894,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) { @@ -4718,7 +4903,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) { @@ -4727,7 +4912,7 @@ parm : rawtype parameter_declarator { } | PERIOD PERIOD PERIOD { SwigType *t = NewString("v(...)"); - $$ = NewParm(t, 0); + $$ = NewParmWithoutFileLineInfo(t, 0); Setfile($$,cparse_file); Setline($$,cparse_line); } @@ -4790,7 +4975,7 @@ valparm : parm { } | valexpr { - $$ = NewParm(0,0); + $$ = NewParmWithoutFileLineInfo(0,0); Setfile($$,cparse_file); Setline($$,cparse_line); Setattr($$,"value",$1.val); @@ -5964,6 +6149,7 @@ exprnum : NUM_INT { $$ = $1; } | NUM_ULONG { $$ = $1; } | NUM_LONGLONG { $$ = $1; } | NUM_ULONGLONG { $$ = $1; } + | NUM_BOOL { $$ = $1; } ; exprcompound : expr PLUS expr { @@ -5982,7 +6168,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); } @@ -6008,40 +6194,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); @@ -6504,14 +6687,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 d3b9b3d99..8d77cb0ee 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -266,7 +266,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) { @@ -426,6 +426,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() * @@ -433,175 +497,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) { @@ -613,13 +796,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 222fb1484..798a6567d 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -74,7 +74,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 @@ -86,6 +86,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 */ @@ -251,15 +253,9 @@ /* please leave 850-869 free for Modula 3 */ -/* These are needed for backward compatibility, but you don't need to add - * PHP4 versions of new warnings since existing user interface files can't - * be using them. - */ -#define WARN_PHP_MULTIPLE_INHERITANCE 870 -#define WARN_PHP_UNKNOWN_PRAGMA 871 - #define WARN_PHP_MULTIPLE_INHERITANCE 870 #define WARN_PHP_UNKNOWN_PRAGMA 871 +#define WARN_PHP_PUBLIC_BASE 872 /* please leave 870-889 free for PHP */ diff --git a/Source/Makefile.am b/Source/Makefile.am index 84c595bc0..bc3222b25 100644 --- a/Source/Makefile.am +++ b/Source/Makefile.am @@ -8,7 +8,7 @@ BUILD_SOURCE_DIR=$(top_builddir)/Source SWIG_CXX_DEFS = @SWILL@ -AM_CFLAGS = -I$(BUILD_SOURCE_DIR)/Include \ +AM_CPPFLAGS = -I$(BUILD_SOURCE_DIR)/Include \ -I$(BUILD_SOURCE_DIR)/CParse \ -I$(SOURCE_DIR)/Include \ -I$(SOURCE_DIR)/DOH \ @@ -17,8 +17,7 @@ AM_CFLAGS = -I$(BUILD_SOURCE_DIR)/Include \ -I$(SOURCE_DIR)/Swig \ -I$(SOURCE_DIR)/Modules -AM_CXXFLAGS = $(AM_CFLAGS) \ - $(SWIG_CXX_DEFS) +AM_CXXFLAGS = $(SWIG_CXX_DEFS) AM_YFLAGS = -d @@ -87,7 +86,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 034799567..3c6e86cc5 100644 --- a/Source/Modules/allegrocl.cxx +++ b/Source/Modules/allegrocl.cxx @@ -378,9 +378,12 @@ void add_defined_foreign_type(Node *n, int overwrite = 0, String *k = 0, // Swig_print_node(n); } - if (SwigType_istemplate(name)) { - String *temp = strip_namespaces(SwigType_templateprefix(name)); + String *tname = SwigType_istemplate_templateprefix(name); + if (tname) { + String *temp = strip_namespaces(tname); name = NewStringf("%s%s%s", temp, SwigType_templateargs(name), SwigType_templatesuffix(name)); + Delete(temp); + Delete(tname); } val = lookup_defined_foreign_type(k); @@ -630,7 +633,7 @@ void note_implicit_template_instantiation(SwigType *t) { add_defined_foreign_type(0, 0, t, t, implicit_ns ? implicit_ns : current_namespace); } -String *get_ffi_type(SwigType *ty, const_String_or_char_ptr name) { +String *get_ffi_type(Node *n, SwigType *ty, const_String_or_char_ptr name) { /* lookup defined foreign type. if it exists, it will return a form suitable for placing into lisp code to generate the def-foreign-type name */ @@ -645,18 +648,20 @@ String *get_ffi_type(SwigType *ty, const_String_or_char_ptr name) { #ifdef ALLEGROCL_TYPE_DEBUG Printf(stderr, "found_type '%s'\n", found_type); #endif - return (Strcmp(found_type, "forward-reference") ? Copy(found_type) : - get_ffi_type(fwdref_ffi_type, "")); + return (Strcmp(found_type, "forward-reference") ? Copy(found_type) : get_ffi_type(n, fwdref_ffi_type, "")); } else { - Hash *typemap = Swig_typemap_search("ffitype", ty, name, 0); - - if (typemap) { - String *typespec = Getattr(typemap, "code"); + Node *node = NewHash(); + Setattr(node, "type", ty); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup("ffitype", node, name, 0); + Delete(node); + if (tm) { #ifdef ALLEGROCL_TYPE_DEBUG - Printf(stderr, "g-f-t: found ffitype typemap '%s'\n%s\n", typespec, typemap); + Printf(stderr, "g-f-t: found ffitype typemap '%s'\n", tm); #endif - return NewString(typespec); + return NewString(tm); } if (SwigType_istemplate(ty)) { @@ -677,7 +682,7 @@ String *lookup_defined_foreign_ltype(String *l) { /* walk type and return string containing lisp version. recursive. */ -String *internal_compose_foreign_type(SwigType *ty) { +String *internal_compose_foreign_type(Node *n, SwigType *ty) { SwigType *tok; String *ffiType = NewString(""); @@ -695,18 +700,18 @@ String *internal_compose_foreign_type(SwigType *ty) { Printf(ffiType, "("); // start parm list for (Iterator i = First(pl); i.item; i = Next(i)) { SwigType *f_arg = SwigType_strip_qualifiers(i.item); - Printf(ffiType, "%s ", internal_compose_foreign_type(f_arg)); + Printf(ffiType, "%s ", internal_compose_foreign_type(n, f_arg)); Delete(f_arg); } Printf(ffiType, ")"); // end parm list. // do function return type. - Printf(ffiType, " %s)", internal_compose_foreign_type(ty)); + Printf(ffiType, " %s)", internal_compose_foreign_type(n, ty)); break; } else if (SwigType_ispointer(tok) || SwigType_isreference(tok)) { - Printf(ffiType, "(* %s)", internal_compose_foreign_type(ty)); + Printf(ffiType, "(* %s)", internal_compose_foreign_type(n, ty)); } else if (SwigType_isarray(tok)) { - Printf(ffiType, "(:array %s", internal_compose_foreign_type(ty)); + Printf(ffiType, "(:array %s", internal_compose_foreign_type(n, ty)); String *atype = NewString("int"); String *dim = convert_literal(SwigType_array_getdim(tok, 0), atype); Delete(atype); @@ -717,18 +722,18 @@ String *internal_compose_foreign_type(SwigType *ty) { } } else if (SwigType_ismemberpointer(tok)) { // temp - Printf(ffiType, "(* %s)", internal_compose_foreign_type(ty)); + Printf(ffiType, "(* %s)", internal_compose_foreign_type(n, ty)); } else { - String *res = get_ffi_type(tok, ""); + String *res = get_ffi_type(n, tok, ""); if (res) { Printf(ffiType, "%s", res); } else { - SwigType *resolved_type = SwigType_typedef_resolve(tok); - if (resolved_type) { - res = get_ffi_type(resolved_type, ""); + SwigType *resolved_type = SwigType_typedef_resolve_all(tok); + if (Cmp(resolved_type, tok) != 0) { + res = get_ffi_type(n, resolved_type, ""); if (res) { } else { - res = internal_compose_foreign_type(resolved_type); + res = internal_compose_foreign_type(n, resolved_type); } if (res) Printf(ffiType, "%s", res); @@ -766,7 +771,7 @@ String *internal_compose_foreign_type(SwigType *ty) { add_forward_referenced_type(nn, 0); // tok_name is dangling here, unused. ouch. why? - Printf(ffiType, "%s", get_ffi_type(tok, ""), tok_name); + Printf(ffiType, "%s", get_ffi_type(n, tok, ""), tok_name); } } } @@ -774,9 +779,7 @@ String *internal_compose_foreign_type(SwigType *ty) { return ffiType; } -String *compose_foreign_type(SwigType *ty, String * /*id*/ = 0) { - -/* Hash *lookup_res = Swig_typemap_search("ffitype", ty, id, 0); */ +String *compose_foreign_type(Node *n, SwigType *ty, String * /*id*/ = 0) { #ifdef ALLEGROCL_TYPE_DEBUG Printf(stderr, "compose_foreign_type: ENTER (%s)...\n ", ty); @@ -806,7 +809,7 @@ String *compose_foreign_type(SwigType *ty, String * /*id*/ = 0) { */ SwigType *temp = SwigType_strip_qualifiers(ty); - String *res = internal_compose_foreign_type(temp); + String *res = internal_compose_foreign_type(n, temp); Delete(temp); #ifdef ALLEGROCL_TYPE_DEBUG @@ -1089,11 +1092,12 @@ void emit_stub_class(Node *n) { if (Getattr(n, "allegrocl:synonym:already-been-stubbed")) return; - if (SwigType_istemplate(name)) { - String *temp = strip_namespaces(SwigType_templateprefix(name)); + String *tname = SwigType_istemplate_templateprefix(name); + if (tname) { + String *temp = strip_namespaces(tname); name = NewStringf("%s%s%s", temp, SwigType_templateargs(name), SwigType_templatesuffix(name)); - Delete(temp); + Delete(tname); } else { name = strip_namespaces(name); } @@ -1243,7 +1247,7 @@ void emit_full_class(Node *n) { #ifdef ALLEGROCL_WRAP_DEBUG Printf(stderr, "slot name = '%s' ns = '%s' class-of '%s' and type = '%s'\n", cname, ns, name, childType); #endif - Printf(slotdefs, "(#.(swig-insert-id \"%s\" %s :type :slot :class \"%s\") %s)", cname, ns, name, compose_foreign_type(childType)); + Printf(slotdefs, "(#.(swig-insert-id \"%s\" %s :type :slot :class \"%s\") %s)", cname, ns, name, compose_foreign_type(n, childType)); Delete(ns); if (access && Strcmp(access, "public")) Printf(slotdefs, " ;; %s member", access); @@ -1280,11 +1284,12 @@ void emit_class(Node *n) { String *ns_list = listify_namespace(Getattr(n, "allegrocl:namespace")); String *name = Getattr(n, is_tempInst ? "real-name" : "name"); - if (SwigType_istemplate(name)) { - String *temp = strip_namespaces(SwigType_templateprefix(name)); + String *tname = SwigType_istemplate_templateprefix(name); + if (tname) { + String *temp = strip_namespaces(tname); name = NewStringf("%s%s%s", temp, SwigType_templateargs(name), SwigType_templatesuffix(name)); - Delete(temp); + Delete(tname); } else { name = strip_namespaces(name); } @@ -1326,7 +1331,7 @@ void emit_typedef(Node *n) { String *name; String *sym_name = Getattr(n, "sym:name"); String *type = NewStringf("%s%s", Getattr(n, "decl"), Getattr(n, "type")); - String *lisp_type = compose_foreign_type(type); + String *lisp_type = compose_foreign_type(n, type); Delete(type); Node *in_class = Getattr(n, "allegrocl:typedef:in-class"); @@ -1339,10 +1344,12 @@ void emit_typedef(Node *n) { if (in_class) { String *class_name = Getattr(in_class, "name"); - if (SwigType_istemplate(class_name)) { - String *temp = strip_namespaces(SwigType_templateprefix(class_name)); + String *tname = SwigType_istemplate_templateprefix(class_name); + if (tname) { + String *temp = strip_namespaces(tname); class_name = NewStringf("%s%s%s", temp, SwigType_templateargs(class_name), SwigType_templatesuffix(class_name)); Delete(temp); + Delete(tname); } name = NewStringf("%s__%s", class_name, sym_name); @@ -1375,9 +1382,13 @@ void emit_enum_type_no_wrap(Node *n) { name = unnamed ? Getattr(n, "allegrocl:name") : Getattr(n, "sym:name"); SwigType *tmp = NewStringf("enum %s", unnamed ? unnamed : name); - Hash *typemap = Swig_typemap_search("ffitype", tmp, 0, 0); - String *enumtype = Getattr(typemap, "code"); - // enumtype = compose_foreign_type(tmp); + Node *node = NewHash(); + Setattr(node, "type", tmp); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *enumtype = Swig_typemap_lookup("ffitype", node, "", 0); + Delete(node); + Delete(tmp); if (name) { @@ -1431,12 +1442,14 @@ void emit_enum_type(Node *n) { name = unnamed ? Getattr(n, "allegrocl:name") : Getattr(n, "sym:name"); SwigType *tmp = NewStringf("enum %s", unnamed ? unnamed : name); - // SwigType *tmp = NewStringf("enum ACL_SWIG_ENUM_NAME"); - Hash *typemap = Swig_typemap_search("ffitype", tmp, 0, 0); - String *enumtype = Getattr(typemap, "code"); + Node *node = NewHash(); + Setattr(node, "type", tmp); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *enumtype = Swig_typemap_lookup("ffitype", node, "", 0); + Delete(node); - // enumtype = compose_foreign_type(tmp); Delete(tmp); if (name) { @@ -1801,13 +1814,13 @@ static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { String *t2 = Getattr(p2, "tmap:typecheck:precedence"); if ((!t1) && (!nodes[i].error)) { Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n), - "Overloaded %s(%s) not supported (no type checking rule for '%s').\n", - Getattr(nodes[i].n, "name"), ParmList_str_defaultargs(Getattr(nodes[i].n, "parms")), SwigType_str(Getattr(p1, "type"), 0)); + "Overloaded method %s not supported (no type checking rule for '%s').\n", + Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0)); nodes[i].error = 1; } else if ((!t2) && (!nodes[j].error)) { Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded %s(%s) not supported (no type checking rule for '%s').\n", - Getattr(nodes[j].n, "name"), ParmList_str_defaultargs(Getattr(nodes[j].n, "parms")), SwigType_str(Getattr(p2, "type"), 0)); + "Overloaded method %s not supported (no type checking rule for '%s').\n", + Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0)); nodes[j].error = 1; } if (t1 && t2) { @@ -1898,14 +1911,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; @@ -1914,14 +1928,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; @@ -1935,19 +1950,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 %s(%s)%s is shadowed by %s(%s)%s at %s:%d.\n", - Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms), - SwigType_isconst(Getattr(nodes[j].n, "decl")) ? " const" : "", - Getattr(nodes[i].n, "name"), ParmList_errorstr(nodes[i].parms), - SwigType_isconst(Getattr(nodes[i].n, "decl")) ? " const" : "", 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(%s)%s ignored. Method %s(%s)%s at %s:%d used.\n", - Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms), - SwigType_isconst(Getattr(nodes[j].n, "decl")) ? " const" : "", - Getattr(nodes[i].n, "name"), ParmList_errorstr(nodes[i].parms), - SwigType_isconst(Getattr(nodes[i].n, "decl")) ? " const" : "", 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; } @@ -1983,14 +1994,16 @@ int any_varargs(ParmList *pl) { return 0; } -String *get_lisp_type(SwigType *ty, const_String_or_char_ptr name) { - Hash *typemap = Swig_typemap_search("lisptype", ty, name, 0); - if (typemap) { - String *typespec = Getattr(typemap, "code"); - return NewString(typespec); - } else { - return NewString(""); - } +String *get_lisp_type(Node *n, SwigType *ty, const_String_or_char_ptr name) { + Node *node = NewHash(); + Setattr(node, "type", ty); + Setattr(node, "name", name); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup("lisptype", node, "", 0); + Delete(node); + + return tm ? NewString(tm) : NewString(""); } Node *parent_node_skipping_extends(Node *n) { @@ -2006,7 +2019,7 @@ Node *parent_node_skipping_extends(Node *n) { * emit_num_lin_arguments() * * Calculate the total number of arguments. This function is safe for use - * with multi-valued typemaps which may change the number of arguments in + * with multi-argument typemaps which may change the number of arguments in * strange ways. * ----------------------------------------------------------------------------- */ @@ -2278,18 +2291,21 @@ int ALLEGROCL::emit_buffered_defuns(Node *n) { return SWIG_OK; } -String *dispatching_type(Parm *p) { +String *dispatching_type(Node *n, Parm *p) { String *result = 0; String *parsed = Getattr(p, "type"); //Swig_cparse_type(Getattr(p,"tmap:ctype")); String *cl_t = SwigType_typedef_resolve_all(parsed); - Hash *typemap = Swig_typemap_search("lispclass", parsed, Getattr(p, "name"), 0); - // Printf(stderr,"inspecting type '%s' for class\n", parsed); - // Printf(stderr," cfcocr = '%s' res_all = '%s'\n", - // class_from_class_or_class_ref(parsed), cl_t); - if (typemap) { - result = Copy(Getattr(typemap, "code")); + Node *node = NewHash(); + Setattr(node, "type", parsed); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup("lispclass", node, Getattr(p, "name"), 0); + Delete(node); + + if (tm) { + result = Copy(tm); } else { String *lookup_type = class_from_class_or_class_ref(parsed); if (lookup_type) @@ -2309,24 +2325,6 @@ String *dispatching_type(Parm *p) { return result; } -String *defmethod_lambda_list(Node *overload) { - String *result = NewString(""); - - ParmList *parms = Getattr(overload, "wrap:parms"); - Parm *p; - int a; - - for (a = 0, p = parms; p; p = nextSibling(p), ++a) { - if (a != 0) - Printf(result, " "); - Printf(result, "(arg%d ", a); - Printf(result, "%s", dispatching_type(p)); - Printf(result, ")"); - } - - return result; -} - int ALLEGROCL::emit_dispatch_defun(Node *n) { #ifdef ALLEGROCL_WRAP_DEBUG Printf(stderr, "emit_dispatch_defun: ENTER... "); @@ -2433,9 +2431,9 @@ int ALLEGROCL::emit_defun(Node *n, File *fcl) { String *argname = NewStringf("PARM%d_%s", largnum, Getattr(p, "name")); // Printf(stderr,"%s\n", Getattr(p,"tmap:lin")); - String *ffitype = compose_foreign_type(argtype, Getattr(p,"name")); + String *ffitype = compose_foreign_type(n, argtype, Getattr(p,"name")); String *deref_ffitype = dereference_ffitype(ffitype); - String *lisptype = get_lisp_type(parmtype, Getattr(p, "name")); + String *lisptype = get_lisp_type(n, parmtype, Getattr(p, "name")); #ifdef ALLEGROCL_DEBUG Printf(stderr, "lisptype of '%s' '%s' = '%s'\n", parmtype, @@ -2458,7 +2456,7 @@ int ALLEGROCL::emit_defun(Node *n, File *fcl) { Replaceall(wrap->code, "$body", parm_code); } - String *dispatchtype = Getattr(n, "sym:overloaded") ? dispatching_type(p) : NewString(""); + String *dispatchtype = Getattr(n, "sym:overloaded") ? dispatching_type(n, p) : NewString(""); // if this parameter has been removed from the C/++ wrapper // it shouldn't be in the lisp wrapper either. @@ -2489,13 +2487,13 @@ int ALLEGROCL::emit_defun(Node *n, File *fcl) { SwigType *parsed = Swig_cparse_type(Getattr(n, "tmap:ctype")); // SwigType *cl_t = SwigType_typedef_resolve_all(parsed); SwigType *cl_t = class_from_class_or_class_ref(parsed); - String *out_ffitype = compose_foreign_type(parsed); + String *out_ffitype = compose_foreign_type(n, parsed); String *deref_out_ffitype; String *out_temp = Copy(parsed); if (SwigType_ispointer(out_temp)) { SwigType_pop(out_temp); - deref_out_ffitype = compose_foreign_type(out_temp); + deref_out_ffitype = compose_foreign_type(n, out_temp); } else { deref_out_ffitype = Copy(out_ffitype); } @@ -2551,7 +2549,7 @@ int ALLEGROCL::emit_defun(Node *n, File *fcl) { ///////////////////////////////////////////////////// // Lisp foreign call return type and optimizations // ///////////////////////////////////////////////////// - Printf(fcl, " (:returning (%s %s)", compose_foreign_type(result_type), get_lisp_type(Getattr(n, "type"), "result")); + Printf(fcl, " (:returning (%s %s)", compose_foreign_type(n, result_type), get_lisp_type(n, Getattr(n, "type"), "result")); for (Iterator option = First(n); option.item; option = Next(option)) { if (Strncmp("feature:ffargs:", option.key, 15)) @@ -2930,10 +2928,6 @@ int ALLEGROCL::variableWrapper(Node *n) { Printf(f_runtime, "EXPORT %s %s;\n%s %s = %s%s;\n", ctype, mangled_name, ctype, mangled_name, (pointer_added ? "&" : ""), name); Printf(f_cl, "(swig-defvar \"%s\" :type %s)\n", mangled_name, ((SwigType_isconst(type)) ? ":constant" : ":variable")); - /* - Printf(f_runtime, "// swigtype: %s\n", SwigType_typedef_resolve_all(Getattr(n,"type"))); - Printf(f_runtime, "// vwrap: %s\n", compose_foreign_type(SwigType_strip_qualifiers(Copy(rtype)))); - */ Printf(stderr,"***\n"); Delete(mangled_name); @@ -2975,7 +2969,7 @@ int ALLEGROCL::typedefHandler(Node *n) { SwigType *typedef_type = Getattr(n,"type"); // has the side-effect of noting any implicit // template instantiations in type. - String *ff_type = compose_foreign_type(typedef_type); + String *ff_type = compose_foreign_type(n, typedef_type); String *sym_name = Getattr(n, "sym:name"); @@ -3136,7 +3130,7 @@ int ALLEGROCL::cppClassHandler(Node *n) { Printf(stderr, "looking at child '%x' of type '%s'\n", c, childType); #endif if (!SwigType_isfunction(childType)) - Delete(compose_foreign_type(childType)); + Delete(compose_foreign_type(n, childType)); Delete(childType); } diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx index 31f27e1eb..2e05fd190 100644 --- a/Source/Modules/allocate.cxx +++ b/Source/Modules/allocate.cxx @@ -522,7 +522,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); @@ -531,8 +531,7 @@ class Allocate:public Dispatcher { } ParmList *throws = Getattr(n, "throws"); if (throws) { - /* if there is no an explicit catchlist, - we catch everything in the throwlist */ + /* if there is no explicit catchlist, we catch everything in the throws list */ if (!catchlist) { Setattr(n, "catchlist", throws); } diff --git a/Source/Modules/cffi.cxx b/Source/Modules/cffi.cxx index c8c431e47..53c44ff66 100644 --- a/Source/Modules/cffi.cxx +++ b/Source/Modules/cffi.cxx @@ -622,12 +622,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); @@ -692,7 +692,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")); @@ -762,7 +762,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); @@ -791,12 +791,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); @@ -823,21 +823,24 @@ void CFFI::emit_struct_union(Node *n, bool un = false) { // Getattr(c, "type")); // SWIG_exit(EXIT_FAILURE); } else { - SwigType *childType = NewStringf("%s%s", Getattr(c, "decl"), - Getattr(c, "type")); + SwigType *childType = NewStringf("%s%s", Getattr(c, "decl"), Getattr(c, "type")); - Hash *typemap = Swig_typemap_search("cin", childType, "", 0); - String *typespec = NewString(""); - if (typemap) { - typespec = NewString(Getattr(typemap, "code")); - } + Node *node = NewHash(); + Setattr(node, "type", childType); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup("cin", node, "", 0); + + String *typespec = tm ? NewString(tm) : NewString(""); String *slot_name = lispify_name(c, Getattr(c, "sym:name"), "'slotname"); if (Strcmp(slot_name, "t") == 0 || Strcmp(slot_name, "T") == 0) - slot_name = NewStringf("t_var"); + slot_name = NewStringf("t_var"); Printf(f_cl, "\n\t(%s %s)", slot_name, typespec); + Delete(node); + Delete(childType); Delete(typespec); } } diff --git a/Source/Modules/clisp.cxx b/Source/Modules/clisp.cxx index 95ee66bc9..b1a6f5610 100644 --- a/Source/Modules/clisp.cxx +++ b/Source/Modules/clisp.cxx @@ -29,7 +29,7 @@ public: virtual int typedefHandler(Node *n); List *entries; private: - String *get_ffi_type(SwigType *ty); + String *get_ffi_type(Node *n, SwigType *ty); String *convert_literal(String *num_param, String *type); String *strip_parens(String *string); int extern_all_flag; @@ -171,7 +171,7 @@ int CLISP::functionWrapper(Node *n) { String *argname = Getattr(p, "name"); // SwigType *argtype; - String *ffitype = get_ffi_type(Getattr(p, "type")); + String *ffitype = get_ffi_type(n, Getattr(p, "type")); int tempargname = 0; @@ -194,7 +194,7 @@ int CLISP::functionWrapper(Node *n) { if (ParmList_len(pl) != 0) { Printf(f_cl, ")\n"); /* finish arg list */ } - String *ffitype = get_ffi_type(Getattr(n, "type")); + String *ffitype = get_ffi_type(n, Getattr(n, "type")); if (Strcmp(ffitype, "NIL")) { //when return type is not nil Printf(f_cl, "\t(:return-type %s)\n", ffitype); } @@ -226,7 +226,7 @@ int CLISP::variableWrapper(Node *n) { return SWIG_OK; String *var_name = Getattr(n, "sym:name"); - String *lisp_type = get_ffi_type(Getattr(n, "type")); + String *lisp_type = get_ffi_type(n, Getattr(n, "type")); Printf(f_cl, "\n(ffi:def-c-var %s\n (:name \"%s\")\n (:type %s)\n", var_name, var_name, lisp_type); Printf(f_cl, "\t(:library +library-name+))\n"); Append(entries, var_name); @@ -238,7 +238,7 @@ int CLISP::variableWrapper(Node *n) { int CLISP::typedefHandler(Node *n) { if (generate_typedef_flag) { is_function = 0; - Printf(f_cl, "\n(ffi:def-c-type %s %s)\n", Getattr(n, "name"), get_ffi_type(Getattr(n, "type"))); + Printf(f_cl, "\n(ffi:def-c-type %s %s)\n", Getattr(n, "name"), get_ffi_type(n, Getattr(n, "type"))); } return Language::typedefHandler(n); @@ -294,7 +294,7 @@ int CLISP::classDeclaration(Node *n) { String *temp = Copy(Getattr(c, "decl")); Append(temp, Getattr(c, "type")); //appending type to the end, otherwise wrong type - String *lisp_type = get_ffi_type(temp); + String *lisp_type = get_ffi_type(n, temp); Delete(temp); String *slot_name = Getattr(c, "sym:name"); @@ -375,15 +375,20 @@ String *CLISP::convert_literal(String *num_param, String *type) { return res; } -String *CLISP::get_ffi_type(SwigType *ty) { - Hash *typemap = Swig_typemap_search("in", ty, "", 0); - if (typemap) { - String *typespec = Getattr(typemap, "code"); - return NewString(typespec); +String *CLISP::get_ffi_type(Node *n, SwigType *ty) { + Node *node = NewHash(); + Setattr(node, "type", ty); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup("in", node, "", 0); + Delete(node); + + if (tm) { + return NewString(tm); } else if (SwigType_ispointer(ty)) { SwigType *cp = Copy(ty); SwigType_del_pointer(cp); - String *inner_type = get_ffi_type(cp); + String *inner_type = get_ffi_type(n, cp); if (SwigType_isfunction(cp)) { return inner_type; @@ -413,12 +418,12 @@ String *CLISP::get_ffi_type(SwigType *ty) { Delete(array_dim); SwigType_del_array(cp); SwigType_add_pointer(cp); - String *str = get_ffi_type(cp); + String *str = get_ffi_type(n, cp); Delete(cp); return str; } else { SwigType_pop_arrays(cp); - String *inner_type = get_ffi_type(cp); + String *inner_type = get_ffi_type(n, cp); Delete(cp); int ndim = SwigType_array_ndim(ty); @@ -451,7 +456,7 @@ String *CLISP::get_ffi_type(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 "); } @@ -459,7 +464,7 @@ String *CLISP::get_ffi_type(SwigType *ty) { for (Parm *p = pl; p; p = nextSibling(p), argnum++) { String *argname = Getattr(p, "name"); SwigType *argtype = Getattr(p, "type"); - String *ffitype = get_ffi_type(argtype); + String *ffitype = get_ffi_type(n, argtype); int tempargname = 0; @@ -479,7 +484,7 @@ String *CLISP::get_ffi_type(SwigType *ty) { if (ParmList_len(pl) != 0) { Printf(args, ")\n"); /* finish arg list */ } - String *ffitype = get_ffi_type(cp); + String *ffitype = get_ffi_type(n, cp); String *str = NewStringf("(ffi:c-function %s \t\t\t\t(:return-type %s))", args, ffitype); Delete(fn); Delete(args); diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 34f4d69f3..d813c2e56 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -90,13 +90,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: /* ----------------------------------------------------------------------------- @@ -341,6 +334,10 @@ public: module_class_name = Copy(Getattr(n, "name")); } + // module class and intermediary classes are always created + addSymbol(imclass_name, n); + addSymbol(module_class_name, n); + imclass_class_code = NewString(""); proxy_class_def = NewString(""); proxy_class_code = NewString(""); @@ -390,10 +387,10 @@ public: Printf(f_runtime, "\n"); - Swig_name_register((char *) "wrapper", (char *) "CSharp_%f"); + Swig_name_register("wrapper", "CSharp_%f"); if (old_variable_names) { - Swig_name_register((char *) "set", (char *) "set_%v"); - Swig_name_register((char *) "get", (char *) "get_%v"); + Swig_name_register("set", "set_%v"); + Swig_name_register("get", "get_%v"); } Printf(f_wrappers, "\n#ifdef __cplusplus\n"); @@ -682,7 +679,7 @@ public: virtual int nativeWrapper(Node *n) { String *wrapname = Getattr(n, "wrap:name"); - if (!addSymbol(wrapname, n)) + if (!addSymbol(wrapname, n, imclass_name)) return SWIG_ERROR; if (Getattr(n, "type")) { @@ -722,7 +719,7 @@ public: String *overloaded_name = getOverloadedName(n); if (!Getattr(n, "sym:overloaded")) { - if (!addSymbol(Getattr(n, "sym:name"), n)) + if (!addSymbol(Getattr(n, "sym:name"), n, imclass_name)) return SWIG_ERROR; } @@ -902,9 +899,9 @@ public: } } - // Get any C# exception classes in the throws typemap + // Look for usage of throws typemap and the canthrow flag ParmList *throw_parm_list = NULL; - if ((throw_parm_list = Getattr(n, "throws"))) { + if ((throw_parm_list = Getattr(n, "catchlist"))) { Swig_typemap_attach_parms("throws", throw_parm_list, f); for (p = throw_parm_list; p; p = nextSibling(p)) { if ((tm = Getattr(p, "tmap:throws"))) { @@ -1119,16 +1116,16 @@ public: // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum // Pure C# baseclass and interfaces - const String *pure_baseclass = typemapLookup("csbase", typemap_lookup_type, WARN_NONE); - const String *pure_interfaces = typemapLookup("csinterfaces", typemap_lookup_type, WARN_NONE); + const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE); + const String *pure_interfaces = typemapLookup(n, "csinterfaces", typemap_lookup_type, WARN_NONE); // Class attributes - const String *csattributes = typemapLookup("csattributes", typemap_lookup_type, WARN_NONE); + const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE); if (csattributes && *Char(csattributes)) Printf(enum_code, "%s\n", csattributes); // Emit the enum - Printv(enum_code, typemapLookup("csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really) + Printv(enum_code, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really) " ", symname, (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces ", " : "", pure_interfaces, " {\n", NIL); } else { @@ -1144,8 +1141,8 @@ public: // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum // Finish the enum declaration // Typemaps are used to generate the enum definition in a similar manner to proxy classes. - Printv(enum_code, (enum_feature == ProperEnum) ? "\n" : typemapLookup("csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class - typemapLookup("cscode", typemap_lookup_type, WARN_NONE), // extra C# code + Printv(enum_code, (enum_feature == ProperEnum) ? "\n" : typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class + typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code "}", NIL); Replaceall(enum_code, "$csclassname", symname); @@ -1181,7 +1178,7 @@ public: addOpenNamespace(namespce, f_enum); - Printv(f_enum, typemapLookup("csimports", typemap_lookup_type, WARN_NONE), // Import statements + Printv(f_enum, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements "\n", enum_code, "\n", NIL); addCloseNamespace(namespce, f_enum); @@ -1215,6 +1212,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 @@ -1226,13 +1226,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 (!Getattr(n, "_last")) // Only the first enum item has this attribute set + 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 @@ -1245,21 +1250,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"); - const String *tm = typemapLookup("cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF); + 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); @@ -1271,6 +1274,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); @@ -1279,9 +1286,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); } @@ -1310,11 +1317,13 @@ public: String *return_type = NewString(""); String *constants_code = NewString(""); - if (!addSymbol(symname, n)) - return SWIG_ERROR; - bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0); + const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname; + String *scope = proxy_flag && wrapping_member_flag ? proxy_class_name : module_class_name; + if (!addSymbol(itemname, n, scope)) + return SWIG_ERROR; + // The %csconst feature determines how the constant value is obtained int const_feature_flag = GetFlag(n, "feature:cs:const"); @@ -1355,7 +1364,6 @@ public: const String *outattributes = Getattr(n, "tmap:cstype:outattributes"); if (outattributes) Printf(constants_code, " %s\n", outattributes); - const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname; const String *methodmods = Getattr(n, "feature:cs:methodmodifiers"); methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); @@ -1388,7 +1396,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 @@ -1494,12 +1509,12 @@ public: String *c_baseclass = NULL; String *baseclass = NULL; String *c_baseclassname = NULL; - String *typemap_lookup_type = Getattr(n, "classtypeobj"); + SwigType *typemap_lookup_type = Getattr(n, "classtypeobj"); bool feature_director = Swig_directorclass(n) ? true : false; // Inheritance from pure C# classes Node *attributes = NewHash(); - const String *pure_baseclass = typemapLookup("csbase", typemap_lookup_type, WARN_NONE, attributes); + const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE, attributes); bool purebase_replace = GetFlag(attributes, "tmap:csbase:replace") ? true : false; bool purebase_notderived = GetFlag(attributes, "tmap:csbase:notderived") ? true : false; Delete(attributes); @@ -1553,21 +1568,21 @@ public: } // Pure C# interfaces - const String *pure_interfaces = typemapLookup(derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE); + const String *pure_interfaces = typemapLookup(n, derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE); // Start writing the proxy class - Printv(proxy_class_def, typemapLookup("csimports", typemap_lookup_type, WARN_NONE), // Import statements + Printv(proxy_class_def, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements "\n", NIL); // Class attributes - const String *csattributes = typemapLookup("csattributes", typemap_lookup_type, WARN_NONE); + const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE); if (csattributes && *Char(csattributes)) Printf(proxy_class_def, "%s\n", csattributes); - Printv(proxy_class_def, typemapLookup("csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers + Printv(proxy_class_def, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers " $csclassname", // Class name and base class (*Char(wanted_base) || *Char(pure_interfaces)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(pure_interfaces)) ? // Interfaces - ", " : "", pure_interfaces, " {", derived ? typemapLookup("csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class - typemapLookup("csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class + ", " : "", pure_interfaces, " {", derived ? typemapLookup(n, "csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class + typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class NIL); // C++ destructor is wrapped by the Dispose method @@ -1578,11 +1593,11 @@ public: String *destruct_methodname = NULL; String *destruct_methodmodifiers = NULL; if (derived) { - tm = typemapLookup("csdestruct_derived", typemap_lookup_type, WARN_NONE, attributes); + tm = typemapLookup(n, "csdestruct_derived", typemap_lookup_type, WARN_NONE, attributes); destruct_methodname = Getattr(attributes, "tmap:csdestruct_derived:methodname"); destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct_derived:methodmodifiers"); } else { - tm = typemapLookup("csdestruct", typemap_lookup_type, WARN_NONE, attributes); + tm = typemapLookup(n, "csdestruct", typemap_lookup_type, WARN_NONE, attributes); destruct_methodname = Getattr(attributes, "tmap:csdestruct:methodname"); destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct:methodmodifiers"); } @@ -1599,7 +1614,7 @@ public: if (tm) { // Finalize method if (*Char(destructor_call)) { - Printv(proxy_class_def, typemapLookup("csfinalize", typemap_lookup_type, WARN_NONE), NIL); + Printv(proxy_class_def, typemapLookup(n, "csfinalize", typemap_lookup_type, WARN_NONE), NIL); } // Dispose method Printv(destruct, tm, NIL); @@ -1694,7 +1709,7 @@ public: Delete(destruct); // Emit extra user code - Printv(proxy_class_def, typemapLookup("cscode", typemap_lookup_type, WARN_NONE), // extra C# code + Printv(proxy_class_def, typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code "\n", NIL); // Substitute various strings into the above template @@ -2359,7 +2374,7 @@ public: /* Insert the csconstruct typemap, doing the replacement for $directorconnect, as needed */ Hash *attributes = NewHash(); - String *construct_tm = Copy(typemapLookup("csconstruct", Getattr(n, "name"), + String *construct_tm = Copy(typemapLookup(n, "csconstruct", Getattr(n, "name"), WARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF, attributes)); if (construct_tm) { if (!feature_director) { @@ -2770,6 +2785,16 @@ public: Delete(func_name); } + /*---------------------------------------------------------------------- + * replaceSpecialVariables() + *--------------------------------------------------------------------*/ + + virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) { + (void)method; + SwigType *type = Getattr(parm, "type"); + substituteClassname(type, tm); + } + /*---------------------------------------------------------------------- * decodeEnumFeature() * Decode the possible enum features, which are one of: @@ -2863,15 +2888,15 @@ public: /* ----------------------------------------------------------------------------- * substituteClassname() * - * Substitute $csclassname with the proxy class name for classes/structs/unions that SWIG knows about. - * Also substitutes enums with enum name. + * Substitute the special variable $csclassname with the proxy class name for classes/structs/unions + * that SWIG knows about. Also substitutes enums with enum name. * Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution * is the same as a $&descriptor substitution, ie one pointer added to descriptor name. * Inputs: * pt - parameter type - * tm - cstype typemap + * tm - typemap contents that might contain the special variable to be replaced * Outputs: - * tm - cstype typemap with $csclassname substitution + * tm - typemap contents complete with the special variable substitution * Return: * substitution_performed - flag indicating if a substitution was performed * ----------------------------------------------------------------------------- */ @@ -2976,6 +3001,10 @@ public: * ----------------------------------------------------------------------------- */ void emitTypeWrapperClass(String *classname, SwigType *type) { + Node *n = NewHash(); + Setfile(n, input_file); + Setline(n, line_number); + String *swigtype = NewString(""); String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), classname); File *f_swigtype = NewFile(filen, "w", SWIG_output_files()); @@ -2993,23 +3022,23 @@ public: addOpenNamespace(namespce, f_swigtype); // Pure C# baseclass and interfaces - const String *pure_baseclass = typemapLookup("csbase", type, WARN_NONE); - const String *pure_interfaces = typemapLookup("csinterfaces", type, WARN_NONE); + const String *pure_baseclass = typemapLookup(n, "csbase", type, WARN_NONE); + const String *pure_interfaces = typemapLookup(n, "csinterfaces", type, WARN_NONE); // Emit the class - Printv(swigtype, typemapLookup("csimports", type, WARN_NONE), // Import statements + Printv(swigtype, typemapLookup(n, "csimports", type, WARN_NONE), // Import statements "\n", NIL); // Class attributes - const String *csattributes = typemapLookup("csattributes", type, WARN_NONE); + const String *csattributes = typemapLookup(n, "csattributes", type, WARN_NONE); if (csattributes && *Char(csattributes)) Printf(swigtype, "%s\n", csattributes); - Printv(swigtype, typemapLookup("csclassmodifiers", type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers + Printv(swigtype, typemapLookup(n, "csclassmodifiers", type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers " $csclassname", // Class name and base class (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces - ", " : "", pure_interfaces, " {", typemapLookup("csbody", type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class - typemapLookup("cscode", type, WARN_NONE), // extra C# code + ", " : "", pure_interfaces, " {", typemapLookup(n, "csbody", type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class + typemapLookup(n, "cscode", type, WARN_NONE), // extra C# code "}\n", NIL); Replaceall(swigtype, "$csclassname", classname); @@ -3023,36 +3052,34 @@ public: Close(f_swigtype); Delete(swigtype); + Delete(n); } /* ----------------------------------------------------------------------------- * typemapLookup() + * n - for input only and must contain info for Getfile(n) and Getline(n) to work + * tmap_method - typemap method name + * type - typemap type to lookup + * warning - warning number to issue if no typemaps found + * typemap_attributes - the typemap attributes are attached to this node and will + * also be used for temporary storage if non null + * return is never NULL, unlike Swig_typemap_lookup() * ----------------------------------------------------------------------------- */ - const String *typemapLookup(const String *op, String *type, int warning, Node *typemap_attributes = NULL) { - String *tm = NULL; - const String *code = NULL; - - if ((tm = Swig_typemap_search(op, type, NULL, NULL))) { - code = Getattr(tm, "code"); - if (typemap_attributes) - Swig_typemap_attach_kwargs(tm, op, typemap_attributes); - } - - if (!code) { - code = empty_string; + const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) { + Node *node = !typemap_attributes ? NewHash() : typemap_attributes; + Setattr(node, "type", type); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0); + if (!tm) { + tm = empty_string; if (warning != WARN_NONE) - Swig_warning(warning, input_file, line_number, "No %s typemap defined for %s\n", op, type); + Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0)); } - - return code ? code : empty_string; - } - - /* ----------------------------------------------------------------------------- - * addThrows() - // TODO: remove - * ----------------------------------------------------------------------------- */ - void addThrows(Node *, const String *, Node *) { + if (!typemap_attributes) + Delete(node); + return tm; } /* ----------------------------------------------------------------------------- @@ -3306,7 +3333,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) { @@ -3326,7 +3353,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))) { @@ -3336,7 +3363,8 @@ public: Delete(jretval_decl); } } else { - Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(returntype, 0)); + Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; } @@ -3401,10 +3429,6 @@ public: Printf(arg, "j%s", ln); - /* Add various typemap's 'throws' clauses */ - addThrows(n, "tmap:directorin", p); - addThrows(n, "tmap:out", p); - /* And add to the upcall args */ if (gencomma > 0) Printf(jupcall_args, ", "); @@ -3416,7 +3440,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 */ @@ -3479,11 +3503,13 @@ public: Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0)); } } else { - Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number, "No csdirectorin typemap defined for %s\n", SwigType_str(pt, 0)); + Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number, "No csdirectorin typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; } } else { - Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0)); + Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; } @@ -3493,11 +3519,13 @@ public: } else { if (!desc_tm) { Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number, - "No or improper directorin typemap defined for %s\n", SwigType_str(c_param_type, 0)); + "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); p = nextSibling(p); } else if (!tm) { Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number, - "No or improper directorin typemap defined for argument %s\n", SwigType_str(pt, 0)); + "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n", + SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); p = nextSibling(p); } @@ -3506,7 +3534,8 @@ public: Delete(tp); } else { - Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0)); + Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; p = nextSibling(p); } @@ -3528,9 +3557,8 @@ public: Printf(declaration, " virtual %s", target); Delete(target); - // Get any Java exception classes in the throws typemap + // Add any exception specifications to the methods in the director class ParmList *throw_parm_list = NULL; - if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { int gencomma = 0; @@ -3541,13 +3569,10 @@ public: Swig_typemap_attach_parms("throws", throw_parm_list, 0); for (p = throw_parm_list; p; p = nextSibling(p)) { if ((tm = Getattr(p, "tmap:throws"))) { - addThrows(n, "tmap:throws", p); - if (gencomma++) { Append(w->def, ", "); Append(declaration, ", "); } - Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0)); Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0)); } @@ -3570,7 +3595,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); @@ -3596,18 +3621,17 @@ 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))) { - addThrows(n, "tmap:directorout", tp); Replaceall(tm, "$input", jresult_str); Replaceall(tm, "$result", result_str); Printf(w->code, "%s\n", tm); } else { Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number, - "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0), - SwigType_namestr(c_classname), SwigType_namestr(name)); + "Unable to use return type %s used in %s::%s (skipping director method)\n", + SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; } @@ -3818,7 +3842,7 @@ public: Node *disconn_attr = NewHash(); String *disconn_methodname = NULL; - disconn_tm = typemapLookup("directordisconnect", full_classname, WARN_NONE, disconn_attr); + disconn_tm = typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr); disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname"); Printv(w->code, "}\n", NIL); diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx index fde3b2457..ed75e4d74 100644 --- a/Source/Modules/emit.cxx +++ b/Source/Modules/emit.cxx @@ -204,7 +204,7 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) { * emit_num_arguments() * * Calculate the total number of arguments. This function is safe for use - * with multi-valued typemaps which may change the number of arguments in + * with multi-argument typemaps which may change the number of arguments in * strange ways. * ----------------------------------------------------------------------------- */ @@ -236,7 +236,7 @@ int emit_num_arguments(ParmList *parms) { * emit_num_required() * * Computes the number of required arguments. This function is safe for - * use with multi-valued typemaps and knows how to skip over everything + * use with multi-argument typemaps and knows how to skip over everything * properly. Note that parameters with default values are counted unless * the compact default args option is on. * ----------------------------------------------------------------------------- */ diff --git a/Source/Modules/guile.cxx b/Source/Modules/guile.cxx index 05ceced22..9e0f43daf 100644 --- a/Source/Modules/guile.cxx +++ b/Source/Modules/guile.cxx @@ -1411,16 +1411,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 5135fd74e..7a9d739f1 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -51,6 +51,7 @@ class JAVA:public Language { String *imclass_name; // intermediary class name String *module_class_name; // module class name + String *constants_interface_name; // constants interface name String *imclass_class_code; // intermediary class code String *proxy_class_def; String *proxy_class_code; @@ -87,13 +88,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: /* ----------------------------------------------------------------------------- @@ -125,6 +119,7 @@ public: member_func_flag(false), imclass_name(NULL), module_class_name(NULL), + constants_interface_name(NULL), imclass_class_code(NULL), proxy_class_def(NULL), proxy_class_code(NULL), @@ -349,6 +344,11 @@ public: else module_class_name = Copy(Getattr(n, "name")); } + constants_interface_name = NewStringf("%sConstants", module_class_name); + + // module class and intermediary classes are always created + addSymbol(imclass_name, n); + addSymbol(module_class_name, n); imclass_class_code = NewString(""); proxy_class_def = NewString(""); @@ -413,10 +413,10 @@ public: Printf(wrapper_name, "Java_%s%s_%%f", Char(jnipackage), jniname); Delete(jniname); - Swig_name_register((char *) "wrapper", Char(wrapper_name)); + Swig_name_register("wrapper", Char(wrapper_name)); if (old_variable_names) { - Swig_name_register((char *) "set", (char *) "set_%v"); - Swig_name_register((char *) "get", (char *) "get_%v"); + Swig_name_register("set", "set_%v"); + Swig_name_register("get", "get_%v"); } Delete(wrapper_name); @@ -512,12 +512,12 @@ public: Printf(f_module, "extends %s ", module_baseclass); if (Len(module_interfaces) > 0) { if (Len(module_class_constants_code) != 0) - Printv(f_module, "implements ", Getattr(n, "name"), "Constants, ", module_interfaces, " ", NIL); + Printv(f_module, "implements ", constants_interface_name, ", ", module_interfaces, " ", NIL); else Printv(f_module, "implements ", module_interfaces, " ", NIL); } else { if (Len(module_class_constants_code) != 0) - Printv(f_module, "implements ", Getattr(n, "name"), "Constants ", NIL); + Printv(f_module, "implements ", constants_interface_name, " ", NIL); } Printf(f_module, "{\n"); @@ -537,7 +537,7 @@ public: // Generate the Java constants interface if (Len(module_class_constants_code) != 0) { - String *filen = NewStringf("%s%sConstants.java", SWIG_output_directory(), module_class_name); + String *filen = NewStringf("%s%s.java", SWIG_output_directory(), constants_interface_name); File *f_module = NewFile(filen, "w", SWIG_output_files()); if (!f_module) { FileErrorDisplay(filen); @@ -556,7 +556,7 @@ public: if (module_imports) Printf(f_module, "%s\n", module_imports); - Printf(f_module, "public interface %sConstants {\n", module_class_name); + Printf(f_module, "public interface %s {\n", constants_interface_name); // Write out all the global constants Printv(f_module, module_class_constants_code, NIL); @@ -621,6 +621,8 @@ public: imclass_class_modifiers = NULL; Delete(module_class_name); module_class_name = NULL; + Delete(constants_interface_name); + constants_interface_name = NULL; Delete(module_class_code); module_class_code = NULL; Delete(module_baseclass); @@ -750,7 +752,7 @@ public: virtual int nativeWrapper(Node *n) { String *wrapname = Getattr(n, "wrap:name"); - if (!addSymbol(wrapname, n)) + if (!addSymbol(wrapname, n, imclass_name)) return SWIG_ERROR; if (Getattr(n, "type")) { @@ -792,7 +794,7 @@ public: bool is_destructor = (Cmp(Getattr(n, "nodeType"), "destructor") == 0); if (!Getattr(n, "sym:overloaded")) { - if (!addSymbol(Getattr(n, "sym:name"), n)) + if (!addSymbol(Getattr(n, "sym:name"), n, imclass_name)) return SWIG_ERROR; } @@ -984,7 +986,7 @@ public: // Get any Java exception classes in the throws typemap ParmList *throw_parm_list = NULL; - if ((throw_parm_list = Getattr(n, "throws"))) { + if ((throw_parm_list = Getattr(n, "catchlist"))) { Swig_typemap_attach_parms("throws", throw_parm_list, f); for (p = throw_parm_list; p; p = nextSibling(p)) { if ((tm = Getattr(p, "tmap:throws"))) { @@ -1175,11 +1177,11 @@ public: // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum // Pure Java baseclass and interfaces - const String *pure_baseclass = typemapLookup("javabase", typemap_lookup_type, WARN_NONE); - const String *pure_interfaces = typemapLookup("javainterfaces", typemap_lookup_type, WARN_NONE); + const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE); + const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE); // Emit the enum - Printv(enum_code, typemapLookup("javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really) + Printv(enum_code, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really) " ", symname, *Char(pure_baseclass) ? // Bases " extends " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces " implements " : "", pure_interfaces, " {\n", NIL); @@ -1200,8 +1202,8 @@ public: // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum // Finish the enum declaration // Typemaps are used to generate the enum definition in a similar manner to proxy classes. - Printv(enum_code, (enum_feature == ProperEnum) ? ";\n" : "", typemapLookup("javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class - typemapLookup("javacode", typemap_lookup_type, WARN_NONE), // extra Java code + Printv(enum_code, (enum_feature == ProperEnum) ? ";\n" : "", typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class + typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE), // extra Java code "}", NIL); Replaceall(enum_code, "$javaclassname", symname); @@ -1238,7 +1240,7 @@ public: if (Len(package) > 0) Printf(f_enum, "package %s;\n", package); - Printv(f_enum, typemapLookup("javaimports", typemap_lookup_type, WARN_NONE), // Import statements + Printv(f_enum, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements "\n", enum_code, "\n", NIL); Printf(f_enum, "\n"); @@ -1271,6 +1273,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 @@ -1282,12 +1287,12 @@ 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 (!Getattr(n, "_last")) // Only the first enum item has this attribute set + if (!GetFlag(n, "firstenumitem")) Printf(enum_code, ",\n"); Printf(enum_code, " %s", symname); if (Getattr(n, "enumvalue")) { @@ -1297,18 +1302,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"); - const String *tm = typemapLookup("jstype", typemap_lookup_type, WARN_JAVA_TYPEMAP_JSTYPE_UNDEF); - String *return_type = Copy(tm); - Delete(typemap_lookup_type); - typemap_lookup_type = NULL; + 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); 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); @@ -1327,9 +1330,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); } @@ -1358,11 +1361,13 @@ public: String *return_type = NewString(""); String *constants_code = NewString(""); - if (!addSymbol(symname, n)) - return SWIG_ERROR; - bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0); + const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname; + String *scope = proxy_flag && wrapping_member_flag ? proxy_class_name : constants_interface_name; + if (!addSymbol(itemname, n, scope)) + return SWIG_ERROR; + // The %javaconst feature determines how the constant value is obtained int const_feature_flag = GetFlag(n, "feature:java:const"); @@ -1397,7 +1402,6 @@ public: Setattr(n, "value", new_value); } - const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname; const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); @@ -1429,7 +1433,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 @@ -1564,12 +1575,12 @@ public: String *c_baseclass = NULL; String *baseclass = NULL; String *c_baseclassname = NULL; - String *typemap_lookup_type = Getattr(n, "classtypeobj"); + SwigType *typemap_lookup_type = Getattr(n, "classtypeobj"); bool feature_director = Swig_directorclass(n) ? true : false; // Inheritance from pure Java classes Node *attributes = NewHash(); - const String *pure_baseclass = typemapLookup("javabase", typemap_lookup_type, WARN_NONE, attributes); + const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE, attributes); bool purebase_replace = GetFlag(attributes, "tmap:javabase:replace") ? true : false; bool purebase_notderived = GetFlag(attributes, "tmap:javabase:notderived") ? true : false; Delete(attributes); @@ -1623,15 +1634,15 @@ public: } // Pure Java interfaces - const String *pure_interfaces = typemapLookup("javainterfaces", typemap_lookup_type, WARN_NONE); + const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE); // Start writing the proxy class - Printv(proxy_class_def, typemapLookup("javaimports", typemap_lookup_type, WARN_NONE), // Import statements - "\n", typemapLookup("javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers + Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements + "\n", typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers " $javaclassname", // Class name and bases (*Char(wanted_base)) ? " extends " : "", wanted_base, *Char(pure_interfaces) ? // Pure Java interfaces - " implements " : "", pure_interfaces, " {", derived ? typemapLookup("javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) : // main body of class - typemapLookup("javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class + " implements " : "", pure_interfaces, " {", derived ? typemapLookup(n, "javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) : // main body of class + typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class NIL); // C++ destructor is wrapped by the delete method @@ -1642,11 +1653,11 @@ public: String *destruct_methodname = NULL; String *destruct_methodmodifiers = NULL; if (derived) { - tm = typemapLookup("javadestruct_derived", typemap_lookup_type, WARN_NONE, attributes); + tm = typemapLookup(n, "javadestruct_derived", typemap_lookup_type, WARN_NONE, attributes); destruct_methodname = Getattr(attributes, "tmap:javadestruct_derived:methodname"); destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct_derived:methodmodifiers"); } else { - tm = typemapLookup("javadestruct", typemap_lookup_type, WARN_NONE, attributes); + tm = typemapLookup(n, "javadestruct", typemap_lookup_type, WARN_NONE, attributes); destruct_methodname = Getattr(attributes, "tmap:javadestruct:methodname"); destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct:methodmodifiers"); } @@ -1664,7 +1675,7 @@ public: if (tm) { // Finalize method if (*Char(destructor_call)) { - Printv(proxy_class_def, typemapLookup("javafinalize", typemap_lookup_type, WARN_NONE), NIL); + Printv(proxy_class_def, typemapLookup(n, "javafinalize", typemap_lookup_type, WARN_NONE), NIL); } // delete method Printv(destruct, tm, NIL); @@ -1685,9 +1696,9 @@ public: release_jnicall = NewStringf("%s.%s_change_ownership(this, swigCPtr, false)", imclass_name, proxy_class_name); take_jnicall = NewStringf("%s.%s_change_ownership(this, swigCPtr, true)", imclass_name, proxy_class_name); - emitCodeTypemap(false, typemap_lookup_type, "directordisconnect", "methodname", destruct_jnicall); - emitCodeTypemap(false, typemap_lookup_type, "directorowner_release", "methodname", release_jnicall); - emitCodeTypemap(false, typemap_lookup_type, "directorowner_take", "methodname", take_jnicall); + emitCodeTypemap(n, false, typemap_lookup_type, "directordisconnect", "methodname", destruct_jnicall); + emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_release", "methodname", release_jnicall); + emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_take", "methodname", take_jnicall); Delete(destruct_jnicall); Delete(release_jnicall); @@ -1698,7 +1709,7 @@ public: Delete(destruct); // Emit extra user code - Printv(proxy_class_def, typemapLookup("javacode", typemap_lookup_type, WARN_NONE), // extra Java code + Printv(proxy_class_def, typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE), // extra Java code "\n", NIL); // Substitute various strings into the above template @@ -1977,7 +1988,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); @@ -2289,7 +2300,7 @@ public: /* Insert the javaconstruct typemap, doing the replacement for $directorconnect, as needed */ Hash *attributes = NewHash(); - String *construct_tm = Copy(typemapLookup("javaconstruct", Getattr(n, "name"), + String *construct_tm = Copy(typemapLookup(n, "javaconstruct", Getattr(n, "name"), WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes)); if (construct_tm) { if (!feature_director) { @@ -2607,6 +2618,16 @@ public: Delete(func_name); } + /*---------------------------------------------------------------------- + * replaceSpecialVariables() + *--------------------------------------------------------------------*/ + + virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) { + (void)method; + SwigType *type = Getattr(parm, "type"); + substituteClassname(type, tm); + } + /*---------------------------------------------------------------------- * decodeEnumFeature() * Decode the possible enum features, which are one of: @@ -2704,16 +2725,16 @@ public: /* ----------------------------------------------------------------------------- * substituteClassname() * - * Substitute $javaclassname with the proxy class name for classes/structs/unions that SWIG knows about. - * Also substitutes enums with enum name. + * Substitute the special variable $javaclassname with the proxy class name for classes/structs/unions + * that SWIG knows about. Also substitutes enums with enum name. * Otherwise use the $descriptor name for the Java class name. Note that the $&javaclassname substitution * is the same as a $&descriptor substitution, ie one pointer added to descriptor name. * Inputs: * pt - parameter type - * tm - jstype typemap + * tm - typemap contents that might contain the special variable to be replaced * jnidescriptor - if set, inner class names are separated with '$' otherwise a '.' * Outputs: - * tm - jstype typemap with $javaclassname substitution + * tm - typemap contents complete with the special variable substitution * Return: * substitution_performed - flag indicating if a substitution was performed * ----------------------------------------------------------------------------- */ @@ -2819,6 +2840,10 @@ public: * ----------------------------------------------------------------------------- */ void emitTypeWrapperClass(String *classname, SwigType *type) { + Node *n = NewHash(); + Setfile(n, input_file); + Setline(n, line_number); + String *swigtype = NewString(""); String *filen = NewStringf("%s%s.java", SWIG_output_directory(), classname); File *f_swigtype = NewFile(filen, "w", SWIG_output_files()); @@ -2837,16 +2862,16 @@ public: Printf(f_swigtype, "package %s;\n", package); // Pure Java baseclass and interfaces - const String *pure_baseclass = typemapLookup("javabase", type, WARN_NONE); - const String *pure_interfaces = typemapLookup("javainterfaces", type, WARN_NONE); + const String *pure_baseclass = typemapLookup(n, "javabase", type, WARN_NONE); + const String *pure_interfaces = typemapLookup(n, "javainterfaces", type, WARN_NONE); // Emit the class - Printv(swigtype, typemapLookup("javaimports", type, WARN_NONE), // Import statements - "\n", typemapLookup("javaclassmodifiers", type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers + Printv(swigtype, typemapLookup(n, "javaimports", type, WARN_NONE), // Import statements + "\n", typemapLookup(n, "javaclassmodifiers", type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers " $javaclassname", // Class name and bases *Char(pure_baseclass) ? " extends " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces - " implements " : "", pure_interfaces, " {", typemapLookup("javabody", type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class - typemapLookup("javacode", type, WARN_NONE), // extra Java code + " implements " : "", pure_interfaces, " {", typemapLookup(n, "javabody", type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class + typemapLookup(n, "javacode", type, WARN_NONE), // extra Java code "}\n", "\n", NIL); Replaceall(swigtype, "$javaclassname", classname); @@ -2856,29 +2881,34 @@ public: Close(f_swigtype); Delete(swigtype); + Delete(n); } /* ----------------------------------------------------------------------------- * typemapLookup() + * n - for input only and must contain info for Getfile(n) and Getline(n) to work + * tmap_method - typemap method name + * type - typemap type to lookup + * warning - warning number to issue if no typemaps found + * typemap_attributes - the typemap attributes are attached to this node and will + * also be used for temporary storage if non null + * return is never NULL, unlike Swig_typemap_lookup() * ----------------------------------------------------------------------------- */ - const String *typemapLookup(const String *op, String *type, int warning, Node *typemap_attributes = NULL) { - String *tm = NULL; - const String *code = NULL; - - if ((tm = Swig_typemap_search(op, type, NULL, NULL))) { - code = Getattr(tm, "code"); - if (typemap_attributes) - Swig_typemap_attach_kwargs(tm, op, typemap_attributes); - } - - if (!code) { - code = empty_string; + const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) { + Node *node = !typemap_attributes ? NewHash() : typemap_attributes; + Setattr(node, "type", type); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0); + if (!tm) { + tm = empty_string; if (warning != WARN_NONE) - Swig_warning(warning, input_file, line_number, "No %s typemap defined for %s\n", op, type); + Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0)); } - - return code ? code : empty_string; + if (!typemap_attributes) + Delete(node); + return tm; } /* ----------------------------------------------------------------------------- @@ -3187,8 +3217,7 @@ public: * typemaps. *--------------------------------------------------------------------*/ - void - emitCodeTypemap(bool derived, String *lookup_type, const String *typemap, const String *methodname, const String *jnicall) { + void emitCodeTypemap(Node *n, bool derived, SwigType *lookup_type, const String *typemap, const String *methodname, const String *jnicall) { const String *tm = NULL; Node *tmattrs = NewHash(); String *lookup_tmname = NewString(typemap); @@ -3199,7 +3228,7 @@ public: Append(lookup_tmname, "_derived"); } - tm = typemapLookup(lookup_tmname, lookup_type, WARN_NONE, tmattrs); + tm = typemapLookup(n, lookup_tmname, lookup_type, WARN_NONE, tmattrs); method_attr_name = NewStringf("tmap:%s:%s", lookup_tmname, methodname); method_attr = Getattr(tmattrs, method_attr_name); @@ -3367,7 +3396,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) { @@ -3379,7 +3408,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"))) { @@ -3391,17 +3420,18 @@ public: Append(classret_desc, jnidesc_canon); Delete(jnidesc_canon); } else { - Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, "No or improper directorin typemap defined for %s\n", SwigType_str(returntype, 0)); + Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; } /* 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); @@ -3422,13 +3452,15 @@ public: Delete(jnidesc_canon); } else { Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, - "No or improper directorin typemap defined for %s\n", SwigType_str(c_ret_type, 0)); + "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(c_ret_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; } Delete(tp); } else { - Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(returntype, 0)); + Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; } @@ -3501,7 +3533,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)) @@ -3512,8 +3544,8 @@ public: Delete(tm); } else { Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, - "No or improper directorin typemap for type %s used in director method %s::%s\n", SwigType_str(type, 0), SwigType_namestr(c_classname), - SwigType_namestr(name)); + "No or improper directorin typemap for type %s for use in %s::%s (skipping director method)\n", + SwigType_str(type, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; } @@ -3543,7 +3575,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 */ @@ -3599,11 +3631,13 @@ public: Append(classdesc, jni_canon); Delete(jni_canon); } else { - Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, "No javadirectorin typemap defined for %s\n", SwigType_str(pt, 0)); + Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, "No javadirectorin typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; } } else { - Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(pt, 0)); + Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; } @@ -3613,19 +3647,23 @@ public: } else { if (!desc_tm) { Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, - "No or improper directorin typemap defined for %s\n", SwigType_str(c_param_type, 0)); + "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); p = nextSibling(p); } else if (!jdesc) { Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number, - "Missing JNI descriptor in directorin typemap defined for %s\n", SwigType_str(c_param_type, 0)); + "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); p = Getattr(p, "tmap:directorin:next"); } else if (!tm) { Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, - "No or improper directorin typemap defined for argument %s\n", SwigType_str(pt, 0)); + "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n", + SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); p = nextSibling(p); } else if (!cdesc) { Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number, - "Missing JNI descriptor in directorin typemap defined for %s\n", SwigType_str(pt, 0)); + "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); p = Getattr(p, "tmap:directorin:next"); } @@ -3634,7 +3672,8 @@ public: Delete(tp); } else { - Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(pt, 0)); + Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n", + SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; p = nextSibling(p); } @@ -3655,6 +3694,7 @@ public: Printf(declaration, " virtual %s", target); Delete(target); + // Add any exception specifications to the methods in the director class // Get any Java exception classes in the throws typemap ParmList *throw_parm_list = NULL; @@ -3691,8 +3731,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); @@ -3736,7 +3779,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))) { @@ -3746,8 +3789,8 @@ public: Printf(w->code, "%s\n", tm); } else { Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number, - "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0), - SwigType_namestr(c_classname), SwigType_namestr(name)); + "Unable to use return type %s used in %s::%s (skipping director method)\n", + SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); output_director = false; } @@ -3829,7 +3872,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); @@ -3866,7 +3909,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; @@ -3973,7 +4016,7 @@ public: Node *disconn_attr = NewHash(); String *disconn_methodname = NULL; - disconn_tm = typemapLookup("directordisconnect", full_classname, WARN_NONE, disconn_attr); + disconn_tm = typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr); disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname"); Printv(w->code, " swig_disconnect_director_self(\"", disconn_methodname, "\");\n", "}\n", NIL); diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 479615908..a22c06dd0 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -22,6 +22,7 @@ static int director_mode = 0; static int director_protected_mode = 1; static int all_protected_mode = 0; static int naturalvar_mode = 0; +Language* Language::this_ = 0; /* Set director_protected_mode */ void Wrapper_director_mode_set(int flag) { @@ -50,6 +51,9 @@ extern "C" { int Swig_all_protected_mode() { return all_protected_mode; } + void Language_replace_special_variables(String *method, String *tm, Parm *parm) { + Language::instance()->replaceSpecialVariables(method, tm, parm); + } } /* Some status variables used during parsing */ @@ -175,7 +179,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) { @@ -307,13 +311,15 @@ Language::Language(): none_comparison(NewString("$arg != 0")), director_ctor_code(NewString("")), director_prot_ctor_code(0), -symbols(NewHash()), +symtabs(NewHash()), classtypes(NewHash()), enumtypes(NewHash()), overloading(0), multiinput(0), cplus_runtime(0), directors(0) { + Hash *symbols = NewHash(); + Setattr(symtabs, "", symbols); // create top level/global symbol table scope argc_template_string = NewString("argc"); argv_template_string = NewString("argv[%d]"); @@ -327,14 +333,17 @@ directors(0) { director_prot_ctor_code = 0; director_multiple_inheritance = 1; director_language = 0; + assert(!this_); + this_ = this; } Language::~Language() { - Delete(symbols); + Delete(symtabs); Delete(classtypes); Delete(enumtypes); Delete(director_ctor_code); Delete(none_comparison); + this_ = 0; } /* ---------------------------------------------------------------------- @@ -779,7 +788,7 @@ int Language::typemapcopyDirective(Node *n) { Swig_error(input_file, line_number, "Can't copy typemap. Number of types differ.\n"); } else { if (Swig_typemap_copy(method, pattern, npattern) < 0) { - Swig_error(input_file, line_number, "Can't copy typemap.\n"); + Swig_error(input_file, line_number, "Can't copy typemap (%s) %s = %s\n", method, ParmList_str(pattern), ParmList_str(npattern)); } } items = nextSibling(items); @@ -878,30 +887,8 @@ int Language::cDeclaration(Node *n) { if (over) over = first_nontemplate(over); if (over && (over != n)) { - SwigType *tc = Copy(decl); - SwigType *td = SwigType_pop_function(tc); - String *oname; - String *cname; - if (CurrentClass) { - oname = NewStringf("%s::%s", ClassName, name); - cname = NewStringf("%s::%s", ClassName, Getattr(over, "name")); - } else { - oname = NewString(name); - cname = NewString(Getattr(over, "name")); - } - - SwigType *tc2 = Copy(Getattr(over, "decl")); - SwigType *td2 = SwigType_pop_function(tc2); - - Swig_warning(WARN_LANG_OVERLOAD_DECL, input_file, line_number, "Overloaded declaration ignored. %s\n", SwigType_str(td, SwigType_namestr(oname))); - Swig_warning(WARN_LANG_OVERLOAD_DECL, Getfile(over), Getline(over), "Previous declaration is %s\n", SwigType_str(td2, SwigType_namestr(cname))); - - Delete(tc2); - Delete(td2); - Delete(tc); - Delete(td); - Delete(oname); - Delete(cname); + Swig_warning(WARN_LANG_OVERLOAD_DECL, input_file, line_number, "Overloaded declaration ignored. %s\n", Swig_name_decl(n)); + Swig_warning(WARN_LANG_OVERLOAD_DECL, Getfile(over), Getline(over), "Previous declaration is %s\n", Swig_name_decl(over)); return SWIG_NOWRAP; } } @@ -919,7 +906,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 */ @@ -982,7 +969,7 @@ int Language::cDeclaration(Node *n) { if (Strncmp(symname, "__dummy_", 8) == 0) { SetFlag(n, "feature:ignore"); Swig_warning(WARN_LANG_TEMPLATE_METHOD_IGNORE, input_file, line_number, - "%%template() contains no name. Template method ignored: %s\n", SwigType_str(decl, SwigType_namestr(Getattr(n,"name")))); + "%%template() contains no name. Template method ignored: %s\n", Swig_name_decl(n)); } } if (!GetFlag(n, "feature:ignore")) @@ -1156,7 +1143,7 @@ int Language::callbackfunctionHandler(Node *n) { Setattr(n, "type", cbty); Setattr(n, "value", calltype); - Node *ns = Getattr(symbols, cbname); + Node *ns = symbolLookup(cbname); if (!ns) constantWrapper(n); @@ -1207,6 +1194,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)); @@ -1426,39 +1415,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); @@ -1500,7 +1486,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)); @@ -1926,12 +1912,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); @@ -2184,7 +2172,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); @@ -2477,7 +2465,7 @@ int Language::classHandler(Node *n) { continue; String *methodname = Getattr(method, "sym:name"); String *wrapname = NewStringf("%s_%s", symname, methodname); - if (!Getattr(symbols, wrapname) && (!is_public(method))) { + if (!symbolLookup(wrapname, "") && (!is_public(method))) { Node *m = Copy(method); Setattr(m, "director", "1"); Setattr(m, "parentNode", n); @@ -2930,27 +2918,71 @@ void Language::main(int argc, char *argv[]) { /* ----------------------------------------------------------------------------- * Language::addSymbol() * - * Adds a symbol entry. Returns 1 if the symbol is added successfully. + * Adds a symbol entry into the target language symbol tables. + * Returns 1 if the symbol is added successfully. * Prints an error message and returns 0 if a conflict occurs. + * The scope is optional for target languages and if supplied must be a fully + * resolved scope and the symbol s must not contain any scope qualifiers. * ----------------------------------------------------------------------------- */ -int -Language::addSymbol(const String *s, const Node *n) { - Node *c = Getattr(symbols, s); - if (c && (c != n)) { - Swig_error(input_file, line_number, "'%s' is multiply defined in the generated module.\n", s); - Swig_error(Getfile(c), Getline(c), "Previous declaration of '%s'\n", s); - return 0; +int Language::addSymbol(const String *s, const Node *n, const_String_or_char_ptr scope) { + Hash *symbols = Getattr(symtabs, scope); + if (!symbols) { + // New scope which has not been added by the target language - lazily created. + symbols = NewHash(); + Setattr(symtabs, scope, symbols); + + // Add the new scope as a symbol in the top level scope. + // Alternatively the target language must add it in before attempting to add symbols into the scope. + const_String_or_char_ptr top_scope = ""; + Hash *topscope_symbols = Getattr(symtabs, top_scope); + Setattr(topscope_symbols, scope, NewHash()); + } else { + Node *c = Getattr(symbols, s); + if (c && (c != n)) { + Swig_error(input_file, line_number, "'%s' is multiply defined in the generated target language module.\n", s); + Swig_error(Getfile(c), Getline(c), "Previous declaration of '%s'\n", s); + return 0; + } } Setattr(symbols, s, n); return 1; } +/* ----------------------------------------------------------------------------- + * Language::dumpSymbols() + * ----------------------------------------------------------------------------- */ + +void Language::dumpSymbols() { + Printf(stdout, "LANGUAGE SYMBOLS start =======================================\n"); + + Node *table = symtabs; + Iterator ki = First(table); + while (ki.key) { + String *k = ki.key; + Printf(stdout, "===================================================\n"); + Printf(stdout, "%s -\n", k); + { + Symtab *symtab = Getattr(table, k); + Iterator it = First(symtab); + while (it.key) { + String *symname = it.key; + Printf(stdout, " %s\n", symname); + it = Next(it); + } + } + ki = Next(ki); + } + + Printf(stdout, "LANGUAGE SYMBOLS finish =======================================\n"); +} + /* ----------------------------------------------------------------------------- * Language::symbolLookup() * ----------------------------------------------------------------------------- */ -Node *Language::symbolLookup(String *s) { +Node *Language::symbolLookup(String *s, const_String_or_char_ptr scope) { + Hash *symbols = Getattr(symtabs, scope); return Getattr(symbols, s); } @@ -3427,6 +3459,24 @@ String *Language::defaultExternalRuntimeFilename() { return 0; } +/* ----------------------------------------------------------------------------- + * Language::replaceSpecialVariables() + * Language modules should implement this if special variables are to be handled + * correctly in the $typemap(...) special variable macro. + * method - typemap method name + * tm - string containing typemap contents + * parm - a parameter describing the typemap type to be handled + * ----------------------------------------------------------------------------- */ +void Language::replaceSpecialVariables(String *method, String *tm, Parm *parm) { + (void)method; + (void)tm; + (void)parm; +} + +Language *Language::instance() { + return this_; +} + Hash *Language::getClassHash() const { return classhash; } diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 2437b35c7..86f279a67 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -29,7 +29,7 @@ char cvsroot_main_cxx[] = "$Id$"; // Global variables -Language *lang; // Language method +static Language *lang = 0; // Language method int CPlusPlus = 0; int Extend = 0; // Extend flag int ForceExtern = 0; // Force extern mode @@ -66,11 +66,17 @@ 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-lsymbols - Display target language layer symbols\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\ @@ -163,9 +169,13 @@ static int help = 0; static int checkout = 0; static int cpp_only = 0; static int no_cpp = 0; -static char *outfile_name = 0; -static char *outfile_name_h = 0; +static String *outfile_name = 0; +static String *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_lang_symbols = 0; static int dump_tags = 0; static int dump_module = 0; static int dump_top = 0; @@ -178,14 +188,13 @@ static int depend = 0; static int depend_only = 0; static int memory_debug = 0; static int allkw = 0; -static DOH *libfiles = 0; static DOH *cpps = 0; static String *dependencies_file = 0; -static File *f_dependencies_file = 0; static String *dependencies_target = 0; static int external_runtime = 0; static String *external_runtime_name = 0; enum { STAGE1=1, STAGE2=2, STAGE3=4, STAGE4=8, STAGEOVERFLOW=16 }; +static List *libfiles = 0; static List *all_output_files = 0; // ----------------------------------------------------------------------------- @@ -561,22 +570,23 @@ void SWIG_getoptions(int argc, char *argv[]) { Swig_mark_arg(i); } else if (strcmp(argv[i], "-swiglib") == 0) { if (SwigLibWin) - printf("%s\n", Char(SwigLibWin)); - printf("%s\n", SwigLib); + Printf(stdout, "%s\n", SwigLibWin); + Printf(stdout, "%s\n", SwigLib); SWIG_exit(EXIT_SUCCESS); } else if (strcmp(argv[i], "-o") == 0) { Swig_mark_arg(i); if (argv[i + 1]) { - outfile_name = Swig_copy_string(argv[i + 1]); + outfile_name = NewString(argv[i + 1]); + Swig_filename_correct(outfile_name); if (!outfile_name_h || !dependencies_file) { - char *ext = strrchr(outfile_name, '.'); - String *basename = ext ? NewStringWithSize(outfile_name, ext - outfile_name) : NewString(outfile_name); + char *ext = strrchr(Char(outfile_name), '.'); + String *basename = ext ? NewStringWithSize(Char(outfile_name), Char(ext) - Char(outfile_name)) : NewString(outfile_name); if (!dependencies_file) { dependencies_file = NewStringf("%s.%s", basename, depends_extension); } if (!outfile_name_h) { Printf(basename, ".%s", hpp_extension); - outfile_name_h = Swig_copy_string(Char(basename)); + outfile_name_h = NewString(basename); } Delete(basename); } @@ -588,7 +598,8 @@ void SWIG_getoptions(int argc, char *argv[]) { } else if (strcmp(argv[i], "-oh") == 0) { Swig_mark_arg(i); if (argv[i + 1]) { - outfile_name_h = Swig_copy_string(argv[i + 1]); + outfile_name_h = NewString(argv[i + 1]); + Swig_filename_correct(outfile_name_h); Swig_mark_arg(i + 1); i++; } else { @@ -653,6 +664,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]) { @@ -720,6 +737,18 @@ 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-lsymbols") == 0) { + dump_lang_symbols = 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); @@ -815,7 +844,6 @@ void SWIG_getoptions(int argc, char *argv[]) { int SWIG_main(int argc, char *argv[], Language *l) { char *c; - extern void Swig_print_xml(Node *obj, String *filename); /* Initialize the SWIG core */ Swig_init(); @@ -833,12 +861,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 */ @@ -928,8 +950,8 @@ int SWIG_main(int argc, char *argv[], Language *l) { Swig_add_directory((String *) SwigLib); if (Verbose) { - printf("LangSubDir: %s\n", Char(LangSubDir)); - printf("Search paths:\n"); + Printf(stdout, "Language subdirectory: %s\n", LangSubDir); + Printf(stdout, "Search paths:\n"); List *sp = Swig_search_path(); Iterator s; for (s = First(sp); s.item; s = Next(s)) { @@ -948,12 +970,12 @@ int SWIG_main(int argc, char *argv[], Language *l) { // If the user has requested to check out a file, handle that if (checkout) { DOH *s; - char *outfile = Char(input_file); + String *outfile = input_file; if (outfile_name) outfile = outfile_name; if (Verbose) - printf("Handling checkout...\n"); + Printf(stdout, "Handling checkout...\n"); s = Swig_include(input_file); if (!s) { @@ -979,7 +1001,7 @@ int SWIG_main(int argc, char *argv[], Language *l) { } else { // Run the preprocessor if (Verbose) - printf("Preprocessing...\n"); + Printf(stdout, "Preprocessing...\n"); { int i; @@ -1009,9 +1031,9 @@ int SWIG_main(int argc, char *argv[], Language *l) { if (lang_config) { Printf(fs, "\n%%include <%s>\n", lang_config); } - Printf(fs, "%%include(maininput=\"%s\") \"%s\"\n", Swig_filename_escape(input_file), Swig_last_file()); + Printf(fs, "%%include(maininput=\"%s\") \"%s\"\n", Swig_filename_escape(input_file), Swig_filename_escape(Swig_last_file())); for (i = 0; i < Len(libfiles); i++) { - Printf(fs, "\n%%include \"%s\"\n", Getitem(libfiles, i)); + Printf(fs, "\n%%include \"%s\"\n", Swig_filename_escape(Getitem(libfiles, i))); } Seek(fs, 0, SEEK_SET); cpps = Preprocessor_parse(fs); @@ -1030,6 +1052,7 @@ int SWIG_main(int argc, char *argv[], Language *l) { if (depend) { if (!no_cpp) { String *outfile; + File *f_dependencies_file = 0; char *basename = Swig_file_basename(outcurrentdir ? Swig_file_filename(input_file): Char(input_file)); if (!outfile_name) { @@ -1063,9 +1086,13 @@ int SWIG_main(int argc, char *argv[], Language *l) { } List *files = Preprocessor_depend(); for (int i = 0; i < Len(files); i++) { - if ((depend != 2) || ((depend == 2) && (Strncmp(Getitem(files, i), SwigLib, Len(SwigLib)) != 0))) { - Printf(f_dependencies_file, "\\\n %s ", Getitem(files, i)); - } + int use_file = 1; + if (depend == 2) { + if ((Strncmp(Getitem(files, i), SwigLib, Len(SwigLib)) == 0) || (SwigLibWin && (Strncmp(Getitem(files, i), SwigLibWin, Len(SwigLibWin)) == 0))) + use_file = 0; + } + if (use_file) + Printf(f_dependencies_file, "\\\n %s ", Getitem(files, i)); } Printf(f_dependencies_file, "\n"); if (f_dependencies_file != stdout) @@ -1149,6 +1176,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); } @@ -1196,6 +1236,9 @@ int SWIG_main(int argc, char *argv[], Language *l) { } } } + if (dump_lang_symbols) { + lang->dumpSymbols(); + } if (dump_top & STAGE4) { Printf(stdout, "debug-top stage 4\n"); Swig_print_tree(top); @@ -1205,6 +1248,8 @@ int SWIG_main(int argc, char *argv[], Language *l) { Swig_print_tree(Getattr(top, "module")); } if (dump_xml && top) { + delete lang; + lang = 0; Swig_print_xml(top, xmlout); } Delete(top); @@ -1239,6 +1284,9 @@ int SWIG_main(int argc, char *argv[], Language *l) { if ((werror) && (Swig_warn_count())) { return Swig_warn_count(); } + + delete lang; + return Swig_error_count(); } diff --git a/Source/Modules/modula3.cxx b/Source/Modules/modula3.cxx index e650edcb2..d1e10b974 100644 --- a/Source/Modules/modula3.cxx +++ b/Source/Modules/modula3.cxx @@ -85,7 +85,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 @@ -970,10 +970,10 @@ MODULA3(): Printf(f_runtime, "#define SWIGMODULA3\n"); Printf(f_runtime, "\n"); - Swig_name_register((char *) "wrapper", (char *) "Modula3_%f"); + Swig_name_register("wrapper", "Modula3_%f"); if (old_variable_names) { - Swig_name_register((char *) "set", (char *) "set_%v"); - Swig_name_register((char *) "get", (char *) "get_%v"); + Swig_name_register("set", "set_%v"); + Swig_name_register("get", "get_%v"); } Printf(f_wrappers, "\n#ifdef __cplusplus\n"); @@ -1408,7 +1408,7 @@ MODULA3(): // Get any Modula 3 exception classes in the throws typemap ParmList *throw_parm_list = NULL; - if ((throw_parm_list = Getattr(n, "throws"))) { + if ((throw_parm_list = Getattr(n, "catchlist"))) { Swig_typemap_attach_parms("throws", throw_parm_list, f); Parm *p; for (p = throw_parm_list; p; p = nextSibling(p)) { @@ -2234,23 +2234,23 @@ MODULA3(): baseclass = NewString(""); // Inheritance from pure Modula 3 classes - const String *pure_baseclass = typemapLookup("m3base", classDeclarationName, WARN_NONE); + const String *pure_baseclass = typemapLookup(n, "m3base", classDeclarationName, WARN_NONE); if (hasContent(pure_baseclass) && hasContent(baseclass)) { Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, input_file, line_number, "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n", classDeclarationName, pure_baseclass); } // Pure Modula 3 interfaces - const String *pure_interfaces = typemapLookup(derived ? "m3interfaces_derived" : "m3interfaces", + const String *pure_interfaces = typemapLookup(n, derived ? "m3interfaces_derived" : "m3interfaces", classDeclarationName, WARN_NONE); // Start writing the proxy class - Printv(proxy_class_def, typemapLookup("m3imports", classDeclarationName, WARN_NONE), // Import statements - "\n", typemapLookup("m3classmodifiers", classDeclarationName, WARN_MODULA3_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers + Printv(proxy_class_def, typemapLookup(n, "m3imports", classDeclarationName, WARN_NONE), // Import statements + "\n", typemapLookup(n, "m3classmodifiers", classDeclarationName, WARN_MODULA3_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers " class $m3classname", // Class name and bases (derived || *Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", baseclass, pure_baseclass, ((derived || *Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces ", " : "", pure_interfaces, " {\n", " private IntPtr swigCPtr;\n", // Member variables for memory handling - derived ? "" : " protected bool swigCMemOwn;\n", "\n", " ", typemapLookup("m3ptrconstructormodifiers", classDeclarationName, WARN_MODULA3_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers + derived ? "" : " protected bool swigCMemOwn;\n", "\n", " ", typemapLookup(n, "m3ptrconstructormodifiers", classDeclarationName, WARN_MODULA3_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers " $m3classname(IntPtr cPtr, bool cMemoryOwn) ", // Constructor used for wrapping pointers derived ? ": base($imclassname.$m3classnameTo$baseclass(cPtr), cMemoryOwn) {\n" @@ -2266,10 +2266,10 @@ MODULA3(): Node *attributes = NewHash(); String *destruct_methodname = NULL; if (derived) { - tm = typemapLookup("m3destruct_derived", classDeclarationName, WARN_NONE, attributes); + tm = typemapLookup(n, "m3destruct_derived", classDeclarationName, WARN_NONE, attributes); destruct_methodname = Getattr(attributes, "tmap:m3destruct_derived:methodname"); } else { - tm = typemapLookup("m3destruct", classDeclarationName, WARN_NONE, attributes); + tm = typemapLookup(n, "m3destruct", classDeclarationName, WARN_NONE, attributes); destruct_methodname = Getattr(attributes, "tmap:m3destruct:methodname"); } if (!destruct_methodname) { @@ -2279,7 +2279,7 @@ MODULA3(): if (tm) { // Finalize method if (*Char(destructor_call)) { - Printv(proxy_class_def, typemapLookup("m3finalize", classDeclarationName, WARN_NONE), NIL); + Printv(proxy_class_def, typemapLookup(n, "m3finalize", classDeclarationName, WARN_NONE), NIL); } // Dispose method Printv(destruct, tm, NIL); @@ -2294,8 +2294,8 @@ MODULA3(): Delete(destruct); // Emit various other methods - Printv(proxy_class_def, typemapLookup("m3getcptr", classDeclarationName, WARN_MODULA3_TYPEMAP_GETCPTR_UNDEF), // getCPtr method - typemapLookup("m3code", classDeclarationName, WARN_NONE), // extra Modula 3 code + Printv(proxy_class_def, typemapLookup(n, "m3getcptr", classDeclarationName, WARN_MODULA3_TYPEMAP_GETCPTR_UNDEF), // getCPtr method + typemapLookup(n, "m3code", classDeclarationName, WARN_NONE), // extra Modula 3 code "\n", NIL); // Substitute various strings into the above template @@ -3585,17 +3585,28 @@ MODULA3(): Delete(throws_hash); } + /*---------------------------------------------------------------------- + * replaceSpecialVariables() + *--------------------------------------------------------------------*/ + + virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) { + (void)method; + SwigType *type = Getattr(parm, "type"); + substituteClassname(type, tm); + } + /* ----------------------------------------------------------------------------- * substituteClassname() * - * Substitute $m3classname with the proxy class name for classes/structs/unions that SWIG knows about. + * Substitute the special variable $m3classname with the proxy class name for classes/structs/unions + * that SWIG knows about. * Otherwise use the $descriptor name for the Modula 3 class name. Note that the $&m3classname substitution * is the same as a $&descriptor substitution, ie one pointer added to descriptor name. * Inputs: * pt - parameter type - * tm - m3wraptype typemap + * tm - typemap contents that might contain the special variable to be replaced * Outputs: - * tm - m3wraptype typemap with $m3classname substitution + * tm - typemap contents complete with the special variable substitution * Return: * substitution_performed - flag indicating if a substitution was performed * ----------------------------------------------------------------------------- */ @@ -3769,6 +3780,10 @@ MODULA3(): * ----------------------------------------------------------------------------- */ void emitTypeWrapperClass(String *classname, SwigType *type) { + Node *n = NewHash(); + Setfile(n, input_file); + Setline(n, line_number); + String *filen = NewStringf("%s%s.m3", Swig_file_dirname(outfile), classname); File *f_swigtype = NewFile(filen, "w", SWIG_output_files()); if (!f_swigtype) { @@ -3781,19 +3796,19 @@ MODULA3(): emitBanner(f_swigtype); // Pure Modula 3 baseclass and interfaces - const String *pure_baseclass = typemapLookup("m3base", type, WARN_NONE); - const String *pure_interfaces = typemapLookup("m3interfaces", type, WARN_NONE); + const String *pure_baseclass = typemapLookup(n, "m3base", type, WARN_NONE); + const String *pure_interfaces = typemapLookup(n, "m3interfaces", type, WARN_NONE); // Emit the class - Printv(swigtype, typemapLookup("m3imports", type, WARN_NONE), // Import statements - "\n", typemapLookup("m3classmodifiers", type, WARN_MODULA3_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers + Printv(swigtype, typemapLookup(n, "m3imports", type, WARN_NONE), // Import statements + "\n", typemapLookup(n, "m3classmodifiers", type, WARN_MODULA3_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers " class $m3classname", // Class name and bases *Char(pure_baseclass) ? " : " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces - " : " : "", pure_interfaces, " {\n", " private IntPtr swigCPtr;\n", "\n", " ", typemapLookup("m3ptrconstructormodifiers", type, WARN_MODULA3_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers + " : " : "", pure_interfaces, " {\n", " private IntPtr swigCPtr;\n", "\n", " ", typemapLookup(n, "m3ptrconstructormodifiers", type, WARN_MODULA3_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers " $m3classname(IntPtr cPtr, bool bFutureUse) {\n", // Constructor used for wrapping pointers " swigCPtr = cPtr;\n", " }\n", "\n", " protected $m3classname() {\n", // Default constructor - " swigCPtr = IntPtr.Zero;\n", " }\n", typemapLookup("m3getcptr", type, WARN_MODULA3_TYPEMAP_GETCPTR_UNDEF), // getCPtr method - typemapLookup("m3code", type, WARN_NONE), // extra Modula 3 code + " swigCPtr = IntPtr.Zero;\n", " }\n", typemapLookup(n, "m3getcptr", type, WARN_MODULA3_TYPEMAP_GETCPTR_UNDEF), // getCPtr method + typemapLookup(n, "m3code", type, WARN_NONE), // extra Modula 3 code "}\n", "\n", NIL); Replaceall(swigtype, "$m3classname", classname); @@ -3806,25 +3821,29 @@ MODULA3(): /* ----------------------------------------------------------------------------- * typemapLookup() + * n - for input only and must contain info for Getfile(n) and Getline(n) to work + * tmap_method - typemap method name + * type - typemap type to lookup + * warning - warning number to issue if no typemaps found + * typemap_attributes - the typemap attributes are attached to this node and will + * also be used for temporary storage if non null + * return is never NULL, unlike Swig_typemap_lookup() * ----------------------------------------------------------------------------- */ - const String *typemapLookup(const String *op, String *type, int warning, Node *typemap_attributes = NULL) { - String *tm = NULL; - const String *code = NULL; - - if ((tm = Swig_typemap_search(op, type, NULL, NULL))) { - code = Getattr(tm, "code"); - if (typemap_attributes) - Swig_typemap_attach_kwargs(tm, op, typemap_attributes); - } - - if (!code) { - code = empty_string; + const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) { + Node *node = !typemap_attributes ? NewHash() : typemap_attributes; + Setattr(node, "type", type); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0); + if (!tm) { + tm = empty_string; if (warning != WARN_NONE) - Swig_warning(warning, input_file, line_number, "No %s typemap defined for %s\n", op, type); + Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0)); } - - return code ? code : empty_string; + if (!typemap_attributes) + Delete(node); + return tm; } /* ----------------------------------------------------------------------------- diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx index d17ccd33c..5eb0a58c9 100644 --- a/Source/Modules/mzscheme.cxx +++ b/Source/Modules/mzscheme.cxx @@ -651,13 +651,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); @@ -766,7 +768,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 7108484b3..41c30c858 100644 --- a/Source/Modules/ocaml.cxx +++ b/Source/Modules/ocaml.cxx @@ -1631,11 +1631,6 @@ public: Setattr(n, "type", return_type); tm = Swig_typemap_lookup("directorout", n, "c_result", w); Setattr(n, "type", type); - if (tm == 0) { - String *name = NewString("c_result"); - tm = Swig_typemap_search("directorout", return_type, name, NULL); - Delete(name); - } if (tm != 0) { Replaceall(tm, "$input", "swig_result"); /* TODO check this */ @@ -1736,7 +1731,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); @@ -1789,7 +1784,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 7646da47d..ab001a48b 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -17,7 +17,8 @@ char cvsroot_octave_cxx[] = "$Id$"; static const char *usage = (char *) "\ Octave Options (available with -octave)\n\ - (none yet)\n\n"; + [no additional options]\n\ + \n"; class OCTAVE:public Language { @@ -959,7 +960,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"); @@ -1054,7 +1055,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; @@ -1309,11 +1310,6 @@ public: Setattr(n, "type", return_type); tm = Swig_typemap_lookup("directorout", n, "result", w); Setattr(n, "type", type); - if (tm == 0) { - String *name = NewString("result"); - tm = Swig_typemap_search("directorout", return_type, name, NULL); - Delete(name); - } if (tm != 0) { char temp[24]; sprintf(temp, "out(%d)", idx); diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx index 57d7fac90..65deee2de 100644 --- a/Source/Modules/overload.cxx +++ b/Source/Modules/overload.cxx @@ -227,13 +227,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; @@ -242,13 +244,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; @@ -262,15 +266,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; } @@ -722,6 +726,10 @@ String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxar Parm *pi = Getattr(ni, "wrap:parms"); int num_required = emit_num_required(pi); int num_arguments = emit_num_arguments(pi); + if (GetFlag(n, "wrap:this")) { + num_required++; + num_arguments++; + } if (num_arguments > *maxargs) *maxargs = num_arguments; int varargs = emit_isvarargs(pi); @@ -755,7 +763,7 @@ String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxar Printf(f, "}\n"); Delete(lfmt); } - if (print_typecheck(f, j, pj)) { + if (print_typecheck(f, (GetFlag(n, "wrap:this") ? j + 1 : j), pj)) { Printf(f, "if (_v) {\n"); num_braces++; } diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index d0c019195..4c7dba1eb 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -1511,7 +1511,7 @@ public: Printf(pcode, "sub new {\n"); } else { /* Constructor doesn't match classname so we'll just use the normal name */ - Printv(pcode, "sub ", Swig_name_construct(symname), " () {\n", NIL); + Printv(pcode, "sub ", Swig_name_construct(symname), " {\n", NIL); } Printv(pcode, diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 94abf58da..989127101 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -13,13 +13,6 @@ */ /* FIXME: PHP5 OO wrapping TODO list: - * - * Short term: - * - * Sort out auto-renaming of method and class names which are reserved - * words (e.g. empty, clone, exception, etc.) - * - * Sort out wrapping of static member variables in OO PHP5. * * Medium term: * @@ -66,6 +59,11 @@ PHP Options (available with -php)\n\ */ #define SWIG_PTR "_cPtr" +/* This is the name of the hash where the variables existing only in PHP + * classes are stored. + */ +#define SWIG_DATA "_pData" + static int constructors = 0; static String *NOTCLASS = NewString("Not a class"); static Node *classnode = 0; @@ -77,8 +75,11 @@ static String *shadow_classname = 0; static File *f_begin = 0; static File *f_runtime = 0; +static File *f_runtime_h = 0; static File *f_h = 0; static File *f_phpcode = 0; +static File *f_directors = 0; +static File *f_directors_h = 0; static String *phpfilename = 0; static String *s_header; @@ -121,14 +122,14 @@ static enum { membervar, staticmembervar, constructor, - destructor + directorconstructor } wrapperType = standard; extern "C" { static void (*r_prevtracefunc) (SwigType *t, String *mangled, String *clientdata) = 0; } -void SwigPHP_emit_resource_registrations() { +static void SwigPHP_emit_resource_registrations() { Iterator ki; if (!zend_types) @@ -143,7 +144,7 @@ void SwigPHP_emit_resource_registrations() { String *human_name = key; // Write out destructor function header - Printf(s_wrappers, "/* NEW Destructor style */\nstatic ZEND_RSRC_DTOR_FUNC(_wrap_destroy%s) {\n", key); + Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(_wrap_destroy%s) {\n", key); // write out body if (class_node != NOTCLASS) { @@ -156,9 +157,11 @@ void SwigPHP_emit_resource_registrations() { Printf(s_wrappers, " %s(rsrc, SWIGTYPE%s->name TSRMLS_CC);\n", destructor, key); } else { Printf(s_wrappers, " /* No destructor for class %s */\n", human_name); + Printf(s_wrappers, " efree(rsrc->ptr);\n"); } } else { Printf(s_wrappers, " /* No destructor for simple type %s */\n", key); + Printf(s_wrappers, " efree(rsrc->ptr);\n"); } // close function @@ -168,7 +171,8 @@ void SwigPHP_emit_resource_registrations() { Printf(s_vdecl, "static int le_swig_%s=0; /* handle for %s */\n", key, human_name); // register with php - Printf(s_oinit, "le_swig_%s=zend_register_list_destructors_ex" "(_wrap_destroy%s,NULL,(char *)(SWIGTYPE%s->name),module_number);\n", key, key, key); + Printf(s_oinit, "le_swig_%s=zend_register_list_destructors_ex" + "(_wrap_destroy%s,NULL,(char *)(SWIGTYPE%s->name),module_number);\n", key, key, key); // store php type in class struct Printf(s_oinit, "SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", key, key); @@ -179,20 +183,8 @@ void SwigPHP_emit_resource_registrations() { class PHP : public Language { public: - PHP() { } - - /* Test to see if a type corresponds to something wrapped with a shadow class. */ - - String *is_shadow(SwigType *t) { - String *r = 0; - Node *n = classLookup(t); - if (n) { - r = Getattr(n, "php:proxy"); // Set by classDeclaration() - if (!r) { - r = Getattr(n, "sym:name"); // Not seen by classDeclaration yet, but this is the name - } - } - return r; + PHP() { + director_language = 1; } /* ------------------------------------------------------------ @@ -260,8 +252,21 @@ public: String *filen; String *s_type; + /* Check if directors are enabled for this module. */ + Node *mod = Getattr(n, "module"); + if (mod) { + Node *options = Getattr(mod, "options"); + if (options && Getattr(options, "directors")) { + allow_directors(); + } + } + + /* Set comparison with null for ConstructorToFunction */ + setSubclassInstanceCheck(NewString("$arg->type != IS_NULL")); + /* Initialize all of the output files */ String *outfile = Getattr(n, "outfile"); + String *outfile_h = Getattr(n, "outfile_h"); /* main output file */ f_begin = NewFile(outfile, "w", SWIG_output_files()); @@ -269,7 +274,7 @@ public: FileErrorDisplay(outfile); SWIG_exit(EXIT_FAILURE); } - f_runtime = NewString(""); + f_runtime = NewStringEmpty(); /* sections of the output file */ s_init = NewString("/* init section */\n"); @@ -286,6 +291,16 @@ public: s_oinit = NewString("/* oinit subsection */\n"); pragma_phpinfo = NewStringEmpty(); s_phpclasses = NewString("/* PHP Proxy Classes */\n"); + f_directors_h = NewStringEmpty(); + f_directors = NewStringEmpty(); + + if (directorsEnabled()) { + f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files()); + if (!f_runtime_h) { + FileErrorDisplay(outfile_h); + SWIG_exit(EXIT_FAILURE); + } + } /* Register file targets with the SWIG file handler */ Swig_register_filebyname("begin", f_begin); @@ -296,6 +311,8 @@ public: Swig_register_filebyname("rshutdown", r_shutdown); Swig_register_filebyname("header", s_header); Swig_register_filebyname("wrapper", s_wrappers); + Swig_register_filebyname("director", f_directors); + Swig_register_filebyname("director_h", f_directors_h); Swig_banner(f_begin); @@ -303,12 +320,25 @@ public: Printf(f_runtime, "#define SWIGPHP\n"); Printf(f_runtime, "\n"); + if (directorsEnabled()) { + Printf(f_runtime, "#define SWIG_DIRECTORS\n"); + } + /* Set the module name */ module = Copy(Getattr(n, "name")); cap_module = NewStringf("%(upper)s", module); if (!prefix) prefix = NewStringEmpty(); + if (directorsEnabled()) { + Swig_banner(f_directors_h); + Printf(f_directors_h, "\n"); + Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", cap_module); + Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", cap_module); + + Printf(f_directors, "\n#include \"%s\"\n\n", Swig_file_filename(outfile_h)); + } + /* PHP module file */ filen = NewStringEmpty(); Printv(filen, SWIG_output_directory(), module, ".php", NIL); @@ -326,7 +356,7 @@ public: Printf(f_phpcode, "\n"); Printf(f_phpcode, "// Try to load our extension if it's not already loaded.\n"); - Printf(f_phpcode, "if (!extension_loaded(\"%s\")) {\n", module); + Printf(f_phpcode, "if (!extension_loaded('%s')) {\n", module); Printf(f_phpcode, " if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {\n"); Printf(f_phpcode, " if (!dl('php_%s.dll')) return;\n", module); Printf(f_phpcode, " } else {\n"); @@ -375,6 +405,39 @@ public: Printf(s_header, " SWIG_ErrorCode() = default_error_code;\n"); Printf(s_header, "}\n"); + Append(s_header, "\n"); + Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_alter_newobject) {\n", module); + Append(s_header, " zval **args[2];\n"); + Append(s_header, " swig_object_wrapper *value;\n"); + Append(s_header, " int type;\n"); + Append(s_header, " int thisown;\n"); + Append(s_header, "\n"); + Append(s_header, " SWIG_ResetError();\n"); + Append(s_header, " if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {\n"); + Append(s_header, " WRONG_PARAM_COUNT;\n"); + Append(s_header, " }\n"); + Append(s_header, "\n"); + Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n"); + Append(s_header, " value->newobject = zval_is_true(*args[1]);\n"); + Append(s_header, "\n"); + Append(s_header, " return;\n"); + Append(s_header, "}\n"); + Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_get_newobject) {\n", module); + Append(s_header, " zval **args[1];\n"); + Append(s_header, " swig_object_wrapper *value;\n"); + Append(s_header, " int type;\n"); + Append(s_header, "\n"); + Append(s_header, " SWIG_ResetError();\n"); + Append(s_header, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n"); + Append(s_header, " WRONG_PARAM_COUNT;\n"); + Append(s_header, " }\n"); + Append(s_header, "\n"); + Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n"); + Append(s_header, " RETVAL_LONG(value->newobject);\n"); + Append(s_header, "\n"); + Append(s_header, " return;\n"); + Append(s_header, "}\n"); + Printf(s_header, "#define SWIG_name \"%s\"\n", module); /* Printf(s_header,"#ifdef HAVE_CONFIG_H\n"); Printf(s_header,"#include \"config.h\"\n"); @@ -391,6 +454,11 @@ public: Printf(s_header, "}\n"); Printf(s_header, "#endif\n\n"); + if (directorsEnabled()) { + // Insert director runtime + Swig_insert_file("director.swg", s_header); + } + /* Create the .h file too */ filen = NewStringEmpty(); Printv(filen, SWIG_output_directory(), "php_", module, ".h", NIL); @@ -432,6 +500,10 @@ public: Printf(s_entry, "static zend_function_entry %s_functions[] = {\n", module); /* start the init section */ + Append(s_init, "#if ZEND_MODULE_API_NO <= 20090626\n"); + Append(s_init, "#undef ZEND_MODULE_BUILD_ID\n"); + Append(s_init, "#define ZEND_MODULE_BUILD_ID (char*)\"API\" ZEND_TOSTR(ZEND_MODULE_API_NO) ZEND_BUILD_TS ZEND_BUILD_DEBUG ZEND_BUILD_SYSTEM ZEND_BUILD_EXTRA\n"); + Append(s_init, "#endif\n"); Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n" "#if ZEND_MODULE_API_NO > 20010900\n" " STANDARD_MODULE_HEADER,\n" "#endif\n", NIL); Printf(s_init, " (char*)\"%s\",\n", module); Printf(s_init, " %s_functions,\n", module); @@ -527,13 +599,27 @@ public: * function really needs totally redoing. */ + if (directorsEnabled()) { + Dump(f_directors_h, f_runtime_h); + Printf(f_runtime_h, "\n"); + Printf(f_runtime_h, "#endif\n"); + Close(f_runtime_h); + } + Printf(s_header, "/* end header section */\n"); Printf(s_wrappers, "/* end wrapper section */\n"); Printf(s_vdecl, "/* end vdecl subsection */\n"); Dump(f_runtime, f_begin); - Printv(f_begin, s_header, s_vdecl, s_wrappers, NIL); - Printv(f_begin, all_cs_entry, "\n\n", s_entry, "{NULL, NULL, NULL}\n};\n\n", NIL); + Printv(f_begin, s_header, NIL); + if (directorsEnabled()) { + Dump(f_directors, f_begin); + } + Printv(f_begin, s_vdecl, s_wrappers, NIL); + Printv(f_begin, all_cs_entry, "\n\n", s_entry, + " SWIG_ZEND_NAMED_FE(swig_", module, "_alter_newobject,_wrap_swig_", module, "_alter_newobject,NULL)\n" + " SWIG_ZEND_NAMED_FE(swig_", module, "_get_newobject,_wrap_swig_", module, "_get_newobject,NULL)\n" + "{NULL, NULL, NULL}\n};\n\n", NIL); Printv(f_begin, s_init, NIL); Delete(s_header); Delete(s_wrappers); @@ -576,6 +662,10 @@ public: int maxargs; String *tmp = NewStringEmpty(); + if (Swig_directorclass(n) && wrapperType == directorconstructor) { + /* We have an extra 'this' parameter. */ + SetFlag(n, "wrap:this"); + } String *dispatch = Swig_overload_dispatch(n, "return %s(INTERNAL_FUNCTION_PARAM_PASSTHRU);", &maxargs); /* Generate a dispatch wrapper for all overloaded functions */ @@ -637,6 +727,7 @@ public: ParmList *l = Getattr(n, "parms"); String *nodeType = Getattr(n, "nodeType"); int newobject = GetFlag(n, "feature:new"); + int constructor = (Cmp(nodeType, "constructor") == 0); Parm *p; int i; @@ -674,8 +765,8 @@ public: String *outarg = NewStringEmpty(); String *cleanup = NewStringEmpty(); - // Not issued for overloaded functions or static member variables. - if (!overloaded && wrapperType != staticmembervar) { + // Not issued for overloaded functions. + if (!overloaded) { create_command(iname, wname); } Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL); @@ -692,12 +783,26 @@ public: int num_required = emit_num_required(l); numopt = num_arguments - num_required; + if (wrapperType == directorconstructor) + num_arguments++; + if (num_arguments > 0) { - String *args = NewStringf("zval **args[%d]", num_arguments); + String *args = NewStringEmpty(); + if (wrapperType == directorconstructor) + Wrapper_add_local(f, "arg0", "zval *arg0"); + Printf(args, "zval **args[%d]", num_arguments); Wrapper_add_local(f, "args", args); Delete(args); args = NULL; } + if (is_member_director(n)) { + Wrapper_add_local(f, "director", "Swig::Director *director = 0"); + Printf(f->code, "director = dynamic_cast(arg1);\n"); + Wrapper_add_local(f, "upcall", "bool upcall = false"); + Printf(f->code, "upcall = !director->is_overriden_method((char *)\"%s\", (char *)\"%s\");\n", + Swig_class_name(Swig_methodclass(n)), name); + } + // This generated code may be called: // 1) as an object method, or // 2) as a class-method/function (without a "this_ptr") @@ -722,6 +827,8 @@ public: } Printf(f->code, "WRONG_PARAM_COUNT;\n}\n\n"); } + if (wrapperType == directorconstructor) + Printf(f->code, "arg0 = *args[0];\n \n"); /* Now convert from PHP to C variables */ // At this point, argcount if used is the number of deliberately passed args @@ -733,7 +840,10 @@ public: // _this and not the first argument. // This may mean looking at Language::memberfunctionHandler - for (i = 0, p = l; i < num_arguments; i++) { + int limit = num_arguments; + if (wrapperType == directorconstructor) + limit--; + for (i = 0, p = l; i < limit; i++) { String *source; /* Skip ignored arguments */ @@ -744,7 +854,11 @@ public: SwigType *pt = Getattr(p, "type"); - source = NewStringf("args[%d]", i); + if (wrapperType == directorconstructor) { + source = NewStringf("args[%d]", i+1); + } else { + source = NewStringf("args[%d]", i); + } String *ln = Getattr(p, "lname"); @@ -776,6 +890,8 @@ public: Delete(source); } + Swig_director_emit_dynamic_cast(n, f); + /* Insert constraint checking code */ for (p = l; p;) { if ((tm = Getattr(p, "tmap:check"))) { @@ -858,7 +974,7 @@ public: /* Error handling code */ Printf(f->code, "fail:\n"); Printv(f->code, cleanup, NIL); - Printv(f->code, "zend_error(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());", NIL); + Printv(f->code, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());", NIL); Printf(f->code, "}\n"); @@ -866,6 +982,8 @@ public: Replaceall(f->code, "$symname", iname); Wrapper_print(f, s_wrappers); + DelWrapper(f); + f = NULL; if (overloaded && !Getattr(n, "sym:nextSibling")) { dispatchFunction(n); @@ -875,7 +993,6 @@ public: wname = NULL; if (!shadow) { - DelWrapper(f); return SWIG_OK; } @@ -891,7 +1008,9 @@ public: Setattr(shadow_set_vars, varname, iname); } } + return SWIG_OK; } + // Only look at non-overloaded methods and the last entry in each overload // chain (we check the last so that wrap:parms and wrap:name have been set // for them all). @@ -900,20 +1019,37 @@ public: if (!s_oowrappers) s_oowrappers = NewStringEmpty(); - if (newobject || wrapperType == memberfn || wrapperType == staticmemberfn || wrapperType == standard) { + + if (newobject || wrapperType == memberfn || wrapperType == staticmemberfn || wrapperType == standard || wrapperType == staticmembervar) { bool handle_as_overload = false; String **arg_names; String **arg_values; // Method or static method or plain function. const char *methodname = 0; String *output = s_oowrappers; - if (newobject) { + if (constructor) { class_has_ctor = true; - methodname = "__construct"; + // Skip the Foo:: prefix. + char *ptr = strrchr(GetChar(Swig_methodclass(n), "sym:name"), ':'); + if (ptr) { + ptr++; + } else { + ptr = GetChar(Swig_methodclass(n), "sym:name"); + } + if (strcmp(ptr, GetChar(n, "constructorHandler:sym:name")) == 0) { + methodname = "__construct"; + } else { + // The class has multiple constructors and this one is + // renamed, so this will be a static factory function + methodname = GetChar(n, "constructorHandler:sym:name"); + } } else if (wrapperType == memberfn) { methodname = Char(Getattr(n, "memberfunctionHandler:sym:name")); } else if (wrapperType == staticmemberfn) { methodname = Char(Getattr(n, "staticmemberfunctionHandler:sym:name")); + } else if (wrapperType == staticmembervar) { + // Static member variable, wrapped as a function due to PHP limitations. + methodname = Char(Getattr(n, "staticmembervariableHandler:sym:name")); } else { // wrapperType == standard methodname = Char(iname); if (!s_fakeoowrappers) @@ -924,6 +1060,7 @@ public: bool really_overloaded = overloaded ? true : false; int min_num_of_arguments = emit_num_required(l); int max_num_of_arguments = emit_num_arguments(l); + // For a function with default arguments, we end up with the fullest // parmlist in full_parmlist. ParmList *full_parmlist = l; @@ -1062,6 +1199,11 @@ public: assert(0 <= argno && argno < max_num_of_arguments); String *&pname = arg_names[argno]; const char *pname_cstr = GetChar(p, "name"); + // Just get rid of the C++ namespace part for now. + const char *ptr = NULL; + if (pname_cstr && (ptr = strrchr(pname_cstr, ':'))) { + pname_cstr = ptr + 1; + } if (!pname_cstr) { // Unnamed parameter, e.g. int foo(int); } else if (pname == NULL) { @@ -1258,9 +1400,11 @@ public: /* We use $r to store the return value, so disallow that as a parameter * name in case the user uses the "call-time pass-by-reference" feature * (it's deprecated and off by default in PHP5, but we want to be - * maximally portable). + * maximally portable). Similarly we use $c for the classname or new + * stdClass object. */ Setattr(seen, "r", seen); + Setattr(seen, "c", seen); for (int argno = 0; argno < max_num_of_arguments; ++argno) { String *&pname = arg_names[argno]; @@ -1351,9 +1495,20 @@ public: while (last_handled_i < i) { Printf(prepare, "case %d: ", ++last_handled_i); } - if (Cmp(d, "void") != 0) - Printf(prepare, "$r="); - Printf(prepare, "%s(%s); break;\n", iname, invoke_args); + if (Cmp(d, "void") != 0) { + if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) { + Append(prepare, "$r="); + } else { + Printf(prepare, "$this->%s=", SWIG_PTR); + } + } + if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) { + Printf(prepare, "%s(%s); break;\n", iname, invoke_args); + } else if (!i) { + Printf(prepare, "%s($_this%s); break;\n", iname, invoke_args); + } else { + Printf(prepare, "%s($_this, %s); break;\n", iname, invoke_args); + } } if (i || wrapperType == memberfn) Printf(invoke_args, ","); @@ -1362,9 +1517,19 @@ public: Printf(prepare, "\t\t"); if (had_a_case) Printf(prepare, "default: "); - if (Cmp(d, "void") != 0) - Printf(prepare, "$r="); - Printf(prepare, "%s(%s);\n", iname, invoke_args); + if (Cmp(d, "void") != 0) { + if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) { + Append(prepare, "$r="); + } else { + Printf(prepare, "$this->%s=", SWIG_PTR); + } + } + + if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) { + Printf(prepare, "%s(%s);\n", iname, invoke_args); + } else { + Printf(prepare, "%s($_this, %s);\n", iname, invoke_args); + } if (had_a_case) Printf(prepare, "\t\t}\n"); Delete(invoke_args); @@ -1373,10 +1538,53 @@ public: Printf(output, "\n"); // If it's a member function or a class constructor... - if (wrapperType == memberfn || (newobject && current_class)) { - // We don't need this code if the wrapped class has a copy ctor - // since the flat function new_CLASSNAME will handle it for us. - if (newobject && !Getattr(current_class, "allocate:copy_constructor")) { + if (wrapperType == memberfn || (constructor && current_class)) { + String *acc = NewString(Getattr(n, "access")); + // If a base has the same method with public access, then PHP + // requires to have it here as public as well + Node *bases = Getattr(Swig_methodclass(n), "bases"); + if (bases && Strcmp(acc, "public") != 0) { + String *warnmsg = 0; + int haspublicbase = 0; + Iterator i = First(bases); + while (i.item) { + Node *j = firstChild(i.item); + while (j) { + if (Strcmp(Getattr(j, "name"), Getattr(n, "name")) != 0) { + j = nextSibling(j); + continue; + } + if (Strcmp(nodeType(j), "cdecl") == 0) { + if (!Getattr(j, "access") || checkAttribute(j, "access", "public")) { + haspublicbase = 1; + } + } else if (Strcmp(nodeType(j), "using") == 0 && firstChild(j) && Strcmp(nodeType(firstChild(j)), "cdecl") == 0) { + if (!Getattr(firstChild(j), "access") || checkAttribute(firstChild(j), "access", "public")) { + haspublicbase = 1; + } + } + if (haspublicbase) { + warnmsg = NewStringf("Modifying the access of '%s::%s' to public, as the base '%s' has it as public as well.\n", Getattr(current_class, "classtype"), Getattr(n, "name"), Getattr(i.item, "classtype")); + break; + } + j = nextSibling(j); + } + i = Next(i); + if (haspublicbase) { + break; + } + } + if (Getattr(n, "access") && haspublicbase) { + Delete(acc); + acc = NewString("public"); + Swig_warning(WARN_PHP_PUBLIC_BASE, input_file, line_number, Char(warnmsg)); + Delete(warnmsg); + } + } + if (Cmp(acc, "") != 0) { + Append(acc, " "); + } + if (constructor) { const char * arg0; if (max_num_of_arguments > 0) { arg0 = Char(arg_names[0]); @@ -1387,29 +1595,66 @@ public: } SwigType *t = Getattr(current_class, "classtype"); String *mangled_type = SwigType_manglestr(SwigType_ltype(t)); - Printf(output, "\tfunction %s(%s) {\n", methodname, args); - Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) == \"_p%s\") {\n", arg0, arg0, mangled_type); + Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args); + Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) === '_p%s') {\n", arg0, arg0, mangled_type); Printf(output, "\t\t\t$this->%s=$%s;\n", SWIG_PTR, arg0); Printf(output, "\t\t\treturn;\n"); Printf(output, "\t\t}\n"); } else { - Printf(output, "\tfunction %s(%s) {\n", methodname, args); + Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args); } + Delete(acc); + } else if (wrapperType == staticmembervar) { + // We're called twice for a writable static member variable - first + // with "foo_set" and then with "foo_get" - so generate half the + // wrapper function each time. + // + // For a const static member, we only get called once. + static bool started = false; + if (!started) { + Printf(output, "\tstatic function %s() {\n", methodname); + if (max_num_of_arguments) { + // Setter. + Printf(output, "\t\tif (func_num_args()) {\n"); + Printf(output, "\t\t\t%s(func_get_arg(0));\n", iname); + Printf(output, "\t\t\treturn;\n"); + Printf(output, "\t\t}\n"); + started = true; + goto done; + } + } + started = false; } else { Printf(output, "\tstatic function %s(%s) {\n", methodname, args); } - Delete(args); - args = NULL; - for (int i = 0; i < max_num_of_arguments; ++i) { - Delete(arg_names[i]); - } - free(arg_names); - arg_names = NULL; - - Printf(output, "%s", prepare); - if (newobject) { - Printf(output, "\t\t$this->%s=%s;\n", SWIG_PTR, invoke); + if (!newobject) + Printf(output, "%s", prepare); + if (constructor) { + if (!directorsEnabled() || !Swig_directorclass(n)) { + if (strcmp(methodname, "__construct") == 0) { + Printf(output, "\t\t$this->%s=%s;\n", SWIG_PTR, invoke); + } else { + String *classname = Swig_class_name(current_class); + Printf(output, "\t\treturn new %s(%s);\n", classname, invoke); + } + } else { + Node *parent = Swig_methodclass(n); + String *classname = Swig_class_name(parent); + 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"); + Printf(output, "\t\t}\n"); + if (!Len(prepare)) { + if (num_arguments > 1) { + Printf(output, "\t\t$this->%s=%s($_this, %s);\n", SWIG_PTR, iname, args); + } else { + Printf(output, "\t\t$this->%s=%s($_this);\n", SWIG_PTR, iname); + } + } + } + Printf(output, "%s", prepare); } else if (Cmp(d, "void") == 0) { if (Cmp(invoke, "$r") != 0) Printf(output, "\t\t%s;\n", invoke); @@ -1417,7 +1662,46 @@ public: if (Cmp(invoke, "$r") != 0) Printf(output, "\t\t$r=%s;\n", invoke); if (Len(ret_types) == 1) { - Printf(output, "\t\treturn is_resource($r) ? new %s%s($r) : $r;\n", prefix, Getattr(classLookup(d), "sym:name")); + /* If it has an abstract base, then we can't create a new + * base object. */ + int hasabstractbase = 0; + Node *bases = Getattr(Swig_methodclass(n), "bases"); + if (bases) { + Iterator i = First(bases); + while(i.item) { + if (Getattr(i.item, "abstract")) { + hasabstractbase = 1; + break; + } + i = Next(i); + } + } + if (newobject || !hasabstractbase) { + /* + * _p_Foo -> Foo, _p_ns__Bar -> Bar + * TODO: do this in a more elegant way + */ + Printf(output, "\t\tif (is_resource($r)) {\n"); + if (Getattr(classLookup(Getattr(n, "type")), "module")) { + if (Len(prefix) == 0) { + Printf(output, "\t\t\t$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n"); + } else { + 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%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 { + Printf(output, "\t\t\t$c = new stdClass();\n"); + Printf(output, "\t\t\t$c->_cPtr = $r;\n"); + Printf(output, "\t\t\treturn $c;\n"); + } + Printf(output, "\t\t}\n\t\treturn $r;\n"); + } else { + Printf(output, "\t\t$this->%s = $r;\n", SWIG_PTR); + Printf(output, "\t\treturn $this;\n"); + } } else { Printf(output, "\t\tif (!is_resource($r)) return $r;\n"); Printf(output, "\t\tswitch (get_resource_type($r)) {\n"); @@ -1438,7 +1722,7 @@ public: class_node = Getattr(zend_types, mangled); } if (i.item) { - Printf(output, "case \"%s\": ", mangled); + Printf(output, "case '%s': ", mangled); } else { Printf(output, "default: "); } @@ -1457,12 +1741,21 @@ public: Printf(output, "\t\treturn %s;\n", invoke); } Printf(output, "\t}\n"); + +done: Delete(prepare); Delete(invoke); free(arg_values); - } - DelWrapper(f); + Delete(args); + args = NULL; + + for (int i = 0; i < max_num_of_arguments; ++i) { + Delete(arg_names[i]); + } + free(arg_names); + arg_names = NULL; + } return SWIG_OK; } @@ -1592,7 +1885,7 @@ public: * Pragma directive. * * %pragma(php) code="String" # Includes a string in the .php file - * %pragma(php) include="file.pl" # Includes a file in the .php file + * %pragma(php) include="file.php" # Includes a file in the .php file */ virtual int pragmaDirective(Node *n) { @@ -1608,7 +1901,7 @@ public: } } else if (Strcmp(type, "include") == 0) { if (value) { - Printf(pragma_incl, "include \"%s\";\n", value); + Printf(pragma_incl, "include '%s';\n", value); } } else if (Strcmp(type, "phpinfo") == 0) { if (value) { @@ -1641,9 +1934,7 @@ public: 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"); @@ -1703,52 +1994,73 @@ public: } Printf(s_phpclasses, "class %s%s ", prefix, shadow_classname); - if (base.item) { - String *baseclass = Getattr(base.item, "sym:name"); + String *baseclass = NULL; + if (base.item && Getattr(base.item, "module")) { + baseclass = Getattr(base.item, "sym:name"); if (!baseclass) baseclass = Getattr(base.item, "name"); Printf(s_phpclasses, "extends %s%s ", prefix, baseclass); + } else if (GetFlag(n, "feature:exceptionclass")) { + Append(s_phpclasses, "extends Exception "); } Printf(s_phpclasses, "{\n\tpublic $%s=null;\n", SWIG_PTR); + if (!baseclass) { + // Only store this in the base class (NB !baseclass means we *are* + // a base class...) + Printf(s_phpclasses, "\tprotected $%s=array();\n", SWIG_DATA); + } // Write property SET handlers ki = First(shadow_set_vars); if (ki.key) { // This class has setters. - // FIXME: just ignore setting an unknown property name for now. Printf(s_phpclasses, "\n\tfunction __set($var,$value) {\n"); // FIXME: tune this threshold... if (Len(shadow_set_vars) <= 2) { // Not many setters, so avoid call_user_func. while (ki.key) { key = ki.key; - Printf(s_phpclasses, "\t\tif ($var == '%s') return %s($this->%s,$value);\n", key, ki.item, SWIG_PTR); + Printf(s_phpclasses, "\t\tif ($var === '%s') return %s($this->%s,$value);\n", key, ki.item, SWIG_PTR); ki = Next(ki); } } else { Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_set';\n", shadow_classname); - Printf(s_phpclasses, "\t\tif (function_exists($func)) call_user_func($func,$this->%s,$value);\n", SWIG_PTR); + Printf(s_phpclasses, "\t\tif (function_exists($func)) return call_user_func($func,$this->%s,$value);\n", SWIG_PTR); + } + Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_alter_newobject($this->%s,$value);\n", module, SWIG_PTR); + if (baseclass) { + Printf(s_phpclasses, "\t\t%s%s::__set($var,$value);\n", prefix, baseclass); + } else { + Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\n", SWIG_DATA); } Printf(s_phpclasses, "\t}\n"); /* Create __isset for PHP 5.1 and later; PHP 5.0 will just ignore it. */ Printf(s_phpclasses, "\n\tfunction __isset($var) {\n"); - // FIXME: tune this threshold, but it should probably be different to - // that for __set() and __get() as we don't need to call_user_func() - // here... - if (Len(shadow_set_vars) == 1) { - // Only one setter, so just check the name. - Printf(s_phpclasses, "\t\treturn "); - while (ki.key) { - key = ki.key; - Printf(s_phpclasses, "$var == '%s'", ki.key); - ki = Next(ki); - if (ki.key) Printf(s_phpclasses, " || "); - } - Printf(s_phpclasses, ";\n"); + Printf(s_phpclasses, "\t\tif (function_exists('%s_'.$var.'_set')) return true;\n", shadow_classname); + Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n"); + if (baseclass) { + Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass); } else { - Printf(s_phpclasses, "\t\treturn function_exists('%s_'.$var.'_set');\n", shadow_classname); + Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA); + } + Printf(s_phpclasses, "\t}\n"); + } else { + Printf(s_phpclasses, "\n\tfunction __set($var,$value) {\n"); + Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_alter_newobject($this->%s,$value);\n", module, SWIG_PTR); + if (baseclass) { + Printf(s_phpclasses, "\t\t%s%s::__set($var,$value);\n", prefix, baseclass); + } else { + Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\n", SWIG_DATA); + } + Printf(s_phpclasses, "\t}\n"); + Printf(s_phpclasses, "\n\tfunction __isset($var) {\n"); + Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n"); + if (baseclass) { + Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass); + } else { + Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA); } Printf(s_phpclasses, "\t}\n"); } @@ -1758,20 +2070,37 @@ public: if (ki.key) { // This class has getters. Printf(s_phpclasses, "\n\tfunction __get($var) {\n"); - // FIXME: tune this threshold... - if (Len(shadow_get_vars) <= 2) { - // Not many getters, so avoid call_user_func. - while (ki.key) { - key = ki.key; - Printf(s_phpclasses, "\t\tif ($var == '%s') return %s($this->%s);\n", key, ki.item, SWIG_PTR); - ki = Next(ki); - } + // FIXME: Currently we always use call_user_func for __get, so we can + // check and wrap the result. This is needless if all the properties + // are primitive types. Also this doesn't handle all the cases which + // a method returning an object does. + Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_get';\n", shadow_classname); + Printf(s_phpclasses, "\t\tif (function_exists($func)) {\n"); + Printf(s_phpclasses, "\t\t\t$r = call_user_func($func,$this->%s);\n", SWIG_PTR); + Printf(s_phpclasses, "\t\t\tif (!is_resource($r)) return $r;\n"); + if (Len(prefix) == 0) { + Printf(s_phpclasses, "\t\t\t$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n"); } else { - Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_get';\n", shadow_classname); - Printf(s_phpclasses, "\t\tif (function_exists($func)) return call_user_func($func,$this->%s);\n", SWIG_PTR); + Printf(s_phpclasses, "\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(s_phpclasses, "\t\t\treturn new $c($r);\n"); + Printf(s_phpclasses, "\t\t}\n"); + Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR); + if (baseclass) { + Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass); + } else { + // Reading an unknown property name gives null in PHP. + Printf(s_phpclasses, "\t\treturn $this->%s[$var];\n", SWIG_DATA); + } + Printf(s_phpclasses, "\t}\n"); + } else { + Printf(s_phpclasses, "\n\tfunction __get($var) {\n"); + Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR); + if (baseclass) { + Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass); + } else { + Printf(s_phpclasses, "\t\treturn $this->%s[$var];\n", SWIG_DATA); } - // Reading an unknown property name gives null in PHP. - Printf(s_phpclasses, "\t\treturn null;\n"); Printf(s_phpclasses, "\t}\n"); } @@ -1807,7 +2136,7 @@ public: virtual int memberfunctionHandler(Node *n) { wrapperType = memberfn; - this->Language::memberfunctionHandler(n); + Language::memberfunctionHandler(n); wrapperType = standard; return SWIG_OK; @@ -1834,66 +2163,6 @@ public: Language::staticmembervariableHandler(n); wrapperType = standard; - SwigType *type = Getattr(n, "type"); - String *name = Getattr(n, "name"); - String *iname = Getattr(n, "sym:name"); - - /* A temporary(!) hack for static member variables. - * PHP currently supports class functions, but not class variables. - * Until it does, we convert a class variable to a class function - * that returns the current value of the variable. E.g. - * - * class Example { - * public: - * static int ncount; - * }; - * - * would be available in PHP as Example::ncount() - */ - - // If the variable is const, then it's wrapped as a constant with set/get - // functions. - if (SwigType_isconst(type)) - return SWIG_OK; - - // This duplicates the logic from Language::variableWrapper() to test if - // the set wrapper is made. - int assignable = is_assignable(n); - if (assignable) { - String *tm = Swig_typemap_lookup("globalin", n, name, 0); - if (!tm && SwigType_isarray(type)) { - assignable = 0; - } - } - - String *class_iname = Swig_name_member(Getattr(current_class, "sym:name"), iname); - create_command(iname, Swig_name_wrapper(class_iname)); - - Wrapper *f = NewWrapper(); - - Printv(f->def, "ZEND_NAMED_FUNCTION(", Swig_name_wrapper(class_iname), ") {\n", NIL); - String *mget = Swig_name_wrapper(Swig_name_get(class_iname)); - String *mset = Swig_name_wrapper(Swig_name_set(class_iname)); - - if (assignable) { - Printf(f->code, "if (ZEND_NUM_ARGS() > 0 ) {\n"); - Printf(f->code, " %s( INTERNAL_FUNCTION_PARAM_PASSTHRU );\n", mset); - Printf(f->code, " // need some error checking here?\n"); - Printf(f->code, " // Set the argument count to 0 for the get call\n"); - Printf(f->code, " ht = 0;\n"); - Printf(f->code, "}\n"); - } - - Printf(f->code, "%s( INTERNAL_FUNCTION_PARAM_PASSTHRU );\n", mget); - Printf(f->code, "}\n"); - - Wrapper_print(f, s_wrappers); - - Delete(class_iname); - Delete(mget); - Delete(mset); - DelWrapper(f); - return SWIG_OK; } @@ -1909,53 +2178,6 @@ public: return SWIG_OK; } - String * GetShadowReturnType(Node *n) { - SwigType *t = Getattr(n, "type"); - - /* Map type here */ - switch (SwigType_type(t)) { - case T_CHAR: - case T_SCHAR: - case T_UCHAR: - case T_SHORT: - case T_USHORT: - case T_INT: - case T_UINT: - case T_LONG: - case T_ULONG: - case T_FLOAT: - case T_DOUBLE: - case T_BOOL: - case T_STRING: - case T_VOID: - break; - case T_POINTER: - case T_REFERENCE: - case T_RVALUE_REFERENCE: - case T_USER: - if (is_shadow(t)) { - return NewString(Char(is_shadow(t))); - } - break; - case T_ARRAY: - /* TODO */ - break; - default: - Printf(stderr, "GetShadowReturnType: unhandled data type: %s\n", SwigType_str(t, 0)); - break; - } - - return NewStringEmpty(); - } - - String *PhpTypeFromTypemap(char *op, Node *n, const_String_or_char_ptr lname) { - String *tms = Swig_typemap_lookup(op, n, lname, 0); - if (!tms) - return 0; - else - return NewStringf("%s", tms); - } - int abstractConstructorHandler(Node *) { return SWIG_OK; } @@ -1966,7 +2188,47 @@ public: virtual int constructorHandler(Node *n) { constructors++; - wrapperType = constructor; + if (Swig_directorclass(n)) { + String *name = GetChar(Swig_methodclass(n), "name"); + String *ctype = GetChar(Swig_methodclass(n), "classtype"); + String *sname = GetChar(Swig_methodclass(n), "sym:name"); + String *args = NewStringEmpty(); + ParmList *p = Getattr(n, "parms"); + int i; + + for (i = 0; p; p = nextSibling(p), i++) { + if (i) { + Printf(args, ", "); + } + if (Strcmp(GetChar(p, "type"), SwigType_str(GetChar(p, "type"), 0))) { + SwigType *t = Getattr(p, "type"); + Printf(args, "%s", SwigType_rcaststr(t, 0)); + if (SwigType_isreference(t)) { + Append(args, "*"); + } + } + Printf(args, "arg%d", i+1); + } + + /* director ctor code is specific for each class */ + Delete(director_ctor_code); + director_ctor_code = NewStringEmpty(); + director_prot_ctor_code = NewStringEmpty(); + Printf(director_ctor_code, "if ( arg0->type == IS_NULL ) { /* not subclassed */\n"); + Printf(director_prot_ctor_code, "if ( arg0->type == IS_NULL ) { /* not subclassed */\n"); + Printf(director_ctor_code, " result = (%s *)new %s(%s);\n", ctype, ctype, args); + Printf(director_prot_ctor_code, " SWIG_PHP_Error(E_ERROR, \"accessing abstract class or protected constructor\");\n", name, name, args); + if (i) { + Insert(args, 0, ", "); + } + Printf(director_ctor_code, "} else {\n result = (%s *)new SwigDirector_%s(arg0%s);\n}\n", ctype, sname, args); + Printf(director_prot_ctor_code, "} else {\n result = (%s *)new SwigDirector_%s(arg0%s);\n}\n", ctype, sname, args); + Delete(args); + + wrapperType = directorconstructor; + } else { + wrapperType = constructor; + } Language::constructorHandler(n); wrapperType = standard; @@ -2019,6 +2281,9 @@ public: Append(f->code, actioncode); Delete(actioncode); + Append(f->code, "return;\n"); + Append(f->code, "fail:\n"); + Append(f->code, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\n"); Printf(f->code, "}\n"); Wrapper_print(f, s_wrappers); @@ -2037,6 +2302,400 @@ public: return SWIG_OK; } + int classDirectorInit(Node *n) { + String *declaration = Swig_director_declaration(n); + Printf(f_directors_h, "%s\n", declaration); + Printf(f_directors_h, "public:\n"); + Delete(declaration); + return Language::classDirectorInit(n); + } + + int classDirectorEnd(Node *n) { + Printf(f_directors_h, "};\n"); + return Language::classDirectorEnd(n); + } + + int classDirectorConstructor(Node *n) { + Node *parent = Getattr(n, "parentNode"); + String *decl = Getattr(n, "decl"); + String *supername = Swig_class_name(parent); + String *classname = NewStringEmpty(); + Printf(classname, "SwigDirector_%s", supername); + + /* insert self parameter */ + Parm *p; + ParmList *superparms = Getattr(n, "parms"); + ParmList *parms = CopyParmList(superparms); + String *type = NewString("zval"); + SwigType_add_pointer(type); + p = NewParm(type, NewString("self"), n); + set_nextSibling(p, parms); + parms = p; + + if (!Getattr(n, "defaultargs")) { + /* constructor */ + { + Wrapper *w = NewWrapper(); + String *call; + String *basetype = Getattr(parent, "classtype"); + String *target = Swig_method_decl(0, decl, classname, parms, 0, 0); + call = Swig_csuperclass_call(0, basetype, superparms); + Printf(w->def, "%s::%s: %s, Swig::Director(self) {", classname, target, call); + Append(w->def, "}"); + Delete(target); + Wrapper_print(w, f_directors); + Delete(call); + DelWrapper(w); + } + + /* constructor header */ + { + String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); + Printf(f_directors_h, " %s;\n", target); + Delete(target); + } + } + return Language::classDirectorConstructor(n); + } + + int classDirectorMethod(Node *n, Node *parent, String *super) { + int is_void = 0; + int is_pointer = 0; + String *decl; + String *type; + String *name; + String *classname; + String *c_classname = Getattr(parent, "name"); + String *declaration; + ParmList *l; + Wrapper *w; + String *tm; + String *wrap_args = NewStringEmpty(); + String *return_type; + String *value = Getattr(n, "value"); + String *storage = Getattr(n, "storage"); + bool pure_virtual = false; + int status = SWIG_OK; + int idx; + bool ignored_method = GetFlag(n, "feature:ignore") ? true : false; + + if (Cmp(storage, "virtual") == 0) { + if (Cmp(value, "0") == 0) { + pure_virtual = true; + } + } + + classname = Getattr(parent, "sym:name"); + type = Getattr(n, "type"); + name = Getattr(n, "name"); + + w = NewWrapper(); + declaration = NewStringEmpty(); + + /* determine if the method returns a pointer */ + decl = Getattr(n, "decl"); + is_pointer = SwigType_ispointer_return(decl); + is_void = (Cmp(type, "void") == 0 && !is_pointer); + + /* form complete return type */ + return_type = Copy(type); + { + SwigType *t = Copy(decl); + SwigType *f = SwigType_pop_function(t); + SwigType_push(return_type, t); + Delete(f); + Delete(t); + } + + /* virtual method definition */ + l = Getattr(n, "parms"); + String *target; + String *pclassname = NewStringf("SwigDirector_%s", classname); + String *qualified_name = NewStringf("%s::%s", pclassname, name); + SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type; + target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); + Printf(w->def, "%s", target); + Delete(qualified_name); + Delete(target); + /* header declaration */ + target = Swig_method_decl(rtype, decl, name, l, 0, 1); + Printf(declaration, " virtual %s", target); + Delete(target); + + // Get any exception classes in the throws typemap + ParmList *throw_parm_list = 0; + + if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { + Parm *p; + int gencomma = 0; + + Append(w->def, " throw("); + Append(declaration, " throw("); + + if (throw_parm_list) + Swig_typemap_attach_parms("throws", throw_parm_list, 0); + for (p = throw_parm_list; p; p = nextSibling(p)) { + if ((tm = Getattr(p, "tmap:throws"))) { + if (gencomma++) { + Append(w->def, ", "); + Append(declaration, ", "); + } + String *str = SwigType_str(Getattr(p, "type"), 0); + Append(w->def, str); + Append(declaration, str); + Delete(str); + } + } + + Append(w->def, ")"); + Append(declaration, ")"); + } + + Append(w->def, " {"); + Append(declaration, ";\n"); + + /* declare method return value + * if the return value is a reference or const reference, a specialized typemap must + * handle it, including declaration of c_result ($result). + */ + if (!is_void) { + if (!(ignored_method && !pure_virtual)) { + String *cres = SwigType_lstr(return_type, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); + } + } + + if (ignored_method) { + if (!pure_virtual) { + if (!is_void) + Printf(w->code, "return "); + String *super_call = Swig_method_call(super, l); + Printf(w->code, "%s;\n", super_call); + Delete(super_call); + } else { + Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname), + SwigType_namestr(name)); + } + } else { + /* attach typemaps to arguments (C/C++ -> PHP) */ + String *parse_args = NewStringEmpty(); + + /* remove the wrapper 'w' since it was producing spurious temps */ + Swig_typemap_attach_parms("in", l, 0); + Swig_typemap_attach_parms("directorin", l, 0); + Swig_typemap_attach_parms("directorargout", l, w); + + Parm *p; + char source[256]; + + int outputs = 0; + if (!is_void) + outputs++; + + /* build argument list and type conversion string */ + idx = 0; + p = l; + int use_parse = 0; + while (p != NULL) { + if (checkAttribute(p, "tmap:in:numinputs", "0")) { + p = Getattr(p, "tmap:in:next"); + continue; + } + + if (Getattr(p, "tmap:directorargout") != 0) + outputs++; + + String *pname = Getattr(p, "name"); + String *ptype = Getattr(p, "type"); + + if ((tm = Getattr(p, "tmap:directorin")) != 0) { + String *parse = Getattr(p, "tmap:directorin:parse"); + if (!parse) { + sprintf(source, "obj%d", idx++); + String *input = NewStringf("&%s", source); + Replaceall(tm, "$input", input); + Delete(input); + Replaceall(tm, "$owner", "0"); + Printv(wrap_args, "zval ", source, ";\n", NIL); + Printf(wrap_args, "args[%d] = &%s;\n", idx - 1, source); + + Printv(wrap_args, tm, "\n", NIL); + Putc('O', parse_args); + } else { + use_parse = 1; + Append(parse_args, parse); + Replaceall(tm, "$input", pname); + Replaceall(tm, "$owner", "0"); + if (Len(tm) == 0) + Append(tm, pname); + } + p = Getattr(p, "tmap:directorin:next"); + continue; + } else if (Cmp(ptype, "void")) { + Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, + "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0), + SwigType_namestr(c_classname), SwigType_namestr(name)); + status = SWIG_NOWRAP; + break; + } + p = nextSibling(p); + } + + /* 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 { + Printf(w->code, "zval *args[%d];\n", idx); + } + Append(w->code, "zval *result, funcname;\n"); + Append(w->code, "MAKE_STD_ZVAL(result);\n"); + Printf(w->code, "ZVAL_STRING(&funcname, (char *)\"%s\", 0);\n", name); + Append(w->code, "if (!swig_self) {\n"); + Append(w->code, " SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");"); + Append(w->code, "}\n\n"); + + /* wrap complex arguments to zvals */ + Printv(w->code, wrap_args, NIL); + + Append(w->code, "call_user_function(EG(function_table), (zval**)&swig_self, &funcname,\n"); + Printf(w->code, " result, %d, args TSRMLS_CC);\n", idx); + + if (tm) { + Printv(w->code, Str(tm), "\n", NIL); + Delete(tm); + } + + /* marshal return value from PHP to C/C++ type */ + + String *cleanup = NewStringEmpty(); + String *outarg = NewStringEmpty(); + + idx = 0; + + /* marshal return value */ + if (!is_void) { + /* this seems really silly. the node's type excludes + * qualifier/pointer/reference markers, which have to be retrieved + * from the decl field to construct return_type. but the typemap + * lookup routine uses the node's type, so we have to swap in and + * out the correct type. it's not just me, similar silliness also + * occurs in Language::cDeclaration(). + */ + Setattr(n, "type", return_type); + tm = Swig_typemap_lookup("directorout", n, "result", w); + Setattr(n, "type", type); + if (tm != 0) { + Replaceall(tm, "$input", "&result"); + char temp[24]; + sprintf(temp, "%d", idx); + Replaceall(tm, "$argnum", temp); + + /* TODO check this */ + if (Getattr(n, "wrap:disown")) { + Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN"); + } else { + Replaceall(tm, "$disown", "0"); + } + Replaceall(tm, "$result", "c_result"); + Printv(w->code, tm, "\n", NIL); + Delete(tm); + } else { + Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number, + "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(return_type, 0), SwigType_namestr(c_classname), + SwigType_namestr(name)); + status = SWIG_ERROR; + } + } + + /* marshal outputs */ + for (p = l; p;) { + if ((tm = Getattr(p, "tmap:directorargout")) != 0) { + Replaceall(tm, "$input", "result"); + Replaceall(tm, "$result", Getattr(p, "name")); + Printv(w->code, tm, "\n", NIL); + p = Getattr(p, "tmap:directorargout:next"); + } else { + p = nextSibling(p); + } + } + + Append(w->code, "FREE_ZVAL(result);\n"); + + Delete(parse_args); + Delete(cleanup); + Delete(outarg); + } + + if (!is_void) { + if (!(ignored_method && !pure_virtual)) { + String *rettype = SwigType_str(return_type, 0); + if (!SwigType_isreference(return_type)) { + Printf(w->code, "return (%s) c_result;\n", rettype); + } else { + Printf(w->code, "return (%s) *c_result;\n", rettype); + } + Delete(rettype); + } + } else { + Append(w->code, "return;\n"); + } + + Append(w->code, "fail:\n"); + Append(w->code, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\n"); + Append(w->code, "}\n"); + + // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method + String *inline_extra_method = NewStringEmpty(); + if (dirprot_mode() && !is_public(n) && !pure_virtual) { + Printv(inline_extra_method, declaration, NIL); + String *extra_method_name = NewStringf("%sSwigPublic", name); + Replaceall(inline_extra_method, name, extra_method_name); + Replaceall(inline_extra_method, ";\n", " {\n "); + if (!is_void) + Printf(inline_extra_method, "return "); + String *methodcall = Swig_method_call(super, l); + Printv(inline_extra_method, methodcall, ";\n }\n", NIL); + Delete(methodcall); + Delete(extra_method_name); + } + + /* emit the director method */ + if (status == SWIG_OK) { + if (!Getattr(n, "defaultargs")) { + Wrapper_print(w, f_directors); + Printv(f_directors_h, declaration, NIL); + Printv(f_directors_h, inline_extra_method, NIL); + } + } + + /* clean up */ + Delete(wrap_args); + Delete(return_type); + Delete(pclassname); + DelWrapper(w); + return status; + } + + int classDirectorDisown(Node *) { + return SWIG_OK; + } }; /* class PHP */ static PHP *maininstance = 0; diff --git a/Source/Modules/pike.cxx b/Source/Modules/pike.cxx index e59248e95..6913596d3 100644 --- a/Source/Modules/pike.cxx +++ b/Source/Modules/pike.cxx @@ -766,7 +766,7 @@ public: /* Create a function to set the values of the (mutable) variables */ if (need_setter) { Wrapper *wrapper = NewWrapper(); - String *setter = Swig_name_member(getClassPrefix(), (char *) "`->="); + String *setter = Swig_name_member(getClassPrefix(), "`->="); String *wname = Swig_name_wrapper(setter); Printv(wrapper->def, "static void ", wname, "(INT32 args) {", NIL); Printf(wrapper->locals, "char *name = (char *) STR0(Pike_sp[0-args].u.string);\n"); @@ -805,7 +805,7 @@ public: /* Create a function to get the values of the (mutable) variables */ Wrapper *wrapper = NewWrapper(); - String *getter = Swig_name_member(getClassPrefix(), (char *) "`->"); + String *getter = Swig_name_member(getClassPrefix(), "`->"); String *wname = Swig_name_wrapper(getter); Printv(wrapper->def, "static void ", wname, "(INT32 args) {", NIL); Printf(wrapper->locals, "char *name = (char *) STR0(Pike_sp[0-args].u.string);\n"); diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 546ab9ec5..bafd567e0 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -147,8 +147,8 @@ static const char *usage3 = (char *) "\ -proxydel - Generate a __del__ method even though it is now redundant (default) \n\ -safecstrings - Use safer (but slower) C string mapping, generating copies from Python -> C/C++\n\ -threads - Add thread support for all the interface\n\ - -O - Enable all the optimization options: \n\ - -modern -fastdispatch -dirvtable -nosafecstrings -fvirtual -noproxydel \n\ + -O - Enable the following optimization options: \n\ + -modern -fastdispatch -nosafecstrings -fvirtual -noproxydel \n\ -fastproxy -fastinit -fastunpack -fastquery -modernargs -nobuildnone \n\ -py3 - Generate code with Python 3 specific features:\n\ Function annotation \n\ @@ -409,7 +409,6 @@ public: } else if (strcmp(argv[i], "-O") == 0) { classic = 0; modern = 1; - dirvtable = 1; safecstrings = 0; buildnone = 0; nobuildnone = 1; @@ -732,7 +731,7 @@ public: Printf(f_shadow, tab8 tab8 "_mod = imp.load_module('%s', fp, pathname, description)\n", module); Printv(f_shadow, tab4 tab8, "finally:\n", NULL); Printv(f_shadow, tab8 tab8, "fp.close()\n", NULL); - Printv(f_shadow, tab8 tab8, "return _mod\n", NULL); + Printv(f_shadow, tab4 tab8, "return _mod\n", NULL); Printf(f_shadow, tab4 "%s = swig_import_helper()\n", module); Printv(f_shadow, tab4, "del swig_import_helper\n", NULL); Printv(f_shadow, "else:\n", NULL); @@ -1917,7 +1916,7 @@ public: Printv(f->def, "SWIGINTERN PyObject *", wname, "__varargs__", "(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *varargs) {", NIL); } if (allow_kwargs) { - Swig_warning(WARN_LANG_OVERLOAD_KEYWORD, input_file, line_number, "Can't use keyword arguments with overloaded functions.\n"); + Swig_warning(WARN_LANG_OVERLOAD_KEYWORD, input_file, line_number, "Can't use keyword arguments with overloaded functions (%s).\n", Swig_name_decl(n)); allow_kwargs = 0; } } else { @@ -2629,7 +2628,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; @@ -2988,7 +2987,7 @@ public: Delete(realct); } if (!have_constructor) { - Printv(f_shadow_file, tab4, "def __init__(self, *args, **kwargs): raise AttributeError(\"No constructor defined\")\n", NIL); + Printv(f_shadow_file, tab4, "def __init__(self, *args, **kwargs): raise AttributeError(\"", "No constructor defined", (Getattr(n, "abstract") ? " - class is abstract" : ""), "\")\n", NIL); } else if (fastinit) { Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL); @@ -3209,7 +3208,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"); @@ -3953,11 +3952,6 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { Setattr(n, "type", return_type); tm = Swig_typemap_lookup("directorout", n, "result", w); Setattr(n, "type", type); - if (tm == 0) { - String *name = NewString("result"); - tm = Swig_typemap_search("directorout", return_type, name, NULL); - Delete(name); - } if (tm != 0) { if (outputs > 1) { Printf(w->code, "output = PyTuple_GetItem(result, %d);\n", idx++); diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index f1fdff662..ad83d608a 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -70,40 +70,6 @@ static String * getRTypeName(SwigType *t, int *outCount = NULL) { */ } -#if 0 -static String * getRType(Node *n) { - SwigType *elType = Getattr(n, "type"); - SwigType *elDecl = Getattr(n, "decl"); - //XXX How can we tell if this is already done. - SwigType_push(elType, elDecl); - String *ans; - - String *rtype = Swig_typemap_lookup("rtype", n, "", 0); - String *i = getRTypeName(elType); - - if(Len(i) == 0) { - SwigType *td = SwigType_typedef_resolve(elType); - if(td) { - // Printf(stderr, "Resolving typedef %s -> %s\n", elType, td); - i = getRTypeName(td); - } - } - // Printf(stderr, " i = %s, rtype = %s (for %s)\n", - // i, rtype, elType); - if(rtype) { - ans = NewString(""); - Printf(ans, "%s", rtype); - Replaceall(ans, "$R_class", Char(i)); - // Printf(stderr, "Found r type in typemap for %s (for %s) => %s (%s) => %s\n", - // SwigType_str(elType, 0), Getattr(n, "name"), rtype, i, ans); - } else { - ans = i; - } - - return(ans); -} -#endif - /********************* Tries to get the name of the R class corresponding to the given type e.g. struct A * is ARef, struct A** is ARefRef. @@ -534,12 +500,7 @@ int R::getFunctionPointerNumArgs(Node *n, SwigType *tt) { n = Getattr(n, "type"); if (debugMode) Printf(stderr, "type: %s\n", n); -#if 0 - SwigType *tmp = SwigType_typedef_resolve(tt); - - n = SwigType_typedef_resolve(tt); -#endif - + ParmList *parms = Getattr(n, "parms"); if (debugMode) Printf(stderr, "parms = %p\n", parms); @@ -592,7 +553,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) { @@ -716,10 +677,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; @@ -1105,7 +1063,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); @@ -1121,7 +1079,7 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, Printf(f->code, "'%s'%s", item, vcount < varaccessor ? ", " : ""); } } - Printf(f->code, ")\n"); + Printf(f->code, ");\n"); } @@ -1133,24 +1091,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"); @@ -1161,15 +1119,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); @@ -1422,15 +1380,13 @@ static List * Swig_overload_rank(Node *n, String *t2 = Getattr(p2,"tmap:typecheck:precedence"); if ((!t1) && (!nodes[i].error)) { Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n), - "Overloaded %s(%s) not supported (no type checking rule for '%s').\n", - Getattr(nodes[i].n,"name"),ParmList_str_defaultargs(Getattr(nodes[i].n,"parms")), - SwigType_str(Getattr(p1,"type"),0)); + "Overloaded method %s not supported (no type checking rule for '%s').\n", + Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0)); nodes[i].error = 1; } else if ((!t2) && (!nodes[j].error)) { Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded %s(%s) not supported (no type checking rule for '%s').\n", - Getattr(nodes[j].n,"name"),ParmList_str_defaultargs(Getattr(nodes[j].n,"parms")), - SwigType_str(Getattr(p2,"type"),0)); + "xx Overloaded method %s not supported (no type checking rule for '%s').\n", + Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0)); nodes[j].error = 1; } if (t1 && t2) { @@ -1495,8 +1451,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); @@ -1506,49 +1462,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; } } @@ -1558,24 +1512,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 %s(%s)%s is shadowed by %s(%s)%s at %s:%d.\n", - Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms), - SwigType_isconst(Getattr(nodes[j].n,"decl")) ? " const" : "", - Getattr(nodes[i].n,"name"), ParmList_errorstr(nodes[i].parms), - SwigType_isconst(Getattr(nodes[i].n,"decl")) ? " const" : "", - 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)%s ignored. Method %s(%s)%s at %s:%d used.\n", - Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms), - SwigType_isconst(Getattr(nodes[j].n,"decl")) ? " const" : "", - Getattr(nodes[i].n,"name"), ParmList_errorstr(nodes[i].parms), - SwigType_isconst(Getattr(nodes[i].n,"decl")) ? " const" : "", - 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; } } @@ -1613,9 +1561,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; @@ -1661,16 +1609,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); @@ -1898,16 +1846,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); @@ -2102,10 +2050,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); @@ -2464,11 +2412,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); @@ -2478,9 +2426,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 9badc0d0a..82808b154 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -2578,7 +2578,7 @@ public: /* First wrap the allocate method */ current = CONSTRUCTOR_ALLOCATE; - Swig_name_register((const_String_or_char_ptr ) "construct", (const_String_or_char_ptr ) "%c_allocate"); + Swig_name_register("construct", "%c_allocate"); Language::constructorHandler(n); @@ -2594,7 +2594,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"); @@ -2613,7 +2613,7 @@ public: Delete(docs); current = CONSTRUCTOR_INITIALIZE; - Swig_name_register((const_String_or_char_ptr ) "construct", (const_String_or_char_ptr ) "new_%c"); + Swig_name_register("construct", "new_%c"); Language::constructorHandler(n); /* Restore original parameter list */ @@ -2635,7 +2635,7 @@ public: /* First wrap the allocate method */ current = CONSTRUCTOR_ALLOCATE; - Swig_name_register((const_String_or_char_ptr ) "construct", (const_String_or_char_ptr ) "%c_allocate"); + Swig_name_register("construct", "%c_allocate"); return Language::copyconstructorHandler(n); } @@ -2816,7 +2816,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; @@ -3249,11 +3249,6 @@ public: Setattr(n, "type", return_type); tm = Swig_typemap_lookup("directorout", n, "result", w); Setattr(n, "type", type); - if (tm == 0) { - String *name = NewString("result"); - tm = Swig_typemap_search("directorout", return_type, name, NULL); - Delete(name); - } if (tm != 0) { if (outputs > 1 && !asvoid ) { Printf(w->code, "output = rb_ary_entry(result, %d);\n", idx++); diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx index 374d08e5a..1ed85e82e 100644 --- a/Source/Modules/swigmain.cxx +++ b/Source/Modules/swigmain.cxx @@ -200,7 +200,8 @@ int main(int margc, char **margv) { dl = (fac) (); } } + int res = SWIG_main(argc, argv, dl); - delete dl; + return res; } diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index 075a209d2..813c56cb9 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -212,14 +212,16 @@ public: /* Miscellaneous */ virtual int validIdentifier(String *s); /* valid identifier? */ - virtual int addSymbol(const String *s, const Node *n); /* Add symbol */ - virtual Node *symbolLookup(String *s); /* Symbol lookup */ + virtual int addSymbol(const String *s, const Node *n, const_String_or_char_ptr scope = ""); /* Add symbol */ + virtual void dumpSymbols(); + virtual Node *symbolLookup(String *s, const_String_or_char_ptr scope = ""); /* Symbol lookup */ virtual Node *classLookup(SwigType *s); /* Class lookup */ virtual Node *enumLookup(SwigType *s); /* Enum lookup */ virtual int abstractClassTest(Node *n); /* Is class really abstract? */ virtual int is_assignable(Node *n); /* Is variable assignable? */ virtual String *runtimeCode(); /* returns the language specific runtime code */ virtual String *defaultExternalRuntimeFilename(); /* the default filename for the external runtime */ + virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm); /* Language specific special variable substitutions for $typemap() */ /* Runtime is C++ based, so extern "C" header section */ void enable_cplus_runtime_mode(); @@ -254,6 +256,9 @@ public: /* Set overload variable templates argc and argv */ void setOverloadResolutionTemplates(String *argc, String *argv); + /* Language instance is a singleton - get instance */ + static Language* instance(); + protected: /* Allow multiple-input typemaps */ void allow_multiple_input(int val = 1); @@ -304,13 +309,14 @@ protected: int director_language; private: - Hash *symbols; + Hash *symtabs; /* symbol tables */ Hash *classtypes; Hash *enumtypes; int overloading; int multiinput; int cplus_runtime; int directors; + static Language *this_; }; int SWIG_main(int, char **, Language *); @@ -320,6 +326,7 @@ void SWIG_exit(int); /* use EXIT_{SUCCESS,FAILURE} */ void SWIG_config_file(const_String_or_char_ptr ); const String *SWIG_output_directory(); void SWIG_config_cppext(const char *ext); +void Swig_print_xml(Node *obj, String *filename); /* get the list of generated files */ List *SWIG_output_files(); @@ -351,7 +358,9 @@ void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f); extern "C" { void SWIG_typemap_lang(const char *); typedef Language *(*ModuleFactory) (void); -} void Swig_register_module(const char *name, ModuleFactory fac); +} + +void Swig_register_module(const char *name, ModuleFactory fac); ModuleFactory Swig_find_module(const char *name); /* Utilities */ diff --git a/Source/Modules/tcl8.cxx b/Source/Modules/tcl8.cxx index efbe28c50..94191abcc 100644 --- a/Source/Modules/tcl8.cxx +++ b/Source/Modules/tcl8.cxx @@ -32,7 +32,7 @@ static String *methods_tab = 0; /* Methods table */ static String *attr_tab = 0; /* Attribute table */ static String *prefix = 0; static String *module = 0; -static int nspace = 0; +static int namespace_option = 0; static String *init_name = 0; static String *ns_name = 0; static int have_constructor; @@ -101,7 +101,7 @@ public: i++; } } else if (strcmp(argv[i], "-namespace") == 0) { - nspace = 1; + namespace_option = 1; Swig_mark_arg(i); } else if (strcmp(argv[i], "-itcl") == 0) { itcl = 1; @@ -208,7 +208,7 @@ public: Printf(f_header, "#define SWIG_init %s\n", init_name); Printf(f_header, "#define SWIG_name \"%s\"\n", module); - if (nspace) { + if (namespace_option) { Printf(f_header, "#define SWIG_prefix \"%s::\"\n", ns_name); Printf(f_header, "#define SWIG_namespace \"%s\"\n\n", ns_name); } else { @@ -670,7 +670,7 @@ public: virtual int constantWrapper(Node *n) { String *name = Getattr(n, "name"); String *iname = Getattr(n, "sym:name"); - String *nsname = !nspace ? Copy(iname) : NewStringf("%s::%s", ns_name, iname); + String *nsname = !namespace_option ? Copy(iname) : NewStringf("%s::%s", ns_name, iname); SwigType *type = Getattr(n, "type"); String *rawval = Getattr(n, "rawval"); String *value = rawval ? rawval : Getattr(n, "value"); @@ -678,7 +678,7 @@ public: if (!addSymbol(iname, n)) return SWIG_ERROR; - if (nspace) + if (namespace_option) Setattr(n, "sym:name", nsname); /* Special hook for member pointer */ @@ -869,7 +869,7 @@ public: Printv(ptrclass, attributes, NIL); // base class swig_getset was being called for complex inheritance trees - if (nspace) { + if (namespace_option) { Printv(ptrclass, " protected method ", class_name, "_swig_getset {var name1 name2 op} {\n", NIL); @@ -935,13 +935,13 @@ public: Printv(f_shadow, " constructor { } {\n", NIL); Printv(f_shadow, " # This constructor will fail if called directly\n", NIL); Printv(f_shadow, " if { [info class] == \"::", class_name, "\" } {\n", NIL); - Printv(f_shadow, " error \"No constructor for class ", class_name, "\"\n", NIL); + Printv(f_shadow, " error \"No constructor for class ", class_name, (Getattr(n, "abstract") ? " - class is abstract" : ""), "\"\n", NIL); Printv(f_shadow, " }\n", NIL); Printv(f_shadow, " }\n", NIL); } Printv(f_shadow, "}\n\n", NIL); - }; + } Printv(f_wrappers, "static swig_class *swig_", mangled_classname, "_bases[] = {", base_class, "0};\n", NIL); Printv(f_wrappers, "static const char * swig_", mangled_classname, "_base_names[] = {", base_class_names, "0};\n", NIL); @@ -1022,7 +1022,7 @@ public: if (Len(dv) > 0) { String *defval = NewString(dv); - if (nspace) { + if (namespace_option) { Insert(defval, 0, "::"); Insert(defval, 0, ns_name); } @@ -1040,7 +1040,7 @@ public: } Printv(imethods, "] ", NIL); - if (nspace) { + if (namespace_option) { Printv(imethods, "{ ", ns_name, "::", class_name, "_", realname, " $swigobj", NIL); } else { Printv(imethods, "{ ", class_name, "_", realname, " $swigobj", NIL); @@ -1168,7 +1168,7 @@ public: // Call to constructor wrapper and parent Ptr class // [BRE] add -namespace/-prefix support - if (nspace) { + if (namespace_option) { Printv(constructor, " ", realname, "Ptr::constructor [", ns_name, "::new_", realname, NIL); } else { Printv(constructor, " ", realname, "Ptr::constructor [new_", realname, NIL); @@ -1235,7 +1235,7 @@ public: if (!temp) temp = NewString(""); Clear(temp); - if (nspace) { + if (namespace_option) { Printf(temp, "%s::%s ", ns_name, iname); } else { Printf(temp, "%s ", iname); diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index e972cea05..8d4ddda11 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -734,6 +734,49 @@ class TypePass:private Dispatcher { } Setattr(n, "enumtype", enumtype); + // This block of code is for dealing with %ignore on an enum item where the target language + // attempts to use the C enum value in the target language itself and expects the previous enum value + // to be one more than the previous value... the previous enum item might not exist if it is ignored! + // - It sets the first non-ignored enum item with the "firstenumitem" attribute. + // - It adds an enumvalue attribute if the previous enum item is ignored + { + Node *c; + int count = 0; + String *previous = 0; + bool previous_ignored = false; + bool firstenumitem = false; + for (c = firstChild(n); c; c = nextSibling(c)) { + assert(strcmp(Char(nodeType(c)), "enumitem") == 0); + + bool reset; + String *enumvalue = Getattr(c, "enumvalue"); + if (GetFlag(c, "feature:ignore")) { + reset = enumvalue ? true : false; + previous_ignored = true; + } else { + if (!enumvalue && previous_ignored) { + if (previous) + Setattr(c, "enumvalue", NewStringf("(%s) + %d", previous, count+1)); + else + Setattr(c, "enumvalue", NewStringf("%d", count)); + SetFlag(c, "virtenumvalue"); // identify enumvalue as virtual, ie not from the parsed source + } + if (!firstenumitem) { + SetFlag(c, "firstenumitem"); + firstenumitem = true; + } + reset = true; + previous_ignored = false; + } + if (reset) { + previous = enumvalue ? enumvalue : Getattr(c, "name"); + count = 0; + } else { + count++; + } + } + } + emit_children(n); return SWIG_OK; } @@ -757,13 +800,16 @@ class TypePass:private Dispatcher { Setattr(n, "value", new_value); Delete(new_value); } - // Make up an enumvalue if one was not specified in the parsed code - if (Getattr(n, "_last") && !Getattr(n, "enumvalue")) { // Only the first enum item has _last set - Setattr(n, "enumvalueex", "0"); - } Node *next = nextSibling(n); - if (next && !Getattr(next, "enumvalue")) { - Setattr(next, "enumvalueex", NewStringf("%s + 1", Getattr(n, "sym:name"))); + + // Make up an enumvalue if one was not specified in the parsed code (not designed to be used on enum items and %ignore - enumvalue will be set instead) + if (!GetFlag(n, "feature:ignore")) { + if (Getattr(n, "_last") && !Getattr(n, "enumvalue")) { // Only the first enum item has _last set (Note: first non-ignored enum item has firstenumitem set) + Setattr(n, "enumvalueex", "0"); + } + if (next && !Getattr(next, "enumvalue")) { + Setattr(next, "enumvalueex", NewStringf("%s + 1", Getattr(n, "sym:name"))); + } } return SWIG_OK; diff --git a/Source/Modules/uffi.cxx b/Source/Modules/uffi.cxx index f793b5643..ac17ca925 100644 --- a/Source/Modules/uffi.cxx +++ b/Source/Modules/uffi.cxx @@ -135,11 +135,17 @@ static void add_defined_foreign_type(String *type) { } -static String *get_ffi_type(SwigType *ty, const_String_or_char_ptr name) { - Hash *typemap = Swig_typemap_search("ffitype", ty, name, 0); - if (typemap) { - String *typespec = Getattr(typemap, "code"); - return NewString(typespec); +static String *get_ffi_type(Node *n, SwigType *ty, const_String_or_char_ptr name) { + Node *node = NewHash(); + Setattr(node, "type", ty); + Setattr(node, "name", name); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup("ffitype", node, "", 0); + Delete(node); + + if (tm) { + return NewString(tm); } else { SwigType *tr = SwigType_typedef_resolve_all(ty); char *type_reduced = Char(tr); @@ -171,14 +177,16 @@ static String *get_ffi_type(SwigType *ty, const_String_or_char_ptr name) { return 0; } -static String *get_lisp_type(SwigType *ty, const_String_or_char_ptr name) { - Hash *typemap = Swig_typemap_search("lisptype", ty, name, 0); - if (typemap) { - String *typespec = Getattr(typemap, "code"); - return NewString(typespec); - } else { - return NewString(""); - } +static String *get_lisp_type(Node *n, SwigType *ty, const_String_or_char_ptr name) { + Node *node = NewHash(); + Setattr(node, "type", ty); + Setattr(node, "name", name); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup("lisptype", node, "", 0); + Delete(node); + + return tm ? NewString(tm) : NewString(""); } void UFFI::main(int argc, char *argv[]) { @@ -284,8 +292,8 @@ int UFFI::functionWrapper(Node *n) { for (p = pl; p; p = nextSibling(p), argnum++) { String *argname = Getattr(p, "name"); SwigType *argtype = Getattr(p, "type"); - String *ffitype = get_ffi_type(argtype, argname); - String *lisptype = get_lisp_type(argtype, argname); + String *ffitype = get_ffi_type(n, argtype, argname); + String *lisptype = get_lisp_type(n, argtype, argname); int tempargname = 0; if (!argname) { @@ -311,7 +319,7 @@ int UFFI::functionWrapper(Node *n) { //" :strings-convert t\n" //" :call-direct %s\n" //" :optimize-for-space t" - ")\n", get_ffi_type(Getattr(n, "type"), "result") + ")\n", get_ffi_type(n, Getattr(n, "type"), "result") //,varargs ? "nil" : "t" ); @@ -365,7 +373,7 @@ int UFFI::classHandler(Node *n) { /* Printf(stdout, "Converting %s in %s\n", type, name); */ - lisp_type = get_ffi_type(type, Getattr(c, "sym:name")); + lisp_type = get_ffi_type(n, type, Getattr(c, "sym:name")); Printf(f_cl, " (#.(%s \"%s\" :type :slot) %s)\n", identifier_converter, Getattr(c, "sym:name"), lisp_type); diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index bcb1061c8..feaa82ff8 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -629,7 +629,7 @@ unterm: /* ----------------------------------------------------------------------------- * DOH *get_filename(DOH *str) * - * Read a filename from str. A filename can be enclose in quotes, angle brackets, + * Read a filename from str. A filename can be enclosed in quotes, angle brackets, * or bare. * ----------------------------------------------------------------------------- */ @@ -656,6 +656,7 @@ static String *get_filename(String *str, int *sysfile) { if (isspace(c)) Ungetc(c, str); } + Swig_filename_unescape(fn); Swig_filename_correct(fn); Seek(fn, 0, SEEK_SET); return fn; @@ -1597,9 +1598,9 @@ String *Preprocessor_parse(String *s) { s1 = cpp_include(fn, sysfile); if (s1) { if (include_all) - Printf(ns, "%%includefile \"%s\" [\n", Swig_last_file()); + Printf(ns, "%%includefile \"%s\" [\n", Swig_filename_escape(Swig_last_file())); else if (import_all) { - Printf(ns, "%%importfile \"%s\" [\n", Swig_last_file()); + Printf(ns, "%%importfile \"%s\" [\n", Swig_filename_escape(Swig_last_file())); push_imported(); } @@ -1652,7 +1653,7 @@ String *Preprocessor_parse(String *s) { state = 0; break; - /* Swig directives */ + /* SWIG directives */ case 100: /* %{,%} block */ if (c == '{') { @@ -1717,7 +1718,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) { @@ -1736,7 +1737,7 @@ String *Preprocessor_parse(String *s) { char *dirname; add_chunk(ns, chunk, allow); copy_location(s, chunk); - Printf(ns, "%sfile%s \"%s\" [\n", decl, opt, Swig_last_file()); + Printf(ns, "%sfile%s \"%s\" [\n", decl, opt, Swig_filename_escape(Swig_last_file())); if (Equal(decl, kpp_dimport)) { push_imported(); } diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index 25dfaea14..08cfdc008 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -212,7 +212,11 @@ int Swig_cargs(Wrapper *w, ParmList *p) { String *type = Getattr(p, "type"); /* default values only emitted if in compact default args mode */ String *pvalue = (compactdefargs) ? Getattr(p, "value") : 0; - SwigType *altty = SwigType_alttype(type, 0); + + /* When using compactdefaultargs, the code generated initialises a variable via a constructor call that accepts the + * default value as a parameter. The default constructor is not called and therefore SwigValueWrapper is not needed. */ + SwigType *altty = pvalue ? 0 : SwigType_alttype(type, 0); + int tycode = SwigType_type(type); if (tycode == T_REFERENCE) { if (pvalue) { @@ -851,7 +855,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"); /* @@ -1203,7 +1207,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"); @@ -1255,7 +1259,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; @@ -1286,13 +1290,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); @@ -1303,21 +1307,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); @@ -1373,7 +1379,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); @@ -1429,7 +1435,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 80eede4e3..fa82ad8d9 100644 --- a/Source/Swig/error.c +++ b/Source/Swig/error.c @@ -53,13 +53,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, ...) { @@ -122,7 +124,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, ...) { @@ -249,8 +251,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: @@ -258,10 +260,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; @@ -279,3 +283,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/include.c b/Source/Swig/include.c index 710a7ad71..baae44bb8 100644 --- a/Source/Swig/include.c +++ b/Source/Swig/include.c @@ -188,9 +188,8 @@ static FILE *Swig_open_file(const_String_or_char_ptr name, int sysfile, int use_ } if (f) { Delete(lastpath); - lastpath = Swig_filename_escape(filename); + lastpath = filename; } - Delete(filename); return f; } @@ -248,7 +247,7 @@ static String *Swig_include_any(const_String_or_char_ptr name, int sysfile) { str = Swig_read_file(f); fclose(f); Seek(str, 0, SEEK_SET); - file = Copy(lastpath); + file = Copy(Swig_last_file()); Setfile(str, file); Delete(file); Setline(str, 1); diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index 3a78fe7ab..19050fd51 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -92,8 +92,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) { @@ -111,9 +111,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; } @@ -162,12 +163,25 @@ void Swig_filename_correct(String *filename) { String *Swig_filename_escape(String *filename) { String *adjusted_filename = Copy(filename); #if defined(_WIN32) /* Note not on Cygwin else filename is displayed with double '/' */ - Replaceall(adjusted_filename, "\\\\", "\\"); /* remove double '\' in case any already present */ - Replaceall(adjusted_filename, "\\", "\\\\"); + Replaceall(adjusted_filename, "\\\\", "\\"); /* remove double '\' in case any already present */ + Replaceall(adjusted_filename, "\\", "\\\\"); #endif return adjusted_filename; } +/* ----------------------------------------------------------------------------- + * Swig_filename_unescape() + * + * Remove double backslash escaping in filename - for Windows + * ----------------------------------------------------------------------------- */ + +void Swig_filename_unescape(String *filename) { + (void)filename; +#if defined(_WIN32) + Replaceall(filename, "\\\\", "\\"); +#endif +} + /* ----------------------------------------------------------------------------- * Swig_string_escape() * @@ -896,7 +910,11 @@ String *Swig_scopename_suffix(const String *s) { /* ----------------------------------------------------------------------------- * Swig_scopename_check() * - * Checks to see if a name is qualified with a scope name + * Checks to see if a name is qualified with a scope name, examples: + * foo -> 0 + * ::foo -> 1 + * foo::bar -> 1 + * foo< ::bar > -> 0 * ----------------------------------------------------------------------------- */ int Swig_scopename_check(const String *s) { diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index 9af0354e2..08c4f6b5d 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -478,25 +478,12 @@ DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType Delete(cls); } /* A template-based class lookup, check name first */ - if (!rn && SwigType_istemplate(name)) { - String *t_name = SwigType_templateprefix(name); - if (!Equal(t_name, name)) { + if (!rn) { + String *t_name = SwigType_istemplate_templateprefix(name); + if (t_name) rn = Swig_name_object_get(namehash, prefix, t_name, decl); - } Delete(t_name); } - /* A template-based class lookup */ - /* - if (!rn && SwigType_istemplate(prefix)) { - String *t_prefix = SwigType_templateprefix(prefix); - if (Strcmp(t_prefix, prefix) != 0) { - String *t_name = SwigType_templateprefix(name); - rn = Swig_name_object_get(namehash, t_prefix, t_name, decl); - Delete(t_name); - } - Delete(t_prefix); - } - */ } /* A wildcard-based class lookup */ if (!rn) { @@ -667,10 +654,9 @@ void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *d if (name) { String *tname = NewStringEmpty(); /* add features for 'root' template */ - if (SwigType_istemplate(name)) { - String *dname = SwigType_templateprefix(name); + String *dname = SwigType_istemplate_templateprefix(name); + if (dname) { features_get(features, dname, decl, ncdecl, node); - Delete(dname); } /* Catch-all */ features_get(features, name, decl, ncdecl, node); @@ -688,16 +674,16 @@ void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *d /* A specific class lookup */ if (Len(prefix)) { /* A template-based class lookup */ - if (SwigType_istemplate(prefix)) { - String *tprefix = SwigType_templateprefix(prefix); + String *tprefix = SwigType_istemplate_templateprefix(prefix); + if (tprefix) { Clear(tname); Printf(tname, "%s::%s", tprefix, name); features_get(features, tname, decl, ncdecl, node); - Delete(tprefix); } Clear(tname); Printf(tname, "%s::%s", prefix, name); features_get(features, tname, decl, ncdecl, node); + Delete(tprefix); } } else { /* Lookup in the global namespace only */ @@ -706,6 +692,7 @@ void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *d features_get(features, tname, decl, ncdecl, node); } Delete(tname); + Delete(dname); } if (name && SwigType_istemplate(name)) { /* add features for complete template type */ @@ -1615,7 +1602,7 @@ String *Swig_name_decl(Node *n) { qname = NewString(""); if (qualifier && Len(qualifier) > 0) Printf(qname, "%s::", qualifier); - Printf(qname, "%s", name); + Printf(qname, "%s", SwigType_str(name, 0)); decl = NewStringf("%s(%s)%s", qname, ParmList_errorstr(Getattr(n, "parms")), SwigType_isconst(Getattr(n, "decl")) ? " const" : ""); diff --git a/Source/Swig/parms.c b/Source/Swig/parms.c index cb8176377..283a2f5c2 100644 --- a/Source/Swig/parms.c +++ b/Source/Swig/parms.c @@ -18,10 +18,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) { @@ -118,6 +133,14 @@ int ParmList_len(ParmList *p) { return i; } +/* --------------------------------------------------------------------- + * get_empty_type() + * ---------------------------------------------------------------------- */ + +static SwigType *get_empty_type() { + return NewStringEmpty(); +} + /* --------------------------------------------------------------------- * ParmList_str() * @@ -127,7 +150,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) { @@ -148,7 +172,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); @@ -162,6 +187,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() * @@ -171,7 +214,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 ed849bf4d..0eb82651a 100644 --- a/Source/Swig/scanner.c +++ b/Source/Swig/scanner.c @@ -20,7 +20,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 */ @@ -97,6 +98,7 @@ void Scanner_clear(Scanner * s) { Clear(s->scanobjs); Scanner_clear_brackets(s); Delete(s->error); + s->str = 0; s->error = 0; s->line = 1; s->nexttoken = -1; @@ -864,7 +866,7 @@ static int look(Scanner * s) { } break; - case 7: /* Identifier or unicode/custom delimiter string */ + case 7: /* Identifier or true/false or unicode/custom delimiter string */ if (c=='R') { /* Possibly CUSTOM DELIMITER string */ state = 72; break; @@ -875,7 +877,7 @@ static int look(Scanner * s) { } if ((c = nextchar(s)) == 0) { - return SWIG_TOKEN_ID; + state = 76; } else if (c=='\"') { /* Definitely u, U or L string */ retract(s, 1); @@ -895,20 +897,20 @@ static int look(Scanner * s) { case 70: /* Identifier */ if ((c = nextchar(s)) == 0) - return SWIG_TOKEN_ID; - if (isalnum(c) || (c == '_') || (c == '$')) { + state = 76; + else if (isalnum(c) || (c == '_') || (c == '$')) { state = 70; } else { retract(s, 1); - return SWIG_TOKEN_ID; + state = 76; } break; case 71: /* Possibly u8 string */ if ((c = nextchar(s)) == 0) { - return SWIG_TOKEN_ID; + state = 76; } - if (c=='\"') { + else if (c=='\"') { retract(s, 1); /* Definitely u8 string */ state = 1000; } @@ -926,9 +928,9 @@ static int look(Scanner * s) { case 73: case 74: if ((c = nextchar(s)) == 0) { - return SWIG_TOKEN_ID; + state = 76; } - if (c=='\"') { + else if (c=='\"') { retract(s, 1); /* Definitely custom delimiter u, U or L string */ str_delimiter = NewStringEmpty(); state = 1000; @@ -956,10 +958,20 @@ static int look(Scanner * s) { } else { retract(s,1); if (Len(s->text) == 1) return SWIG_TOKEN_DOLLAR; - return SWIG_TOKEN_ID; + state = 76; } break; + case 76: /* Identifier or true/false */ + if (cparse_cplusplus) { + if (Strcmp(s->text, "true") == 0) + return SWIG_TOKEN_BOOL; + else if (Strcmp(s->text, "false") == 0) + return SWIG_TOKEN_BOOL; + } + return SWIG_TOKEN_ID; + break; + case 8: /* A numerical digit */ if ((c = nextchar(s)) == 0) return SWIG_TOKEN_INT; diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index a8abf88fe..989d59259 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -543,7 +543,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; @@ -562,7 +568,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(); } @@ -1134,6 +1143,25 @@ void SwigType_typename_replace(SwigType *t, String *pat, String *rep) { Delete(elem); } +/* ----------------------------------------------------------------------------- + * SwigType_remove_global_scope_prefix() + * + * Removes the unary scope operator (::) prefix indicating global scope in all + * components of the type + * ----------------------------------------------------------------------------- */ + +SwigType *SwigType_remove_global_scope_prefix(const SwigType *t) { + SwigType *result; + const char *type = Char(t); + if (strncmp(type, "::", 2) == 0) + type += 2; + result = NewString(type); + Replaceall(result, ".::", "."); + Replaceall(result, "(::", "("); + Replaceall(result, "enum ::", "enum "); + return result; +} + /* ----------------------------------------------------------------------------- * SwigType_check_decl() * diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 07f27774d..8d66b6672 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -131,7 +131,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); @@ -167,6 +167,7 @@ extern "C" { extern String *SwigType_namestr(const SwigType *t); extern String *SwigType_templateprefix(const SwigType *t); extern String *SwigType_templatesuffix(const SwigType *t); + extern String *SwigType_istemplate_templateprefix(const SwigType *t); extern String *SwigType_templateargs(const SwigType *t); extern String *SwigType_prefix(const SwigType *t); extern int SwigType_array_ndim(SwigType *t); @@ -175,6 +176,7 @@ extern "C" { extern SwigType *SwigType_array_type(SwigType *t); extern String *SwigType_default(SwigType *t); extern void SwigType_typename_replace(SwigType *t, String *pat, String *rep); + extern SwigType *SwigType_remove_global_scope_prefix(const SwigType *t); extern SwigType *SwigType_alttype(SwigType *t, int ltmap); extern void SwigType_template_defargs(Parm *parms, Parm *targs, Symtab *tscope, Symtab *tsdecl); @@ -209,6 +211,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); @@ -216,6 +222,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); @@ -296,8 +303,9 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern void Swig_banner(File *f); extern void Swig_banner_target_lang(File *f, const_String_or_char_ptr commentchar); extern String *Swig_strip_c_comments(const String *s); - extern String *Swig_filename_escape(String *filename); extern void Swig_filename_correct(String *filename); + extern String *Swig_filename_escape(String *filename); + extern void Swig_filename_unescape(String *filename); extern String *Swig_string_escape(String *s); extern String *Swig_string_mangle(const String *s); extern void Swig_scopename_split(const String *s, String **prefix, String **last); @@ -311,13 +319,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, ...); @@ -328,6 +331,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); @@ -352,7 +356,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); @@ -372,22 +376,21 @@ extern int ParmList_is_compactdefargs(ParmList *p); /* --- Legacy Typemap API (somewhat simplified, ha!) --- */ extern void Swig_typemap_init(void); - extern void Swig_typemap_register(const_String_or_char_ptr op, ParmList *pattern, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs); - extern int Swig_typemap_copy(const_String_or_char_ptr op, ParmList *srcpattern, ParmList *pattern); - extern void Swig_typemap_clear(const_String_or_char_ptr op, ParmList *pattern); + extern void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *pattern, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs); + extern int Swig_typemap_copy(const_String_or_char_ptr tmap_method, ParmList *srcpattern, ParmList *pattern); + extern void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *pattern); extern int Swig_typemap_apply(ParmList *srcpat, ParmList *destpat); extern void Swig_typemap_clear_apply(ParmList *pattern); extern void Swig_typemap_debug(void); + extern void Swig_typemap_search_debug_set(void); + extern void Swig_typemap_used_debug_set(void); - extern Hash *Swig_typemap_search(const_String_or_char_ptr op, SwigType *type, const_String_or_char_ptr pname, SwigType **matchtype); - extern Hash *Swig_typemap_search_multi(const_String_or_char_ptr op, ParmList *parms, int *nmatch); - extern String *Swig_typemap_lookup(const_String_or_char_ptr op, Node *n, const_String_or_char_ptr lname, Wrapper *f); - extern String *Swig_typemap_lookup_out(const_String_or_char_ptr op, Node *n, const_String_or_char_ptr lname, Wrapper *f, String *actioncode); - extern void Swig_typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr op, Parm *p); + extern String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f); + extern String *Swig_typemap_lookup_out(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f, String *actioncode); extern void Swig_typemap_new_scope(void); extern Hash *Swig_typemap_pop_scope(void); - extern void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wrapper *f); + extern void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f); /* --- Code fragment support --- */ @@ -402,6 +405,7 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern void Wrapper_director_mode_set(int); extern void Wrapper_director_protected_mode_set(int); extern void Wrapper_all_protected_mode_set(int); + extern void Language_replace_special_variables(String *method, String *tm, Parm *parm); /* -- template init -- */ diff --git a/Source/Swig/swigparm.h b/Source/Swig/swigparm.h index 3e6269eae..060225f6b 100644 --- a/Source/Swig/swigparm.h +++ b/Source/Swig/swigparm.h @@ -15,7 +15,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 */ @@ -28,6 +29,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 faec4fe48..d52124c60 100644 --- a/Source/Swig/swigscan.h +++ b/Source/Swig/swigscan.h @@ -68,6 +68,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 50dde9159..73a136a4a 100644 --- a/Source/Swig/symbol.c +++ b/Source/Swig/symbol.c @@ -179,20 +179,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 *table = symtabs; + Iterator ki = First(table); + while (ki.key) { + String *k = ki.key; + Printf(stdout, "===================================================\n"); + Printf(stdout, "%s -\n", k); + { + Symtab *symtab = Getattr(Getattr(table, k), symboltabletype); + Iterator it = First(symtab); + while (it.key) { + String *symname = it.key; + Printf(stdout, " %s\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() @@ -200,7 +260,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(); @@ -244,7 +304,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"); } @@ -299,7 +359,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; @@ -350,7 +410,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); @@ -361,13 +421,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; } @@ -1002,6 +1072,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 { @@ -1074,6 +1146,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 { @@ -1138,6 +1212,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 { @@ -1186,6 +1262,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 { @@ -1257,7 +1335,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) { @@ -1732,7 +1811,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 @@ -1809,7 +1888,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 c80c61081..c76ac958e 100644 --- a/Source/Swig/tree.c +++ b/Source/Swig/tree.c @@ -34,7 +34,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)); @@ -272,7 +272,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 6595944a0..47e833bb6 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -21,7 +21,11 @@ char cvsroot_typemap_c[] = "$Id$"; #define SWIG_DEBUG #endif -static void replace_embedded_typemap(String *s); +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 @@ -35,14 +39,24 @@ static void replace_embedded_typemap(String *s); * different typemap methods. These are referenced by names such as * "tmap:in", "tmap:out", "tmap:argout", and so forth. * - * The object corresponding to a specific method has the following - * attributes: + * The object corresponding to a specific typemap method has the following attributes: * * "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 + * + * Example for a typemap method named "in": + * %typemap(in, warning="987:my warning", noblock=1) int &my_int (int tmp) "$1 = $input;" + * + * "type" - r.int + * "pname" - my_int + * "code" - $1 = $input; + * "source" - typemap(in) int &my_int + * "locals" - int tmp + * "kwargs" - warning="987:my typemap warning", foo=123 * * ----------------------------------------------------------------------------- */ @@ -52,47 +66,44 @@ static void replace_embedded_typemap(String *s); static Hash *typemaps[MAX_SCOPE]; static int tm_scope = 0; -static Hash *get_typemap(int tm_scope, SwigType *type) { +static Hash *get_typemap(int tm_scope, const SwigType *type) { Hash *tm = 0; SwigType *dtype = 0; + SwigType *hashtype; + if (SwigType_istemplate(type)) { String *ty = Swig_symbol_template_deftype(type, 0); dtype = Swig_symbol_type_qualify(ty, 0); - /* Printf(stderr,"gettm %s %s\n", type, dtype); */ type = dtype; Delete(ty); } - tm = Getattr(typemaps[tm_scope], type); + /* remove unary scope operator (::) prefix indicating global scope for looking up in the hashmap */ + hashtype = SwigType_remove_global_scope_prefix(type); + tm = Getattr(typemaps[tm_scope], hashtype); - if (dtype) { - if (!tm) { - String *t_name = SwigType_templateprefix(type); - if (!Equal(t_name, type)) { - tm = Getattr(typemaps[tm_scope], t_name); - } - Delete(t_name); - } - Delete(dtype); - } + Delete(dtype); + Delete(hashtype); return tm; } -static void set_typemap(int tm_scope, SwigType *type, Hash *tm) { - SwigType *dtype = 0; +static void set_typemap(int tm_scope, const SwigType *type, Hash *tm) { + SwigType *hashtype = 0; if (SwigType_istemplate(type)) { String *ty = Swig_symbol_template_deftype(type, 0); - dtype = Swig_symbol_type_qualify(ty, 0); - /* Printf(stderr,"settm %s %s\n", type, dtype); */ - type = dtype; + String *tyq = Swig_symbol_type_qualify(ty, 0); + hashtype = SwigType_remove_global_scope_prefix(tyq); + Delete(tyq); Delete(ty); } else { - dtype = Copy(type); - type = dtype; + hashtype = SwigType_remove_global_scope_prefix(type); } - Setattr(typemaps[tm_scope], type, tm); - Delete(dtype); + + /* note that the unary scope operator (::) prefix indicating global scope has been removed from the type */ + Setattr(typemaps[tm_scope], hashtype, tm); + + Delete(hashtype); } @@ -111,33 +122,34 @@ void Swig_typemap_init() { tm_scope = 0; } -static String *tmop_name(const_String_or_char_ptr op) { +static String *typemap_method_name(const_String_or_char_ptr tmap_method) { static Hash *names = 0; String *s; /* Due to "interesting" object-identity semantics of DOH, we have to make sure that we only intern strings without object identity into the hash table. - (Swig_typemap_attach_kwargs calls tmop_name several times with - the "same" String *op (i.e., same object identity) but differing + (typemap_attach_kwargs calls typemap_method_name several times with + the "same" String *tmap_method (i.e., same object identity) but differing string values.) Most other callers work around this by using char* rather than String *. -- mkoeppe, Jun 17, 2003 */ - const char *op_without_object_identity = Char(op); + const char *method_without_object_identity = Char(tmap_method); if (!names) names = NewHash(); - s = Getattr(names, op_without_object_identity); + s = Getattr(names, method_without_object_identity); if (s) return s; - s = NewStringf("tmap:%s", op); - Setattr(names, op_without_object_identity, s); + s = NewStringf("tmap:%s", tmap_method); + Setattr(names, method_without_object_identity, s); Delete(s); return s; } +#if 0 /* ----------------------------------------------------------------------------- * Swig_typemap_new_scope() * @@ -161,25 +173,26 @@ Hash *Swig_typemap_pop_scope() { } return 0; } +#endif /* ----------------------------------------------------------------------------- - * Swig_typemap_register() + * typemap_register() * - * Add a new multi-valued typemap + * Internal implementation for Swig_typemap_register() * ----------------------------------------------------------------------------- */ -void Swig_typemap_register(const_String_or_char_ptr op, 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; Parm *np; - String *tmop; + String *tm_method; SwigType *type; String *pname; if (!parms) return; - tmop = tmop_name(op); + tm_method = typemap_method_name(tmap_method); /* Register the first type in the parameter list */ @@ -204,18 +217,18 @@ void Swig_typemap_register(const_String_or_char_ptr op, ParmList *parms, const_S tm = tm1; } - /* Now see if this typemap op has been seen before */ - tm2 = Getattr(tm, tmop); + /* Now see if this typemap method has been seen before */ + tm2 = Getattr(tm, tm_method); if (!tm2) { tm2 = NewHash(); - Setattr(tm, tmop, tm2); + Setattr(tm, tm_method, tm2); Delete(tm2); } - /* For a multi-valued typemap, the typemap code and information + /* 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 @@ -225,35 +238,35 @@ void Swig_typemap_register(const_String_or_char_ptr op, ParmList *parms, const_S 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:", op, 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", op, 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); } @@ -262,19 +275,32 @@ void Swig_typemap_register(const_String_or_char_ptr op, ParmList *parms, const_S 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); +} + /* ----------------------------------------------------------------------------- - * Swig_typemap_get() + * typemap_get() * * Retrieve typemap information from current scope. * ----------------------------------------------------------------------------- */ -static Hash *Swig_typemap_get(SwigType *type, const_String_or_char_ptr name, int scope) { +static Hash *typemap_get(SwigType *type, const_String_or_char_ptr name, int scope) { Hash *tm, *tm1; /* See if this type has been seen before */ if ((scope < 0) || (scope > tm_scope)) @@ -296,46 +322,53 @@ static Hash *Swig_typemap_get(SwigType *type, const_String_or_char_ptr name, int * Copy a typemap * ----------------------------------------------------------------------------- */ -int Swig_typemap_copy(const_String_or_char_ptr op, ParmList *srcparms, ParmList *parms) { +int Swig_typemap_copy(const_String_or_char_ptr tmap_method, ParmList *srcparms, ParmList *parms) { Hash *tm = 0; - String *tmop; + String *tm_method; Parm *p; String *pname; SwigType *ptype; int ts = tm_scope; - String *tmops, *newop; + String *tm_methods, *multi_tmap_method; if (ParmList_len(parms) != ParmList_len(srcparms)) return -1; - tmop = tmop_name(op); + tm_method = typemap_method_name(tmap_method); while (ts >= 0) { p = srcparms; - tmops = NewString(tmop); + tm_methods = NewString(tm_method); while (p) { ptype = Getattr(p, "type"); pname = Getattr(p, "name"); /* Lookup the type */ - tm = Swig_typemap_get(ptype, pname, ts); + tm = typemap_get(ptype, pname, ts); if (!tm) break; - tm = Getattr(tm, tmops); + tm = Getattr(tm, tm_methods); if (!tm) break; /* Got a match. Look for next typemap */ - newop = NewStringf("%s-%s+%s:", tmops, ptype, pname); - Delete(tmops); - tmops = newop; + multi_tmap_method = NewStringf("%s-%s+%s:", tm_methods, ptype, pname); + Delete(tm_methods); + tm_methods = multi_tmap_method; p = nextSibling(p); } - Delete(tmops); + Delete(tm_methods); if (!p && tm) { - /* Got some kind of match */ - Swig_typemap_register(op, 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--; @@ -348,38 +381,38 @@ int Swig_typemap_copy(const_String_or_char_ptr op, ParmList *srcparms, ParmList /* ----------------------------------------------------------------------------- * Swig_typemap_clear() * - * Delete a multi-valued typemap + * Delete a multi-argument typemap * ----------------------------------------------------------------------------- */ -void Swig_typemap_clear(const_String_or_char_ptr op, ParmList *parms) { +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(op); + multi_tmap_method = NewString(tmap_method); p = parms; while (p) { type = Getattr(p, "type"); name = Getattr(p, "name"); - tm = Swig_typemap_get(type, name, tm_scope); + tm = typemap_get(type, name, tm_scope); if (!tm) 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, tmop_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); } /* ----------------------------------------------------------------------------- @@ -389,8 +422,7 @@ void Swig_typemap_clear(const_String_or_char_ptr op, ParmList *parms) { * it works. * ----------------------------------------------------------------------------- */ -static -int count_args(String *s) { +static int count_args(String *s) { /* Count up number of arguments */ int na = 0; char *c = Char(s); @@ -460,7 +492,7 @@ int Swig_typemap_apply(ParmList *src, ParmList *dest) { while (ts >= 0) { /* See if there is a matching typemap in this scope */ - sm = Swig_typemap_get(type, name, ts); + sm = typemap_get(type, name, ts); /* if there is not matching, look for a typemap in the original typedef, if any, like in: @@ -472,7 +504,7 @@ int Swig_typemap_apply(ParmList *src, ParmList *dest) { if (!sm) { SwigType *ntype = SwigType_typedef_resolve(type); if (ntype && (Cmp(ntype, type) != 0)) { - sm = Swig_typemap_get(ntype, name, ts); + sm = typemap_get(ntype, name, ts); } Delete(ntype); } @@ -502,9 +534,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); @@ -587,78 +627,128 @@ 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"); +} + /* ----------------------------------------------------------------------------- - * Swig_typemap_search() + * typemap_search_helper() * - * Search for a typemap match. Tries to find the most specific typemap - * that includes a 'code' attribute. + * Helper function for typemap_search to see if there is a type match in the typemap + * tm. A match is sought in this order: + * %typemap(tm_method) ctype cqualifiedname + * %typemap(tm_method) ctype cname + * %typemap(tm_method) ctype * ----------------------------------------------------------------------------- */ -Hash *Swig_typemap_search(const_String_or_char_ptr op, SwigType *type, const_String_or_char_ptr name, SwigType **matchtype) { - Hash *result = 0, *tm, *tm1, *tma; +static Hash *typemap_search_helper(int debug_display, Hash *tm, const String *tm_method, SwigType *ctype, const String *cqualifiedname, const String *cname, Hash **backup) { + Hash *result = 0; + Hash *tm1; + if (debug_display && cqualifiedname) + Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, cqualifiedname)); + if (tm && cqualifiedname) { + tm1 = Getattr(tm, cqualifiedname); + if (tm1) { + result = Getattr(tm1, tm_method); /* See if there is a type - qualified name match */ + if (result && Getattr(result, "code")) + goto ret_result; + if (result) + *backup = result; + } + } + if (debug_display && cname) + Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, cname)); + if (tm && cname) { + tm1 = Getattr(tm, cname); + if (tm1) { + result = Getattr(tm1, tm_method); /* See if there is a type - name match */ + if (result && Getattr(result, "code")) + goto ret_result; + if (result) + *backup = result; + } + } + if (debug_display) + Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, 0)); + if (tm) { + result = Getattr(tm, tm_method); /* See if there is simply a type match */ + if (result && Getattr(result, "code")) + goto ret_result; + if (result) + *backup = result; + } +ret_result: + return result; +} + +/* ----------------------------------------------------------------------------- + * typemap_search() + * + * Search for a typemap match. This is where the typemap pattern matching rules + * are implemented... tries to find the most specific typemap that includes a + * 'code' attribute. + * ----------------------------------------------------------------------------- */ + +static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type, const_String_or_char_ptr name, const_String_or_char_ptr qualifiedname, SwigType **matchtype, Node *node) { + Hash *result = 0; + Hash *tm; Hash *backup = 0; - SwigType *noarrays = 0; SwigType *primitive = 0; SwigType *ctype = 0; int ts; int isarray; const String *cname = 0; + const String *cqualifiedname = 0; SwigType *unstripped = 0; - String *tmop = tmop_name(op); + 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 (tm1) { - result = Getattr(tm1, tmop); /* See if there is a type-name match */ - if (result && Getattr(result, "code")) - goto ret_result; + result = typemap_search_helper(debug_display, tm, tm_method, ctype, cqualifiedname, cname, &backup); + if (result) + goto ret_result; + + { + /* Look for the type reduced to just the template prefix */ + SwigType *template_prefix = SwigType_istemplate_templateprefix(ctype); + if (template_prefix) { + tm = get_typemap(ts, template_prefix); + result = typemap_search_helper(debug_display, tm, tm_method, template_prefix, cqualifiedname, cname, &backup); + Delete(template_prefix); if (result) - backup = result; + goto ret_result; } } - if (tm) { - result = Getattr(tm, tmop); /* See if there is simply a type match */ - if (result && Getattr(result, "code")) - goto ret_result; - if (result) - backup = result; - } + + /* look for [ANY] arrays */ isarray = SwigType_isarray(ctype); if (isarray) { /* If working with arrays, strip away all of the dimensions and replace with "ANY". See if that generates a match */ - if (!noarrays) { - noarrays = strip_arrays(ctype); - } - tma = get_typemap(ts, noarrays); - if (tma && cname) { - tm1 = Getattr(tma, cname); - if (tm1) { - result = Getattr(tm1, tmop); /* type-name match */ - if (result && Getattr(result, "code")) - goto ret_result; - if (result) - backup = result; - } - } - if (tma) { - result = Getattr(tma, tmop); /* type match */ - if (result && Getattr(result, "code")) - goto ret_result; - if (result) - backup = result; - } + SwigType *noarrays = strip_arrays(ctype); + tm = get_typemap(ts, noarrays); + result = typemap_search_helper(debug_display, tm, tm_method, noarrays, cqualifiedname, cname, &backup); Delete(noarrays); - noarrays = 0; + if (result) + goto ret_result; } /* No match so far. If the type is unstripped, we'll strip its @@ -687,24 +777,15 @@ Hash *Swig_typemap_search(const_String_or_char_ptr op, SwigType *type, const_Str } } - /* 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 (tm1) { - result = Getattr(tm1, tmop); /* See if there is a type-name match */ - if (result) - goto ret_result; - } - } - if (tm) { /* See if there is simply a type match */ - result = Getattr(tm, tmop); - if (result) - goto ret_result; - } + result = typemap_search_helper(debug_display, tm, tm_method, primitive, cqualifiedname, cname, &backup); + if (result) + goto ret_result; + { SwigType *nprim = SwigType_default(primitive); Delete(primitive); @@ -720,15 +801,11 @@ Hash *Swig_typemap_search(const_String_or_char_ptr op, SwigType *type, const_Str result = backup; ret_result: - if (noarrays) - Delete(noarrays); - if (primitive) - Delete(primitive); + Delete(primitive); if ((unstripped) && (unstripped != type)) Delete(unstripped); - if (matchtype) { + if (matchtype) *matchtype = Copy(ctype); - } if (type != ctype) Delete(ctype); return result; @@ -736,17 +813,18 @@ ret_result: /* ----------------------------------------------------------------------------- - * Swig_typemap_search_multi() + * typemap_search_multi() * - * Search for a multi-valued typemap. + * Search for a multi-argument typemap. * ----------------------------------------------------------------------------- */ -Hash *Swig_typemap_search_multi(const_String_or_char_ptr op, ParmList *parms, int *nmatch) { +static Hash *typemap_search_multi(const_String_or_char_ptr tmap_method, ParmList *parms, int *nmatch) { 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; @@ -756,23 +834,38 @@ Hash *Swig_typemap_search_multi(const_String_or_char_ptr op, ParmList *parms, in name = Getattr(parms, "name"); /* Try to find a match on the first type */ - tm = Swig_typemap_search(op, 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:", op, type, name); - tm1 = Swig_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; } @@ -784,8 +877,7 @@ Hash *Swig_typemap_search_multi(const_String_or_char_ptr op, ParmList *parms, in * type and pname are the type and parameter name. * ----------------------------------------------------------------------------- */ -static -void replace_local_types(ParmList *p, const String *name, const String *rep) { +static void replace_local_types(ParmList *p, const String *name, const String *rep) { SwigType *t; while (p) { t = Getattr(p, "type"); @@ -794,8 +886,7 @@ void replace_local_types(ParmList *p, const String *name, const String *rep) { } } -static -int check_locals(ParmList *p, const char *s) { +static int check_locals(ParmList *p, const char *s) { while (p) { char *c = GetChar(p, "type"); if (strstr(c, s)) @@ -805,14 +896,13 @@ int check_locals(ParmList *p, const char *s) { return 0; } -static -int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index) { +static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index) { char var[512]; char *varname; SwigType *ftype; int bare_substitution_count = 0; - Replaceall(s, "$typemap", "$TYPEMAP"); + Replaceall(s, "$typemap", "$TYPEMAP"); /* workaround for $type substitution below */ ftype = SwigType_typedef_resolve_all(type); @@ -1163,24 +1253,51 @@ 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() * * Attach one or more typemaps to a node and optionally generate the typemap contents * into the wrapper. - * op - typemap name, eg "out", "newfree" - * node - the node to attach the typemaps to - * lname - name of variable to substitute $1, $2 etc for - * f - wrapper code to generate into if non null - * actioncode - code to generate into f before the out typemap code, unless + * + * Looks for a typemap matching the given type and name and attaches the typemap code + * and any typemap attributes to the provided node. + * + * The node should contain the "type" and "name" attributes for the typemap match on. + * input. The typemap code and typemap attribute values are attached onto the node + * prefixed with "tmap:". For example with tmap_method="in", the typemap code can be retrieved + * with a call to Getattr(node, "tmap:in") (this is also the string returned) and the + * "noblock" attribute can be retrieved with a call to Getattr(node, "tmap:in:noblock"). + * + * tmap_method - typemap method, eg "in", "out", "newfree" + * node - the node to attach the typemap and typemap attributes to + * lname - name of variable to substitute $1, $2 etc for + * f - wrapper code to generate into if non null + * actioncode - code to generate into f before the out typemap code, unless * the optimal attribute is set in the out typemap in which case * $1 in the out typemap will be replaced by the code in actioncode. * ----------------------------------------------------------------------------- */ -static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) { +static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) { SwigType *type; SwigType *mtype = 0; String *pname; + String *qpname = 0; Hash *tm = 0; String *s = 0; String *sdef = 0; @@ -1190,14 +1307,13 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node, String *symname; String *cname = 0; String *clname = 0; - char *cop = Char(op); + 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' */ - if (node && Cmp(op, "newfree") == 0) { + /* 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); } @@ -1207,30 +1323,33 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node, 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 = Swig_typemap_search(op, 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 = Swig_typemap_search(op, 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; @@ -1248,15 +1367,15 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node, kw = Getattr(tm, "kwargs"); while (kw) { String *value = Copy(Getattr(kw, "value")); - String *type = Getattr(kw, "type"); + String *kwtype = Getattr(kw, "type"); char *ckwname = Char(Getattr(kw, "name")); - if (type) { - String *mangle = Swig_string_mangle(type); + if (kwtype) { + String *mangle = Swig_string_mangle(kwtype); Append(value, mangle); Delete(mangle); } - sprintf(temp, "%s:%s", cop, ckwname); - Setattr(node, tmop_name(temp), value); + 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; Delete(value); @@ -1290,7 +1409,8 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node, } } 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 { @@ -1324,13 +1444,21 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node, } 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); } - replace_embedded_typemap(s); + + { + ParmList *parm_sublist = NewParmWithoutFileLineInfo(type, pname); + Setattr(parm_sublist, "lname", lname); + replace_embedded_typemap(s, parm_sublist, f, tm); + Delete(parm_sublist); + } Replace(s, "$name", pname, DOH_REPLACE_ANY); @@ -1339,35 +1467,28 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node, Replace(s, "$symname", symname, DOH_REPLACE_ANY); } - Setattr(node, tmop_name(op), s); + Setattr(node, typemap_method_name(tmap_method), s); if (locals) { - sprintf(temp, "%s:locals", cop); - Setattr(node, tmop_name(temp), locals); + sprintf(temp, "%s:locals", cmethod); + Setattr(node, typemap_method_name(temp), locals); Delete(locals); } if (Checkattr(tm, "type", "SWIGTYPE")) { - sprintf(temp, "%s:SWIGTYPE", cop); - Setattr(node, tmop_name(temp), "1"); + 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, tmop_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 *f; - sprintf(temp, "%s:fragment", cop); - f = Getattr(node, tmop_name(temp)); - if (f) { - String *fname = Copy(f); + String *fragment; + sprintf(temp, "%s:fragment", cmethod); + fragment = Getattr(node, typemap_method_name(temp)); + if (fragment) { + String *fname = Copy(fragment); Setfile(fname, Getfile(node)); Setline(fname, Getline(node)); Swig_fragment_emit(fname); @@ -1388,19 +1509,18 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node, return s; } -String *Swig_typemap_lookup_out(const_String_or_char_ptr op, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) { +String *Swig_typemap_lookup_out(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) { assert(actioncode); - assert(Cmp(op, "out") == 0); - return Swig_typemap_lookup_impl(op, node, lname, f, actioncode); + assert(Cmp(tmap_method, "out") == 0); + return Swig_typemap_lookup_impl(tmap_method, node, lname, f, actioncode); } -String *Swig_typemap_lookup(const_String_or_char_ptr op, Node *node, const_String_or_char_ptr lname, Wrapper *f) { - return Swig_typemap_lookup_impl(op, node, lname, f, 0); +String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f) { + return Swig_typemap_lookup_impl(tmap_method, node, lname, f, 0); } - /* ----------------------------------------------------------------------------- - * Swig_typemap_attach_kwargs() + * typemap_attach_kwargs() * * If this hash (tm) contains a linked list of parameters under its "kwargs" * attribute, add keys for each of those named keyword arguments to this @@ -1410,7 +1530,7 @@ String *Swig_typemap_lookup(const_String_or_char_ptr op, Node *node, const_Strin * A new attribute called "tmap:in:foo" with value "xyz" is attached to p. * ----------------------------------------------------------------------------- */ -void Swig_typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr op, Parm *p) { +static void typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr tmap_method, Parm *p) { String *temp = NewStringEmpty(); Parm *kw = Getattr(tm, "kwargs"); while (kw) { @@ -1424,36 +1544,20 @@ void Swig_typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr op, Parm *p) value = v; } Clear(temp); - Printf(temp, "%s:%s", op, Getattr(kw, "name")); - Setattr(p, tmop_name(temp), value); + Printf(temp, "%s:%s", tmap_method, Getattr(kw, "name")); + Setattr(p, typemap_method_name(temp), value); Delete(value); kw = nextSibling(kw); } Clear(temp); - Printf(temp, "%s:match_type", op); - Setattr(p, tmop_name(temp), Getattr(tm, "type")); + Printf(temp, "%s:match_type", tmap_method); + Setattr(p, typemap_method_name(temp), Getattr(tm, "type")); Delete(temp); } -/* ----------------------------------------------------------------------------- - * Swig_typemap_warn() - * - * If any warning message is attached to this parameter's "tmap:op:warning" - * attribute, print that warning message. - * ----------------------------------------------------------------------------- */ - -static void Swig_typemap_warn(const_String_or_char_ptr op, Parm *p) { - String *temp = NewStringf("%s:warning", op); - String *w = Getattr(p, tmop_name(temp)); - Delete(temp); - if (w) { - Swig_warning(0, Getfile(p), Getline(p), "%s\n", w); - } -} - -static void Swig_typemap_emit_code_fragments(const_String_or_char_ptr op, Parm *p) { - String *temp = NewStringf("%s:fragment", op); - String *f = Getattr(p, tmop_name(temp)); +static void typemap_emit_code_fragments(const_String_or_char_ptr tmap_method, Parm *p) { + String *temp = NewStringf("%s:fragment", tmap_method); + String *f = Getattr(p, typemap_method_name(temp)); if (f) { String *fname = Copy(f); Setfile(fname, Getfile(p)); @@ -1464,14 +1568,7 @@ static void Swig_typemap_emit_code_fragments(const_String_or_char_ptr op, Parm * Delete(temp); } -/* ----------------------------------------------------------------------------- - * Swig_typemap_attach_parms() - * - * Given a parameter list, this function attaches all of the typemaps for a - * given typemap type - * ----------------------------------------------------------------------------- */ - -String *Swig_typemap_get_option(Hash *tm, const_String_or_char_ptr name) { +static String *typemap_get_option(Hash *tm, const_String_or_char_ptr name) { Parm *kw = Getattr(tm, "kwargs"); while (kw) { String *kname = Getattr(kw, "name"); @@ -1483,7 +1580,23 @@ String *Swig_typemap_get_option(Hash *tm, const_String_or_char_ptr name) { return 0; } -void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wrapper *f) { +/* ----------------------------------------------------------------------------- + * Swig_typemap_attach_parms() + * + * Given a parameter list, this function attaches all of the typemaps and typemap + * attributes to the parameter for each type in the parameter list. + * + * This function basically provides the typemap code and typemap attribute values as + * attributes on each parameter prefixed with "tmap:". For example with tmap_method="in", the typemap + * code can be retrieved for the first parameter with a call to Getattr(parm, "tmap:in") + * and the "numinputs" attribute can be retrieved with a call to Getattr(parm, "tmap:in:numinputs"). + * + * tmap_method - typemap method, eg "in", "out", "newfree" + * parms - parameter list to attach each typemap and all typemap attributes + * f - wrapper code to generate into if non null + * ----------------------------------------------------------------------------- */ + +void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f) { Parm *p, *firstp; Hash *tm; int nmatch = 0; @@ -1492,21 +1605,21 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra ParmList *locals; int argnum = 0; char temp[256]; - char *cop = Char(op); + char *cmethod = Char(tmap_method); String *kwmatch = 0; p = parms; #ifdef SWIG_DEBUG - Printf(stdout, "Swig_typemap_attach_parms: %s\n", op); + Printf(stdout, "Swig_typemap_attach_parms: %s\n", tmap_method); #endif while (p) { argnum++; nmatch = 0; #ifdef SWIG_DEBUG - Printf(stdout, "parms: %s %s %s\n", op, Getattr(p, "name"), Getattr(p, "type")); + Printf(stdout, "parms: %s %s %s\n", tmap_method, Getattr(p, "name"), Getattr(p, "type")); #endif - tm = Swig_typemap_search_multi(op, p, &nmatch); + tm = typemap_search_multi(tmap_method, p, &nmatch); #ifdef SWIG_DEBUG if (tm) Printf(stdout, "found: %s\n", tm); @@ -1525,7 +1638,7 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra here, the freearg typemap requires the "in" typemap to match, or the 'var$argnum' variable will not exist. */ - kwmatch = Swig_typemap_get_option(tm, "match"); + kwmatch = typemap_get_option(tm, "match"); if (kwmatch) { String *tmname = NewStringf("tmap:%s", kwmatch); String *tmin = Getattr(p, tmname); @@ -1551,7 +1664,7 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra continue; } else { int nnmatch; - Hash *tmapin = Swig_typemap_search_multi(kwmatch, p, &nnmatch); + Hash *tmapin = typemap_search_multi(kwmatch, p, &nnmatch); String *tmname = Getattr(tm, "pname"); String *tnname = Getattr(tmapin, "pname"); if (!(tmname && tnname && Equal(tmname, tnname)) && !(!tmname && !tnname)) { @@ -1611,8 +1724,8 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra } if (Checkattr(tm, "type", "SWIGTYPE")) { - sprintf(temp, "%s:SWIGTYPE", cop); - Setattr(p, tmop_name(temp), "1"); + sprintf(temp, "%s:SWIGTYPE", cmethod); + Setattr(p, typemap_method_name(temp), "1"); } p = nextSibling(p); } @@ -1621,7 +1734,7 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra typemap_locals(s, locals, f, argnum); } - replace_embedded_typemap(s); + replace_embedded_typemap(s, firstp, f, tm); /* Replace the argument number */ sprintf(temp, "%d", argnum); @@ -1629,34 +1742,34 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra /* Attach attributes to object */ #ifdef SWIG_DEBUG - Printf(stdout, "attach: %s %s %s\n", Getattr(firstp, "name"), tmop_name(op), s); + Printf(stdout, "attach: %s %s %s\n", Getattr(firstp, "name"), typemap_method_name(tmap_method), s); #endif - Setattr(firstp, tmop_name(op), s); /* Code object */ + Setattr(firstp, typemap_method_name(tmap_method), s); /* Code object */ if (locals) { - sprintf(temp, "%s:locals", cop); - Setattr(firstp, tmop_name(temp), locals); + sprintf(temp, "%s:locals", cmethod); + Setattr(firstp, typemap_method_name(temp), locals); Delete(locals); } /* Attach a link to the next parameter. Needed for multimaps */ - sprintf(temp, "%s:next", cop); - Setattr(firstp, tmop_name(temp), p); + sprintf(temp, "%s:next", cmethod); + Setattr(firstp, typemap_method_name(temp), p); /* Attach kwargs */ - Swig_typemap_attach_kwargs(tm, op, firstp); + typemap_attach_kwargs(tm, tmap_method, firstp); /* Print warnings, if any */ - Swig_typemap_warn(op, firstp); + typemap_warn(tmap_method, firstp); /* Look for code fragments */ - Swig_typemap_emit_code_fragments(op, firstp); + typemap_emit_code_fragments(tmap_method, firstp); /* increase argnum to consider numinputs */ argnum += nmatch - 1; Delete(s); #ifdef SWIG_DEBUG - Printf(stdout, "res: %s %s %s\n", Getattr(firstp, "name"), tmop_name(op), Getattr(firstp, tmop_name(op))); + Printf(stdout, "res: %s %s %s\n", Getattr(firstp, "name"), typemap_method_name(tmap_method), Getattr(firstp, typemap_method_name(tmap_method))); #endif } @@ -1666,30 +1779,17 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra } -/* ----------------------------------------------------------------------------- - * split_embedded() - * - * This function replaces the special variable $typemap(....) with typemap - * code. The general form of $typemap is as follows: - * - * $TYPEMAP(method, $var1=value, $var2=value, $var3=value,...) - * - * For example: - * - * $TYPEMAP(in, $1=int x, $input=y, ...) - * - * Note: this was added as an experiment and could be removed - * ----------------------------------------------------------------------------- */ - /* Splits the arguments of an embedded typemap */ -static List *split_embedded(String *s) { +static List *split_embedded_typemap(String *s) { List *args = 0; char *c, *start; int level = 0; + int angle_level = 0; int leading = 1; - args = NewList(); + args = NewList(); c = strchr(Char(s), '('); + assert(c); c++; start = c; @@ -1706,7 +1806,7 @@ static List *split_embedded(String *s) { c++; } } - if ((level == 0) && ((*c == ',') || (*c == ')'))) { + if ((level == 0) && angle_level == 0 && ((*c == ',') || (*c == ')'))) { String *tmp = NewStringWithSize(start, c - start); Append(args, tmp); Delete(tmp); @@ -1721,6 +1821,10 @@ static List *split_embedded(String *s) { level++; if (*c == ')') level--; + if (*c == '<') + angle_level++; + if (*c == '>') + angle_level--; if (isspace((int) *c) && leading) start++; if (!isspace((int) *c)) @@ -1730,41 +1834,36 @@ static List *split_embedded(String *s) { return args; } -static void split_var(String *s, String **name, String **value) { - char *eq; - char *c; +/* ----------------------------------------------------------------------------- + * replace_embedded_typemap() + * + * This function replaces the special variable macro $typemap(...) with typemap + * code. The general form of $typemap is as follows: + * + * $typemap(method, typelist, var1=value, var2=value, ...) + * + * where varx parameters are optional and undocumented; they were used in an earlier version of $typemap. + * A search is made using the typemap matching rules of form: + * + * %typemap(method) typelist {...} + * + * and if found will substitute in the typemap contents, making appropriate variable replacements. + * + * For example: + * $typemap(in, int) # simple usage matching %typemap(in) int { ... } + * $typemap(in, int b) # simple usage matching %typemap(in) int b { ... } or above %typemap + * $typemap(in, (Foo a, int b)) # multi-argument typemap matching %typemap(in) (Foo a, int b) {...} + * ----------------------------------------------------------------------------- */ - eq = strchr(Char(s), '='); - if (!eq) { - *name = 0; - *value = 0; - return; - } - c = Char(s); - *name = NewStringWithSize(c, eq - c); - - /* Look for $n variables */ - if (isdigit((int) *(c))) { - /* Parse the value as a type */ - String *v; - Parm *p; - v = NewString(eq + 1); - p = Swig_cparse_parm(v); - Delete(v); - *value = p; - } else { - *value = NewString(eq + 1); - } -} - -static void replace_embedded_typemap(String *s) { +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("))) { + while ((start = strstr(Char(s), "$TYPEMAP("))) { /* note $typemap capitalisation to $TYPEMAP hack */ - /* Gather the argument */ + /* Gather the parameters */ char *end = 0, *c; int level = 0; - String *tmp; + String *dollar_typemap; + int syntax_error = 1; c = start; while (*c) { if (*c == '(') @@ -1779,108 +1878,135 @@ static void replace_embedded_typemap(String *s) { c++; } if (end) { - tmp = NewStringWithSize(start, (end - start)); + dollar_typemap = NewStringWithSize(start, (end - start)); + syntax_error = 0; } else { - tmp = 0; + dollar_typemap = NewStringWithSize(start, (c - start)); } - /* Got a substitution. Split it apart into pieces */ - if (tmp) { + if (!syntax_error) { List *l; + String *tmap_method; Hash *vars; - String *method; - int i, ilen; + syntax_error = 1; - l = split_embedded(tmp); - vars = NewHash(); - ilen = Len(l); - for (i = 1; i < ilen; i++) { - String *n, *v; - split_var(Getitem(l, i), &n, &v); - if (n && v) { - Insert(n, 0, "$"); - Setattr(vars, n, v); - } - Delete(n); - Delete(v); - } + /* Split apart each parameter in $typemap(...) */ + l = split_embedded_typemap(dollar_typemap); - method = Getitem(l, 0); - /* Generate the parameter list for matching typemaps */ + if (Len(l) >= 2) { + ParmList *to_match_parms; + tmap_method = Getitem(l, 0); - { - Parm *p = 0; - Parm *first = 0; - char temp[32]; - int n = 1; - while (1) { - Hash *v; - sprintf(temp, "$%d", n); - v = Getattr(vars, temp); - if (v) { - if (p) { - set_nextSibling(p, v); - set_previousSibling(v, p); + /* the second parameter might contain multiple sub-parameters for multi-argument + * typemap matching, so split these parameters apart */ + to_match_parms = Swig_cparse_parms(Getitem(l, 1), file_line_node); + if (to_match_parms) { + Parm *p = to_match_parms; + Parm *sub_p = parm_sublist; + String *empty_string = NewStringEmpty(); + String *lname = empty_string; + while (p) { + if (sub_p) { + lname = Getattr(sub_p, "lname"); + sub_p = nextSibling(sub_p); } - p = v; - Setattr(p, "lname", Getattr(p, "name")); - if (Getattr(p, "value")) { - Setattr(p, "name", Getattr(p, "value")); - } - if (!first) - first = p; - DohIncref(p); - Delattr(vars, temp); - } else { - break; + Setattr(p, "lname", lname); + p = nextSibling(p); } - n++; + Delete(empty_string); } + + /* process optional extra parameters - the variable replacements (undocumented) */ + vars = NewHash(); + { + int i, ilen; + ilen = Len(l); + for (i = 2; i < ilen; i++) { + String *parm = Getitem(l, i); + char *eq = strchr(Char(parm), '='); + char *c = Char(parm); + if (eq && (eq - c > 0)) { + String *name = NewStringWithSize(c, eq - c); + String *value = NewString(eq + 1); + Insert(name, 0, "$"); + Setattr(vars, name, value); + } else { + to_match_parms = 0; /* error - variable replacement parameters must be of form varname=value */ + } + } + } + /* Perform a typemap search */ - if (first) { + if (to_match_parms) { + static int already_substituting = 0; + String *tm; + String *attr; + int match = 0; #ifdef SWIG_DEBUG Printf(stdout, "Swig_typemap_attach_parms: embedded\n"); #endif - Swig_typemap_attach_parms(method, first, 0); - { - String *tm; - int match = 0; - char attr[64]; - sprintf(attr, "tmap:%s", Char(method)); + if (!already_substituting) { + already_substituting = 1; + Swig_typemap_attach_parms(tmap_method, to_match_parms, f); + already_substituting = 0; /* Look for the typemap code */ - tm = Getattr(first, attr); + attr = NewStringf("tmap:%s", tmap_method); + tm = Getattr(to_match_parms, attr); if (tm) { - sprintf(attr, "tmap:%s:next", Char(method)); - if (!Getattr(first, attr)) { - /* Should be no more matches. Hack??? */ - /* Replace all of the remaining variables */ + Printf(attr, "%s", ":next"); + /* fail if multi-argument lookup requested in $typemap(...) and the lookup failed */ + if (!Getattr(to_match_parms, attr)) { + /* Replace parameter variables */ Iterator ki; for (ki = First(vars); ki.key; ki = Next(ki)) { Replace(tm, ki.key, ki.item, DOH_REPLACE_ANY); } - /* Do the replacement */ - Replace(s, tmp, tm, DOH_REPLACE_ANY); + /* offer the target language module the chance to make special variable substitutions */ + Language_replace_special_variables(tmap_method, tm, to_match_parms); + /* finish up - do the substitution */ + Replace(s, dollar_typemap, tm, DOH_REPLACE_ANY); Delete(tm); match = 1; } } + if (!match) { - Swig_error(Getfile(s), Getline(s), "No typemap found for %s\n", tmp); + String *dtypemap = NewString(dollar_typemap); + Replaceall(dtypemap, "$TYPEMAP", "$typemap"); + Swig_error(Getfile(s), Getline(s), "No typemap found for %s\n", dtypemap); + Delete(dtypemap); } + Delete(attr); + } else { + /* simple recursive call check, but prevents using an embedded typemap that contains another embedded typemap */ + String *dtypemap = NewString(dollar_typemap); + Replaceall(dtypemap, "$TYPEMAP", "$typemap"); + Swig_error(Getfile(s), Getline(s), "Recursive $typemap calls not supported - %s\n", dtypemap); + Delete(dtypemap); } + syntax_error = 0; } + Delete(vars); } - Replace(s, tmp, "", DOH_REPLACE_ANY); - Delete(vars); - Delete(tmp); Delete(l); } + + if (syntax_error) { + String *dtypemap = NewString(dollar_typemap); + Replaceall(dtypemap, "$TYPEMAP", "$typemap"); + Swig_error(Getfile(s), Getline(s), "Syntax error in: %s\n", dtypemap); + Delete(dtypemap); + } + Replace(s, dollar_typemap, "", DOH_REPLACE_ANY); + Delete(dollar_typemap); } } /* ----------------------------------------------------------------------------- * Swig_typemap_debug() + * + * Display all typemaps * ----------------------------------------------------------------------------- */ void Swig_typemap_debug() { @@ -1895,3 +2021,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 a72a102aa..23bc7b924 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -824,13 +824,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) { @@ -893,11 +895,12 @@ SwigType *SwigType_add_template(SwigType *t, ParmList *parms) { * SwigType_templateprefix() * * Returns the prefix before the first template definition. + * Returns the type unmodified if not a template. * For example: * - * Foo<(p.int)>::bar - * - * returns "Foo" + * Foo<(p.int)>::bar => Foo + * r.q(const).Foo<(p.int)>::bar => r.q(const).Foo + * Foo => Foo * ----------------------------------------------------------------------------- */ String *SwigType_templateprefix(const SwigType *t) { @@ -938,6 +941,25 @@ String *SwigType_templatesuffix(const SwigType *t) { return NewStringEmpty(); } +/* ----------------------------------------------------------------------------- + * SwigType_istemplate_templateprefix() + * + * Combines SwigType_istemplate and SwigType_templateprefix efficiently into one function. + * Returns the prefix before the first template definition. + * Returns NULL if not a template. + * For example: + * + * Foo<(p.int)>::bar => Foo + * r.q(const).Foo<(p.int)>::bar => r.q(const).Foo + * Foo => NULL + * ----------------------------------------------------------------------------- */ + +String *SwigType_istemplate_templateprefix(const SwigType *t) { + const char *s = Char(t); + const char *c = strstr(s, "<("); + return c ? NewStringWithSize(s, c - s) : 0; +} + /* ----------------------------------------------------------------------------- * SwigType_templateargs() * diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index f6baa5a83..3e9429f75 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -844,7 +844,8 @@ SwigType *SwigType_typedef_resolve_all(SwigType *t) { * * Given a type declaration, this function tries to fully qualify it according to * typedef scope rules. - * Inconsistency to be fixed: ::Foo returns ::Foo, whereas ::Foo * returns Foo * + * If the unary scope operator (::) is used as a prefix to the type to denote global + * scope, it is left in place. * ----------------------------------------------------------------------------- */ SwigType *SwigType_typedef_qualified(SwigType *t) { @@ -852,10 +853,6 @@ SwigType *SwigType_typedef_qualified(SwigType *t) { String *result; int i, len; - if (strncmp(Char(t), "::", 2) == 0) { - return Copy(t); - } - if (!typedef_qualified_cache) typedef_qualified_cache = NewHash(); result = Getattr(typedef_qualified_cache, t); @@ -1003,10 +1000,6 @@ SwigType *SwigType_typedef_qualified(SwigType *t) { Delete(qprefix); Delete(parms); } - if (strncmp(Char(e), "::", 2) == 0) { - Delitem(e, 0); - Delitem(e, 0); - } Append(result, e); Delete(ty); } else if (SwigType_isfunction(e)) { @@ -1124,11 +1117,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); + } } } } @@ -1170,9 +1165,9 @@ int SwigType_isclass(SwigType *t) { isclass = 1; } /* Hmmm. Not a class. If a template, it might be uninstantiated */ - if (!isclass && SwigType_istemplate(qtys)) { - String *tp = SwigType_templateprefix(qtys); - if (Strcmp(tp, t) != 0) { + if (!isclass) { + String *tp = SwigType_istemplate_templateprefix(qtys); + if (tp && Strcmp(tp, t) != 0) { isclass = SwigType_isclass(tp); } Delete(tp); 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 cf0418220..7e8b280cc 100644 --- a/configure.in +++ b/configure.in @@ -316,10 +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= # Add switch to enable C++0x support AC_SUBST(PLATCXXFLAGS)