From c0de963191b4f88de9d293e3eac9ebbffe41014a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 2 Aug 2015 22:21:14 +0100 Subject: Test case warning suppression for visual c++ fix --- Examples/test-suite/array_typedef_memberin.i | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/array_typedef_memberin.i b/Examples/test-suite/array_typedef_memberin.i index 7301057e9..ad2855eed 100644 --- a/Examples/test-suite/array_typedef_memberin.i +++ b/Examples/test-suite/array_typedef_memberin.i @@ -1,14 +1,14 @@ %module array_typedef_memberin -#if defined(_MSC_VER) - #pragma warning(disable: 4351) // new behavior: elements of array 'xyz' will be default initialized -#endif - #if defined(SWIGSCILAB) %rename(ExDetail) ExampleDetail; #endif %inline %{ +#if defined(_MSC_VER) + #pragma warning(disable: 4351) // new behavior: elements of array 'xyz' will be default initialized +#endif + typedef short Eight[8]; typedef const short ConstEight[8]; namespace ArrayExample -- cgit v1.2.1 From 9d509ba92b039dc225a9df8feb5fc6d58e46b1ad Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 2 Aug 2015 22:51:59 +0100 Subject: Add 3.0.7 release summary and release date --- ANNOUNCE | 12 +++++++++++- CHANGES.current | 4 ++-- Doc/Manual/Sections.html | 2 +- README | 2 +- RELEASENOTES | 8 ++++++++ 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index f7d7eb8a9..6f1411668 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,4 +1,4 @@ -*** ANNOUNCE: SWIG 3.0.7 (in progress) *** +*** ANNOUNCE: SWIG 3.0.7 (3 Aug 2015) *** http://www.swig.org @@ -18,6 +18,16 @@ include generation of scripting language extension modules, rapid prototyping, testing, and user interface development for large C/C++ systems. +Release Notes +============= +Detailed release notes are available with the release and are also +published on the SWIG web site at http://swig.org/release.html. + +SWIG-3.0.7 summary: +- Add support for Octave-4.0.0. +- Remove potential Android security exploit in generated Java classes. +- Minor new features and bug fixes. + Availability ============ The release is available for download on Sourceforge at diff --git a/CHANGES.current b/CHANGES.current index 48ccc2036..f6922c5f2 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -2,8 +2,8 @@ Below are the changes for the current release. See the CHANGES file for changes in older releases. See the RELEASENOTES file for a summary of changes in each release. -Version 3.0.7 (in progress) -=========================== +Version 3.0.7 (3 Aug 2015) +========================== 2015-08-02: wsfulton [Java] Fix potential security exploit in generated Java classes. diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html index 4bf40c969..f0027d136 100644 --- a/Doc/Manual/Sections.html +++ b/Doc/Manual/Sections.html @@ -6,7 +6,7 @@

SWIG-3.0 Documentation

-Last update : SWIG-3.0.7 (in progress) +Last update : SWIG-3.0.7 (3 Aug 2015)

Sections

diff --git a/README b/README index a02c56ea9..27d33df32 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ SWIG (Simplified Wrapper and Interface Generator) -Version: 3.0.7 (in progress) +Version: 3.0.7 (3 Aug 2015) Tagline: SWIG is a compiler that integrates C and C++ with languages including Perl, Python, Tcl, Ruby, PHP, Java, C#, D, Go, Lua, diff --git a/RELEASENOTES b/RELEASENOTES index bb1d82bb9..895caa2dd 100644 --- a/RELEASENOTES +++ b/RELEASENOTES @@ -4,6 +4,14 @@ and CHANGES files. Release Notes ============= +Detailed release notes are available with the release and are also +published on the SWIG web site at http://swig.org/release.html. + +SWIG-3.0.7 summary: +- Add support for Octave-4.0.0. +- Remove potential Android security exploit in generated Java classes. +- Minor new features and bug fixes. + SWIG-3.0.6 summary: - Stability and regression fixes. - Fixed parsing of C++ corner cases. -- cgit v1.2.1 From 9babc2663449aa156233521475cff3849d6a7ac7 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 3 Aug 2015 08:12:38 +0100 Subject: Update Scilab test-suite output wording --- Examples/test-suite/scilab/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/scilab/Makefile.in b/Examples/test-suite/scilab/Makefile.in index 4a9a4f007..9ddd8f1aa 100644 --- a/Examples/test-suite/scilab/Makefile.in +++ b/Examples/test-suite/scilab/Makefile.in @@ -62,7 +62,7 @@ setup = \ mkdir $(TEST_DIR); \ fi; \ if [ -f $(SRC_RUNME_SCRIPT) ]; then \ - echo "$(ACTION)ing testcase $* (with run test) under $(LANGUAGE)" ; \ + echo "$(ACTION)ing $(LANGUAGE) testcase $* (with run test)" ; \ if [ ! -f $(TEST_DIR) ]; then \ cp $(SRC_RUNME_SCRIPT) $(TEST_DIR); \ fi; \ @@ -73,7 +73,7 @@ setup = \ cp $(srcdir)/swigtest.quit $(TEST_DIR); \ fi; \ else \ - echo "$(ACTION)ing testcase $* under $(LANGUAGE)" ; \ + echo "$(ACTION)ing $(LANGUAGE) testcase $*" ; \ fi; \ # Runs the testcase. A testcase is only run if -- cgit v1.2.1 From 5d363276f5688d2bf1b4ad304a191c216f5c8483 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 3 Aug 2015 22:33:52 +0100 Subject: Bump version to 3.0.8 --- ANNOUNCE | 13 ++---- CHANGES | 117 ++++++++++++++++++++++++++++++++++++++++++++++ CHANGES.current | 119 +---------------------------------------------- Doc/Manual/Sections.html | 2 +- README | 2 +- configure.ac | 2 +- 6 files changed, 126 insertions(+), 129 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index 6f1411668..d9b932e2c 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,8 +1,8 @@ -*** ANNOUNCE: SWIG 3.0.7 (3 Aug 2015) *** +*** ANNOUNCE: SWIG 3.0.8 (in progress) *** http://www.swig.org -We're pleased to announce SWIG-3.0.7, the latest SWIG release. +We're pleased to announce SWIG-3.0.8, the latest SWIG release. What is SWIG? ============= @@ -23,20 +23,15 @@ Release Notes Detailed release notes are available with the release and are also published on the SWIG web site at http://swig.org/release.html. -SWIG-3.0.7 summary: -- Add support for Octave-4.0.0. -- Remove potential Android security exploit in generated Java classes. -- Minor new features and bug fixes. - Availability ============ The release is available for download on Sourceforge at - http://prdownloads.sourceforge.net/swig/swig-3.0.7.tar.gz + http://prdownloads.sourceforge.net/swig/swig-3.0.8.tar.gz A Windows version is also available at - http://prdownloads.sourceforge.net/swig/swigwin-3.0.7.zip + http://prdownloads.sourceforge.net/swig/swigwin-3.0.8.zip Please report problems with this release to the swig-devel mailing list, details at http://www.swig.org/mail.html. diff --git a/CHANGES b/CHANGES index 691fa5544..29b36352c 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,123 @@ SWIG (Simplified Wrapper and Interface Generator) See the CHANGES.current file for changes in the current version. See the RELEASENOTES file for a summary of changes in each release. +Version 3.0.7 (3 Aug 2015) +========================== + +2015-08-02: wsfulton + [Java] Fix potential security exploit in generated Java classes. + The swigCPtr and swigCMemOwn member variables in the generated Java + classes are now declared 'transient' by default. Further details of the exploit + in Android is being published in an academic paper as part of USENIX WOOT '15: + https://www.usenix.org/conference/woot15/workshop-program/presentation/peles. + + In the unlikely event that you are relying on these members being serializable, + then you will need to override the default javabody and javabody_derived typemaps + to generate the old generated code. The relevant typemaps are in the Lib directory + in the java.swg, boost_shared_ptr.i and boost_intrusive_ptr.i files. Copy the + relevant default typemaps into your interface file and remove the 'transient' keyword. + + *** POTENTIAL INCOMPATIBILITY *** + +2015-08-01: vadz + Make configure --without-alllang option more useful: it can now be overridden by the following + --with-xxx options, allowing to easily enable just one or two languages. + +2015-07-30: wsfulton + Fix #440 - Initialise all newly created arrays when using %array_functions and %array_class + in the carrays.i library - bug is only relevant when using C++. + +2015-07-29: wsfulton + [Python] Improve indentation warning and error messages for code in the following directives: + + %pythonprepend + %pythonappend + %pythoncode + %pythonbegin + %feature("shadow") + + Old error example: + Error: Line indented less than expected (line 3 of pythoncode) + + New error example: + Error: Line indented less than expected (line 3 of %pythoncode or %insert("python") block) + as no line should be indented less than the indentation in line 1 + + Old warning example: + Warning 740: Whitespace prefix doesn't match (line 2 of %pythoncode or %insert("python") block) + + New warning example: + Warning 740: Whitespace indentation is inconsistent compared to earlier lines (line 3 of + %pythoncode or %insert("python") block) + + +2015-07-28: wsfulton + [Python] Fix #475. Improve docstring indentation handling. + + SWIG-3.0.5 and earlier sometimes truncated text provided in the docstring feature. + This occurred when the indentation (whitespace) in the docstring was less in the + second or later lines when compared to the first line. + SWIG-3.0.6 gave a 'Line indented less than expected' error instead of truncating + the docstring text. + Now the indentation for the 'docstring' feature is smarter and is appropriately + adjusted so that no truncation occurs. + +2015-07-22: wsfulton + Support for special variable expansion in typemap attributes. Example usage expansion + in the 'out' attribute (C# specific): + + %typemap(ctype, out="$*1_ltype") unsigned int& "$*1_ltype" + + is equivalent to the following as $*1_ltype expands to 'unsigned int': + + %typemap(ctype, out="unsigned int") unsigned int& "unsigned int" + + Special variables can be used within special variable macros too. Example usage expansion: + + %typemap(cstype) unsigned int "uint" + %typemap(cstype, out="$typemap(cstype, $*1_ltype)") unsigned int& "$typemap(cstype, $*1_ltype)" + + Special variables are expanded first and hence the above is equivalent to: + + %typemap(cstype, out="$typemap(cstype, unsigned int)") unsigned int& "$typemap(cstype, unsigned int)" + + which then expands to: + + %typemap(cstype, out="uint") unsigned int& "uint" + +2015-07-22: lindleyf + Apply patch #439 - support for $typemap() (aka embedded typemaps or special variable + macros) in typemap attributes. A simple example where $typemap() is expanded in the + 'out' attribute (C# specific): + + %typemap(cstype) unsigned int "uint" + %typemap(cstype, out="$typemap(cstype, unsigned int)") unsigned int& "$typemap(cstype, unsigned int)" + + is equivalent to: + + %typemap(cstype, out="uint") unsigned int& "uint" + +2015-07-18: m7thon + [Python] Docstrings provided via %feature("docstring") are now quoted and added to + the tp_doc slot when using python builtin classes (-builtin). When no docstring is + provided, the tp_doc slot is set to the fully qualified C/C++ class name. + Github issues #445 and #461. + +2015-07-17: kwwette + [octave] Support Octave version 4.0.0 (thanks to patches from Orion Poplawski). + +2015-07-07: wsfulton + SWIG no longer generates a wrapper for a class' constructor if that class has + any base class with a private destructor. This is because your compiler should + not allow a class to be instantiated if a base has a private destructor. Some + compilers do, so if you need the old behaviour, use the "notabstract" feature, eg: + + %feature("notabstract") Derived; + class Base { + ~Base() {} + }; + struct Derived : Base {}; + Version 3.0.6 (5 Jul 2015) ========================== diff --git a/CHANGES.current b/CHANGES.current index f6922c5f2..c0694f657 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -2,120 +2,5 @@ Below are the changes for the current release. See the CHANGES file for changes in older releases. See the RELEASENOTES file for a summary of changes in each release. -Version 3.0.7 (3 Aug 2015) -========================== - -2015-08-02: wsfulton - [Java] Fix potential security exploit in generated Java classes. - The swigCPtr and swigCMemOwn member variables in the generated Java - classes are now declared 'transient' by default. Further details of the exploit - in Android is being published in an academic paper as part of USENIX WOOT '15: - https://www.usenix.org/conference/woot15/workshop-program/presentation/peles. - - In the unlikely event that you are relying on these members being serializable, - then you will need to override the default javabody and javabody_derived typemaps - to generate the old generated code. The relevant typemaps are in the Lib directory - in the java.swg, boost_shared_ptr.i and boost_intrusive_ptr.i files. Copy the - relevant default typemaps into your interface file and remove the 'transient' keyword. - - *** POTENTIAL INCOMPATIBILITY *** - -2015-08-01: vadz - Make configure --without-alllang option more useful: it can now be overridden by the following - --with-xxx options, allowing to easily enable just one or two languages. - -2015-07-30: wsfulton - Fix #440 - Initialise all newly created arrays when using %array_functions and %array_class - in the carrays.i library - bug is only relevant when using C++. - -2015-07-29: wsfulton - [Python] Improve indentation warning and error messages for code in the following directives: - - %pythonprepend - %pythonappend - %pythoncode - %pythonbegin - %feature("shadow") - - Old error example: - Error: Line indented less than expected (line 3 of pythoncode) - - New error example: - Error: Line indented less than expected (line 3 of %pythoncode or %insert("python") block) - as no line should be indented less than the indentation in line 1 - - Old warning example: - Warning 740: Whitespace prefix doesn't match (line 2 of %pythoncode or %insert("python") block) - - New warning example: - Warning 740: Whitespace indentation is inconsistent compared to earlier lines (line 3 of - %pythoncode or %insert("python") block) - - -2015-07-28: wsfulton - [Python] Fix #475. Improve docstring indentation handling. - - SWIG-3.0.5 and earlier sometimes truncated text provided in the docstring feature. - This occurred when the indentation (whitespace) in the docstring was less in the - second or later lines when compared to the first line. - SWIG-3.0.6 gave a 'Line indented less than expected' error instead of truncating - the docstring text. - Now the indentation for the 'docstring' feature is smarter and is appropriately - adjusted so that no truncation occurs. - -2015-07-22: wsfulton - Support for special variable expansion in typemap attributes. Example usage expansion - in the 'out' attribute (C# specific): - - %typemap(ctype, out="$*1_ltype") unsigned int& "$*1_ltype" - - is equivalent to the following as $*1_ltype expands to 'unsigned int': - - %typemap(ctype, out="unsigned int") unsigned int& "unsigned int" - - Special variables can be used within special variable macros too. Example usage expansion: - - %typemap(cstype) unsigned int "uint" - %typemap(cstype, out="$typemap(cstype, $*1_ltype)") unsigned int& "$typemap(cstype, $*1_ltype)" - - Special variables are expanded first and hence the above is equivalent to: - - %typemap(cstype, out="$typemap(cstype, unsigned int)") unsigned int& "$typemap(cstype, unsigned int)" - - which then expands to: - - %typemap(cstype, out="uint") unsigned int& "uint" - -2015-07-22: lindleyf - Apply patch #439 - support for $typemap() (aka embedded typemaps or special variable - macros) in typemap attributes. A simple example where $typemap() is expanded in the - 'out' attribute (C# specific): - - %typemap(cstype) unsigned int "uint" - %typemap(cstype, out="$typemap(cstype, unsigned int)") unsigned int& "$typemap(cstype, unsigned int)" - - is equivalent to: - - %typemap(cstype, out="uint") unsigned int& "uint" - -2015-07-18: m7thon - [Python] Docstrings provided via %feature("docstring") are now quoted and added to - the tp_doc slot when using python builtin classes (-builtin). When no docstring is - provided, the tp_doc slot is set to the fully qualified C/C++ class name. - Github issues #445 and #461. - -2015-07-17: kwwette - [octave] Support Octave version 4.0.0 (thanks to patches from Orion Poplawski). - -2015-07-07: wsfulton - SWIG no longer generates a wrapper for a class' constructor if that class has - any base class with a private destructor. This is because your compiler should - not allow a class to be instantiated if a base has a private destructor. Some - compilers do, so if you need the old behaviour, use the "notabstract" feature, eg: - - %feature("notabstract") Derived; - class Base { - ~Base() {} - }; - struct Derived : Base {}; - +Version 3.0.8 (in progress) +=========================== diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html index f0027d136..b917c4cd8 100644 --- a/Doc/Manual/Sections.html +++ b/Doc/Manual/Sections.html @@ -6,7 +6,7 @@

SWIG-3.0 Documentation

-Last update : SWIG-3.0.7 (3 Aug 2015) +Last update : SWIG-3.0.8 (in progress)

Sections

diff --git a/README b/README index 27d33df32..e3f15e4da 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ SWIG (Simplified Wrapper and Interface Generator) -Version: 3.0.7 (3 Aug 2015) +Version: 3.0.8 (in progress) Tagline: SWIG is a compiler that integrates C and C++ with languages including Perl, Python, Tcl, Ruby, PHP, Java, C#, D, Go, Lua, diff --git a/configure.ac b/configure.ac index 6d4505875..74235204e 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. dnl The macros which aren't shipped with the autotools are stored in the dnl Tools/config directory in .m4 files. -AC_INIT([swig],[3.0.7],[http://www.swig.org]) +AC_INIT([swig],[3.0.8],[http://www.swig.org]) dnl NB: When this requirement is increased to 2.60 or later, AC_PROG_SED dnl definition below can be removed -- cgit v1.2.1 From a17c9727bd11c8dee4e67f4cb53b8e907436f874 Mon Sep 17 00:00:00 2001 From: Michael Schaller Date: Wed, 24 Jun 2015 14:48:17 +0200 Subject: Fleshed out Go's documentation about the director feature and added a director example. Fixes issues #418. --- Doc/Manual/Go.html | 553 +++++++++++++++++++++++++++++++++++++-- Examples/go/check.list | 1 + Examples/go/director/Makefile | 17 ++ Examples/go/director/director.go | 70 +++++ Examples/go/director/director.h | 41 +++ Examples/go/director/example.i | 11 + Examples/go/director/index.html | 28 ++ Examples/go/director/runme.go | 39 +++ 8 files changed, 738 insertions(+), 22 deletions(-) create mode 100644 Examples/go/director/Makefile create mode 100644 Examples/go/director/director.go create mode 100644 Examples/go/director/director.h create mode 100644 Examples/go/director/example.i create mode 100644 Examples/go/director/index.html create mode 100644 Examples/go/director/runme.go diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html index 20e923d19..0be378f6a 100644 --- a/Doc/Manual/Go.html +++ b/Doc/Manual/Go.html @@ -29,6 +29,17 @@
  • Go Templates
  • Go Director Classes +
  • Default Go primitive type mappings
  • Output arguments
  • Adding additional go code @@ -574,49 +585,547 @@ In order to use C++ templates in Go, you must tell SWIG to create wrappers for a particular template instantation. To do this, use the %template directive. +

    23.4.7 Go Director Classes

    -SWIG's director feature permits a Go type to act as the subclass of a -C++ class with virtual methods. This is complicated by the fact that -C++ and Go define inheritance differently. In Go, structs can inherit -methods via anonymous field embedding. However, when a method is -called for an embedded struct, if that method calls any other methods, -they are called for the embedded struct, not for the original type. -Therefore, SWIG must use Go interfaces to represent C++ inheritance. +SWIG's director feature permits a Go type to act as the subclass of a C++ class. +This is complicated by the fact that C++ and Go define inheritance differently. +SWIG normally represents the C++ class inheritance automatically in Go via +interfaces but with a Go type representing a subclass of a C++ class quite some +manual work is necessary. +

    + +

    +This subchapter gives a step by step guide how to properly sublass a C++ class +with a Go type. In general it is strongly recommended to follow this guide +completely to avoid common pitfalls with directors in Go. +

    + + +

    23.4.7.1 Example C++ code

    + +

    +The step by step guide is based on two example C++ classes. FooBarAbs is an +abstract C++ class and the FooBarCpp class inherits from it. This guide +explains how to implement a FooBarGo class similar to the FooBarCpp class. +

    + +

    +FooBarAbs abstract C++ class: +

    + +
    +
    +class FooBarAbs
    +{
    +public:
    +	FooBarAbs() {};
    +	virtual ~FooBarAbs() {};
    +
    +	std::string FooBar() {
    +		return this->Foo() + ", " + this->Bar();
    +	};
    +
    +protected:
    +	virtual std::string Foo() {
    +		return "Foo";
    +	};
    +
    +	virtual std::string Bar() = 0;
    +};
    +
    +
    + +

    +FooBarCpp C++ class: +

    + +
    +
    +class FooBarCpp : public FooBarAbs
    +{
    +protected:
    +	virtual std::string Foo() {
    +		return "C++ " + FooBarAbs::Foo();
    +	}
    +
    +	virtual std::string Bar() {
    +		return "C++ Bar";
    +	}
    +};
    +
    +
    + +

    +Returned string by the FooBarCpp::FooBar method is: +

    + +
    +
    +C++ Foo, C++ Bar
    +
    +
    + + +

    +The complete example, including the FooBarGoo class implementation, can +be found in the end of the guide. +

    + + +

    23.4.7.2 Enable director feature

    + + +

    +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
    +
    +
    + +

    +Second, you must use the %feature("director") directive to tell SWIG which +classes should get directors. In the example the FooBarAbs class needs the +director feature enabled so that the FooBarGo class can inherit from it, like +this: +

    + +
    +
    +%feature("director") FooBarAbs;
    +
    +
    + +

    +For a more detailed documentation of the director feature and how to enable or +disable it for specific classes and virtual methods see SWIG's Java +documentation on directors. +

    + + +

    23.4.7.3 Constructor and destructor

    + + +

    +SWIG creates an additional set of constructor and destructor functions once the +director feature has been enabled for a C++ class. NewDirectorClassName + allows to override virtual methods on the new object instance and +DeleteDirectorClassName needs to be used to free a director object instance +created with NewDirectorClassName. More on overriding virtual methods +follows later in this guide under +overriding virtual methods. +

    + +

    +The default constructor and destructor functions NewClassName and +DeleteClassName can still be used as before so that existing code +doesn't break just because the director feature has been enabled for a C++ +class. The behavior is undefined if the default and director constructor and +destructor functions get mixed and so great care needs to be taken that only one +of the constructor and destructor function pairs is used for any object +instance. Both constructor functions, the default and the director one, return +the same interface type. This makes it potentially hard to know which +destructor function, the default or the director one, needs to be called to +delete an object instance. +

    + +

    +In theory the DirectorInterface method could be used to +determine if an object instance was created via NewDirectorClassName: +

    + +
    +
    +if o.DirectorInterface() != nil {
    +	DeleteDirectorClassName(o)
    +} else {
    +	DeleteClassName(o)
    +}
    +
    +
    + +

    +In practice it is strongly recommended to embed a director object +instance in a Go struct so that a director object instance will be represented +as a distinct Go type that subclasses a C++ class. For this Go type custom +constructor and destructor functions take care of the director constructor and +destructor function calls and the resulting Go class will appear to the user as +any other SWIG wrapped C++ class. More on properly subclassing a C++ class +follows later in this guide under subclass via +embedding. +

    + + +

    23.4.7.4 Override virtual methods

    + + +

    +In order to override virtual methods on a C++ class with Go methods the +NewDirectorClassName constructor functions receives a +DirectorInterface argument. The methods in the +DirectorInterface are a subset of the public and protected virtual methods +of the C++ class. If the DirectorInterface contains a method with a +matching signature to a virtual method of the C++ class then the virtual C++ +method will be overwritten with the Go method. As Go doesn't support protected +methods all overriden protected virtual C++ methods will be public in Go. +

    + +

    +As an example see part of the FooBarGo class: +

    + +
    +
    +type overwritenMethodsOnFooBarAbs struct {
    +	fb FooBarAbs
    +}
    +
    +func (om *overwritenMethodsOnFooBarAbs) Foo() string {
    +	...
    +}
    +
    +func (om *overwritenMethodsOnFooBarAbs) Bar() string {
    +	...
    +}
    +
    +func NewFooBarGo() FooBarGo {
    +	om := &overwritenMethodsOnFooBarAbs{}
    +	fb := NewDirectorFooBarAbs(om)
    +	om.fb = fb
    +	...
    +}
    +
    +
    + +

    +The complete example, including the FooBarGoo class implementation, can +be found in the end of the guide. In +this part of the example the virtual methods FooBarAbs::Foo and +FooBarAbs::Bar have been overwritten with Go methods similarly to how +the FooBarAbs virtual methods are overwritten by the FooBarCpp +class. +

    + +

    +The DirectorInterface in the example is implemented by the +overwritenMethodsOnFooBarAbs Go struct type. A pointer to a +overwritenMethodsOnFooBarAbs struct instance will be given to the +NewDirectorFooBarAbs constructor function. The constructor return +value implements the FooBarAbs interface. +overwritenMethodsOnFooBarAbs could in theory be any Go type but in +practice a struct is used as it typically contains at least a value of the +C++ class interface so that the overwritten methods can use the rest of the +C++ class. If the FooBarGo class would receive additional constructor +arguments then these would also typically be stored in the +overwritenMethodsOnFooBarAbs struct so that they can be used by the +Go methods. +

    + + +

    23.4.7.5 Call base methods

    + + +

    +Often a virtual method will be overwritten to extend the original behavior of +the method in the base class. This is also the case for the FooBarCpp::Foo + method of the example code:

    +
    +
    +virtual std::string Foo() {
    +	return "C++ " + FooBarAbs::Foo();
    +}
    +
    +
    + +

    +To use base methods the DirectorClassNameMethodName wrapper functions +are automatically generated by SWIG for public and protected virtual methods. +The FooBarGo.Foo implementation in the example looks like this: +

    + +
    +
    +func (om *overwritenMethodsOnFooBarAbs) Foo() string {
    +	return "Go " + DirectorFooBarAbsFoo(om.fb)
    +}
    +
    +
    + +

    +The complete example, including the FooBarGoo class implementation, can +be found in the end of the guide. +

    + + +

    23.4.7.6 Subclass via embedding

    + + +

    +As previously mentioned in this guide the +default and director constructor functions return the same interface type. To +properly subclass a C++ class with a Go type the director object instance +returned by the NewDirectorClassName constructor function should be +embedded into a Go struct so that it represents a distinct but compatible type +in Go's type system. This Go struct should be private and the constructor and +destructor functions should instead work with a public interface type so that +the Go class that subclasses a C++ class can be used as a compatible drop in. +

    + +

    +The subclassing part of the FooBarGo class for an example looks like +this: +

    + +
    +
    +type FooBarGo interface {
    +	FooBarAbs
    +	deleteFooBarAbs()
    +	IsFooBarGo()
    +}
    +
    +type fooBarGo struct {
    +	FooBarAbs
    +}
    +
    +func (fbgs *fooBarGo) deleteFooBarAbs() {
    +	DeleteDirectorFooBarAbs(fbgs.FooBarAbs)
    +}
    +
    +func (fbgs *fooBarGo) IsFooBarGo() {}
    +
    +func NewFooBarGo() FooBarGo {
    +	om := &overwritenMethodsOnFooBarAbs{}
    +	fb := NewDirectorFooBarAbs(om)
    +	om.fb = fb
    +
    +	return &fooBarGo{FooBarAbs: fb}
    +}
    +
    +func DeleteFooBarGo(fbg FooBarGo) {
    +	fbg.deleteFooBarAbs()
    +}
    +
    +
    + +

    -In order to use the director feature in Go, you must define a type in -your Go code. You must then add methods for the type. Define a -method in Go for each C++ virtual function that you want to override. -You must then create a value of your new type, and pass a pointer to -it to the function NewDirectorClassName, -where ClassName is the name of the C++ class. That will -return a value of type ClassName. +The complete example, including the FooBarGoo class implementation, can +be found in the end of the guide. In +this part of the example the private fooBarGo struct embeds +FooBarAbs which lets the fooBarGo Go type "inherit" all the +methods of the FooBarAbs C++ class by means of embedding. The public +FooBarGo interface type includes the FooBarAbs interface and +hence FooBarGo can be used as a drop in replacement for +FooBarAbs while the reverse isn't possible and would raise a compile +time error. Furthemore the constructor and destructor functions +NewFooBarGo and DeleteFooBarGo take care of all the director +specifics and to the user the class appears as any other SWIG wrapped C++ +class.

    + +

    23.4.7.7 Memory management with runtime.SetFinalizer

    + +

    -For example: +In general all guidelines for C++ class memory +management apply as well to director classes. One often overlooked +limitation with runtime.SetFinalizer is that a finalizer doesn't run +in case of a cycle and director classes typically have a cycle. The cycle +in the FooBarGo class is here:

    -type GoClass struct { }
    -func (p *GoClass) VirtualFunction() { }
    -func MakeClass() ClassName {
    -	return NewDirectorClassName(&GoClass{})
    +type overwritenMethodsOnFooBarAbs struct {
    +	fb FooBarAbs
    +}
    +
    +func NewFooBarGo() FooBarGo {
    +	om := &overwritenMethodsOnFooBarAbs{}
    +	fb := NewDirectorFooBarAbs(om) // fb.v = om
    +	om.fb = fb // Backlink causes cycle as fb.v = om!
    +	...
     }
     

    -Any call in C++ code to the virtual function will wind up calling the -method defined in Go. The Go code may of course call other methods on -itself, and those methods may be defined either in Go or in C++. +In order to be able to use runtime.SetFinalizer nevertheless the +finalizer needs to be set on something that isn't in a cycle and that references +the director object instance. In the FooBarGo class example the +FooBarAbs director instance can be automatically deleted by setting the +finalizer on fooBarGo:

    +
    +
    +type fooBarGo struct {
    +	FooBarAbs
    +}
    +
    +type overwritenMethodsOnFooBarAbs struct {
    +	fb FooBarAbs
    +}
    +
    +func NewFooBarGo() FooBarGo {
    +	om := &overwritenMethodsOnFooBarAbs{}
    +	fb := NewDirectorFooBarAbs(om)
    +	om.fb = fb // Backlink causes cycle as fb.v = om!
    +
    +	fbgs := &fooBarGo{FooBarAbs: fb}
    +	runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs)
    +	return fbgs
    +}
    +
    +
    + +

    +Furthermore if runtime.SetFinalizer is in use either the +DeleteClassName destructor function needs to be removed or the +fooBarGo struct needs additional data to prevent double deletion. Please +read the C++ class memory management subchapter +before using runtime.SetFinalizer to know all of its gotchas. +

    + + +

    23.4.7.8 Complete FooBarGo example class

    + + +

    +The complete and annotated FooBarGo class looks like this: +

    + +
    +
    +// FooBarGo is a superset of FooBarAbs and hence FooBarGo can be used as a drop
    +// in replacement for FooBarAbs but the reverse causes a compile time error.
    +type FooBarGo interface {
    +	FooBarAbs
    +	deleteFooBarAbs()
    +	IsFooBarGo()
    +}
    +
    +// Via embedding fooBarGo "inherits" all methods of FooBarAbs.
    +type fooBarGo struct {
    +	FooBarAbs
    +}
    +
    +func (fbgs *fooBarGo) deleteFooBarAbs() {
    +	DeleteDirectorFooBarAbs(fbgs.FooBarAbs)
    +}
    +
    +// The IsFooBarGo method ensures that FooBarGo is a superset of FooBarAbs.
    +// This is also how the class hierarchy gets represented by the SWIG generated
    +// wrapper code.  For an instance FooBarCpp has the IsFooBarAbs and IsFooBarCpp
    +// methods.
    +func (fbgs *fooBarGo) IsFooBarGo() {}
    +
    +// Go type that defines the DirectorInterface. It contains the Foo and Bar
    +// methods that overwrite the respective virtual C++ methods on FooBarAbs.
    +type overwritenMethodsOnFooBarAbs struct {
    +	// Backlink to FooBarAbs so that the rest of the class can be used by the
    +	// overridden methods.
    +	fb FooBarAbs
    +
    +	// If additional constructor arguments have been given they are typically
    +	// stored here so that the overriden methods can use them.
    +}
    +
    +func (om *overwritenMethodsOnFooBarAbs) Foo() string {
    +	// DirectorFooBarAbsFoo calls the base method FooBarAbs::Foo.
    +	return "Go " + DirectorFooBarAbsFoo(om.fb)
    +}
    +
    +func (om *overwritenMethodsOnFooBarAbs) Bar() string {
    +	return "Go Bar"
    +}
    +
    +func NewFooBarGo() FooBarGo {
    +	// Instantiate FooBarAbs with selected methods overridden.  The methods that
    +	// will be overwritten are defined on overwritenMethodsOnFooBarAbs and have
    +	// a compatible signature to the respective virtual C++ methods.
    +	// Furthermore additional constructor arguments will be typically stored in
    +	// the overwritenMethodsOnFooBarAbs struct.
    +	om := &overwritenMethodsOnFooBarAbs{}
    +	fb := NewDirectorFooBarAbs(om)
    +	om.fb = fb // Backlink causes cycle as fb.v = om!
    +
    +	fbgs := &fooBarGo{FooBarAbs: fb}
    +	// The memory of the FooBarAbs director object instance can be automatically
    +	// freed once the FooBarGo instance is garbage collected by uncommenting the
    +	// following line.  Please make sure to understand the runtime.SetFinalizer
    +	// specific gotchas before doing this.  Furthemore DeleteFooBarGo should be
    +	// deleted if a finalizer is in use or the fooBarGo struct needs additional
    +	// data to prevent double deletion.
    +	// runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs)
    +	return fbgs
    +}
    +
    +// Recommended to be removed if runtime.SetFinalizer is in use.
    +func DeleteFooBarGo(fbg FooBarGo) {
    +	fbg.deleteFooBarAbs()
    +}
    +
    +
    + +

    +Returned string by the FooBarGo.FooBar method is: +

    + +
    +
    +Go Foo, Go Bar
    +
    +
    + +

    +For comparison the FooBarCpp class looks like this: +

    + +
    +
    +class FooBarCpp : public FooBarAbs
    +{
    +protected:
    +	virtual std::string Foo() {
    +		return "C++ " + FooBarAbs::Foo();
    +	}
    +
    +	virtual std::string Bar() {
    +		return "C++ Bar";
    +	}
    +};
    +
    +
    + +

    +For comparison the returned string by the FooBarCpp::FooBar method is: +

    + +
    +
    +C++ Foo, C++ Bar
    +
    +
    + +

    +The complete source of this example can be found under + +SWIG/Examples/go/director/. +

    + +

    23.4.8 Default Go primitive type mappings

    diff --git a/Examples/go/check.list b/Examples/go/check.list index 5399b8979..b3f34b306 100644 --- a/Examples/go/check.list +++ b/Examples/go/check.list @@ -2,6 +2,7 @@ callback class constants +director enum extend funcptr diff --git a/Examples/go/director/Makefile b/Examples/go/director/Makefile new file mode 100644 index 000000000..8a5fd508a --- /dev/null +++ b/Examples/go/director/Makefile @@ -0,0 +1,17 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +GOSRCS = example.go director.go # example.go gets generated by SWIG +TARGET = example +INTERFACE = example.i +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' GOSRCS='$(GOSRCS)' \ + SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/director/director.go b/Examples/go/director/director.go new file mode 100644 index 000000000..c3132d217 --- /dev/null +++ b/Examples/go/director/director.go @@ -0,0 +1,70 @@ +package example + +// FooBarGo is a superset of FooBarAbs and hence FooBarGo can be used as a drop +// in replacement for FooBarAbs but the reverse causes a compile time error. +type FooBarGo interface { + FooBarAbs + deleteFooBarAbs() + IsFooBarGo() +} + +// Via embedding fooBarGo "inherits" all methods of FooBarAbs. +type fooBarGo struct { + FooBarAbs +} + +func (fbgs *fooBarGo) deleteFooBarAbs() { + DeleteDirectorFooBarAbs(fbgs.FooBarAbs) +} + +// The IsFooBarGo method ensures that FooBarGo is a superset of FooBarAbs. +// This is also how the class hierarchy gets represented by the SWIG generated +// wrapper code. For an instance FooBarCpp has the IsFooBarAbs and IsFooBarCpp +// methods. +func (fbgs *fooBarGo) IsFooBarGo() {} + +// Go type that defines the DirectorInterface. It contains the Foo and Bar +// methods that overwrite the respective virtual C++ methods on FooBarAbs. +type overwritenMethodsOnFooBarAbs struct { + // Backlink to FooBarAbs so that the rest of the class can be used by the + // overridden methods. + fb FooBarAbs + + // If additional constructor arguments have been given they are typically + // stored here so that the overriden methods can use them. +} + +func (om *overwritenMethodsOnFooBarAbs) Foo() string { + // DirectorFooBarAbsFoo calls the base method FooBarAbs::Foo. + return "Go " + DirectorFooBarAbsFoo(om.fb) +} + +func (om *overwritenMethodsOnFooBarAbs) Bar() string { + return "Go Bar" +} + +func NewFooBarGo() FooBarGo { + // Instantiate FooBarAbs with selected methods overridden. The methods that + // will be overwritten are defined on overwritenMethodsOnFooBarAbs and have + // a compatible signature to the respective virtual C++ methods. + // Furthermore additional constructor arguments will be typically stored in + // the overwritenMethodsOnFooBarAbs struct. + om := &overwritenMethodsOnFooBarAbs{} + fb := NewDirectorFooBarAbs(om) + om.fb = fb // Backlink causes cycle as fb.v = om! + + fbgs := &fooBarGo{FooBarAbs: fb} + // The memory of the FooBarAbs director object instance can be automatically + // freed once the FooBarGo instance is garbage collected by uncommenting the + // following line. Please make sure to understand the runtime.SetFinalizer + // specific gotchas before doing this. Furthemore DeleteFooBarGo should be + // deleted if a finalizer is in use or the fooBarGo struct needs additional + // data to prevent double deletion. + // runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs) + return fbgs +} + +// Recommended to be removed if runtime.SetFinalizer is in use. +func DeleteFooBarGo(fbg FooBarGo) { + fbg.deleteFooBarAbs() +} diff --git a/Examples/go/director/director.h b/Examples/go/director/director.h new file mode 100644 index 000000000..e08c11594 --- /dev/null +++ b/Examples/go/director/director.h @@ -0,0 +1,41 @@ +#ifndef DIRECTOR_H +#define DIRECTOR_H + + +#include +#include + + +class FooBarAbs +{ +public: + FooBarAbs() {}; + virtual ~FooBarAbs() {}; + + std::string FooBar() { + return this->Foo() + ", " + this->Bar(); + }; + +protected: + virtual std::string Foo() { + return "Foo"; + }; + + virtual std::string Bar() = 0; +}; + + +class FooBarCpp : public FooBarAbs +{ +protected: + virtual std::string Foo() { + return "C++ " + FooBarAbs::Foo(); + } + + virtual std::string Bar() { + return "C++ Bar"; + } +}; + + +#endif diff --git a/Examples/go/director/example.i b/Examples/go/director/example.i new file mode 100644 index 000000000..b56998e6d --- /dev/null +++ b/Examples/go/director/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module(directors="1") example + +%include "std_string.i" + +%header %{ +#include "director.h" +%} + +%feature("director") FooBarAbs; +%include "director.h" diff --git a/Examples/go/director/index.html b/Examples/go/director/index.html new file mode 100644 index 000000000..d1d5a74bc --- /dev/null +++ b/Examples/go/director/index.html @@ -0,0 +1,28 @@ + + +SWIG:Examples:go:director + + + + +SWIG/Examples/go/director/ +
    + +

    How to subclass a C++ class with a Go type

    + +

    +See the Go Director +Classes documentation subsection for an explanation of this example. +

    + +

    +

      +
    • director.go. Go source with the definition of the FooBarGo class. +
    • director.h. Header with the definition of the FooBarAbs and FooBarCpp classes. +
    • example.i. SWIG interface file. +
    • runme.go. Sample Go program. +
    + +
    + + diff --git a/Examples/go/director/runme.go b/Examples/go/director/runme.go new file mode 100644 index 000000000..0d839bc88 --- /dev/null +++ b/Examples/go/director/runme.go @@ -0,0 +1,39 @@ +package main + +import ( + "./example" + "fmt" + "os" +) + +func Compare(name string, got string, exp string) error { + fmt.Printf("%s; Got: '%s'; Expected: '%s'\n", name, got, exp) + if got != exp { + return fmt.Errorf("%s returned unexpected string! Got: '%s'; Expected: '%s'\n", name, got, exp) + } + return nil +} + +func TestFooBarCpp() error { + fb := example.NewFooBarCpp() + defer example.DeleteFooBarCpp(fb) + return Compare("FooBarCpp.FooBar()", fb.FooBar(), "C++ Foo, C++ Bar") +} + +func TestFooBarGo() error { + fb := example.NewFooBarGo() + defer example.DeleteFooBarGo(fb) + return Compare("FooBarGo.FooBar()", fb.FooBar(), "Go Foo, Go Bar") +} + +func main() { + fmt.Println("Test output:") + fmt.Println("------------") + err := TestFooBarCpp() + err = TestFooBarGo() + fmt.Println("------------") + if err != nil { + fmt.Fprintf(os.Stderr, "Tests failed! Last error: %s\n", err.Error()) + os.Exit(1) + } +} -- cgit v1.2.1 From 94994a749e813176ddd68fc67e22ae2cda442ddd Mon Sep 17 00:00:00 2001 From: Michael Schaller Date: Wed, 24 Jun 2015 14:53:28 +0200 Subject: Removed empty line in table of contents of the Go documentation. --- Doc/Manual/Go.html | 1 - 1 file changed, 1 deletion(-) diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html index 0be378f6a..19a078d89 100644 --- a/Doc/Manual/Go.html +++ b/Doc/Manual/Go.html @@ -38,7 +38,6 @@
  • Subclass via embedding
  • Memory management with runtime.SetFinalizer
  • Complete FooBarGo example class -
  • Default Go primitive type mappings
  • Output arguments -- cgit v1.2.1 From afd6a55ce1089b0ee67bfa5509abfa126926c459 Mon Sep 17 00:00:00 2001 From: Michael Schaller Date: Fri, 26 Jun 2015 11:25:23 +0200 Subject: Fixed Examples/go/director/Makefile as director.go was missing in separate build directories. --- Examples/go/director/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Examples/go/director/Makefile b/Examples/go/director/Makefile index 8a5fd508a..0bb5c7b98 100644 --- a/Examples/go/director/Makefile +++ b/Examples/go/director/Makefile @@ -10,6 +10,9 @@ check: build $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run build: + if [ -n '$(SRCDIR)' ]; then \ + cp $(SRCDIR)/director.go .; \ + fi $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' GOSRCS='$(GOSRCS)' \ SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp -- cgit v1.2.1 From 0db9a6ba7b243546979f9a1737bac8d8435295d8 Mon Sep 17 00:00:00 2001 From: Michael Schaller Date: Fri, 26 Jun 2015 12:34:43 +0200 Subject: Fixed Examples/go/director/Makefile as the copy of director.go wasn't cleaned up in separate build directories. --- Examples/go/director/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Examples/go/director/Makefile b/Examples/go/director/Makefile index 0bb5c7b98..0c59bf340 100644 --- a/Examples/go/director/Makefile +++ b/Examples/go/director/Makefile @@ -17,4 +17,7 @@ build: SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp clean: + if [ -n '$(SRCDIR)' ]; then \ + rm director.go; \ + fi $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean -- cgit v1.2.1 From e47d87e404859b8de09663f8d38485238f7eab52 Mon Sep 17 00:00:00 2001 From: Michael Schaller Date: Fri, 26 Jun 2015 13:27:37 +0200 Subject: Fixed Examples/go/director/Makefile as there might be no copy of director.go during clean if a separate build directory is in use. --- Examples/go/director/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/go/director/Makefile b/Examples/go/director/Makefile index 0c59bf340..84de5855d 100644 --- a/Examples/go/director/Makefile +++ b/Examples/go/director/Makefile @@ -18,6 +18,6 @@ build: clean: if [ -n '$(SRCDIR)' ]; then \ - rm director.go; \ + rm director.go || true; \ fi $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean -- cgit v1.2.1 From d9d26149e78e1488c263c00c4604c998004f65b5 Mon Sep 17 00:00:00 2001 From: Michael Schaller Date: Tue, 4 Aug 2015 09:50:56 +0200 Subject: Some minor changes after first code review by ianlancetaylor. Renamed overwritenMethodsOnFooBarAbs to overwrittenMethodsOnFooBarAbs. Changed some line breaks. --- Doc/Manual/Go.html | 62 ++++++++++++++++++++-------------------- Examples/go/director/director.go | 12 ++++---- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html index 19a078d89..c008ef22c 100644 --- a/Doc/Manual/Go.html +++ b/Doc/Manual/Go.html @@ -592,8 +592,8 @@ the %template directive. SWIG's director feature permits a Go type to act as the subclass of a C++ class. This is complicated by the fact that C++ and Go define inheritance differently. SWIG normally represents the C++ class inheritance automatically in Go via -interfaces but with a Go type representing a subclass of a C++ class quite some -manual work is necessary. +interfaces but with a Go type representing a subclass of a C++ class some manual +work is necessary.

    @@ -714,12 +714,12 @@ documentation on directors.

    SWIG creates an additional set of constructor and destructor functions once the -director feature has been enabled for a C++ class. NewDirectorClassName - allows to override virtual methods on the new object instance and -DeleteDirectorClassName needs to be used to free a director object instance -created with NewDirectorClassName. More on overriding virtual methods -follows later in this guide under -overriding virtual methods. +director feature has been enabled for a C++ class. +NewDirectorClassName allows overriding virtual methods on the new +object instance and DeleteDirectorClassName needs to be used to free a +director object instance created with NewDirectorClassName. +More on overriding virtual methods follows later in this guide under +overriding virtual methods.

    @@ -782,20 +782,20 @@ As an example see part of the FooBarGo class:

    -type overwritenMethodsOnFooBarAbs struct {
    +type overwrittenMethodsOnFooBarAbs struct {
     	fb FooBarAbs
     }
     
    -func (om *overwritenMethodsOnFooBarAbs) Foo() string {
    +func (om *overwrittenMethodsOnFooBarAbs) Foo() string {
     	...
     }
     
    -func (om *overwritenMethodsOnFooBarAbs) Bar() string {
    +func (om *overwrittenMethodsOnFooBarAbs) Bar() string {
     	...
     }
     
     func NewFooBarGo() FooBarGo {
    -	om := &overwritenMethodsOnFooBarAbs{}
    +	om := &overwrittenMethodsOnFooBarAbs{}
     	fb := NewDirectorFooBarAbs(om)
     	om.fb = fb
     	...
    @@ -814,16 +814,16 @@ class.
     
     

    The DirectorInterface in the example is implemented by the -overwritenMethodsOnFooBarAbs Go struct type. A pointer to a -overwritenMethodsOnFooBarAbs struct instance will be given to the +overwrittenMethodsOnFooBarAbs Go struct type. A pointer to a +overwrittenMethodsOnFooBarAbs struct instance will be given to the NewDirectorFooBarAbs constructor function. The constructor return value implements the FooBarAbs interface. -overwritenMethodsOnFooBarAbs could in theory be any Go type but in +overwrittenMethodsOnFooBarAbs could in theory be any Go type but in practice a struct is used as it typically contains at least a value of the C++ class interface so that the overwritten methods can use the rest of the C++ class. If the FooBarGo class would receive additional constructor -arguments then these would also typically be stored in the -overwritenMethodsOnFooBarAbs struct so that they can be used by the +arguments then these would also typically be stored in the +overwrittenMethodsOnFooBarAbs struct so that they can be used by the Go methods.

    @@ -833,8 +833,8 @@ Go methods.

    Often a virtual method will be overwritten to extend the original behavior of -the method in the base class. This is also the case for the FooBarCpp::Foo - method of the example code: +the method in the base class. This is also the case for the +FooBarCpp::Foo method of the example code:

    @@ -853,7 +853,7 @@ The FooBarGo.Foo implementation in the example looks like this:
    -func (om *overwritenMethodsOnFooBarAbs) Foo() string {
    +func (om *overwrittenMethodsOnFooBarAbs) Foo() string {
     	return "Go " + DirectorFooBarAbsFoo(om.fb)
     }
     
    @@ -903,7 +903,7 @@ func (fbgs *fooBarGo) deleteFooBarAbs() { func (fbgs *fooBarGo) IsFooBarGo() {} func NewFooBarGo() FooBarGo { - om := &overwritenMethodsOnFooBarAbs{} + om := &overwrittenMethodsOnFooBarAbs{} fb := NewDirectorFooBarAbs(om) om.fb = fb @@ -946,12 +946,12 @@ in the FooBarGo class is here:
    -type overwritenMethodsOnFooBarAbs struct {
    +type overwrittenMethodsOnFooBarAbs struct {
     	fb FooBarAbs
     }
     
     func NewFooBarGo() FooBarGo {
    -	om := &overwritenMethodsOnFooBarAbs{}
    +	om := &overwrittenMethodsOnFooBarAbs{}
     	fb := NewDirectorFooBarAbs(om) // fb.v = om
     	om.fb = fb // Backlink causes cycle as fb.v = om!
     	...
    @@ -973,12 +973,12 @@ type fooBarGo struct {
     	FooBarAbs
     }
     
    -type overwritenMethodsOnFooBarAbs struct {
    +type overwrittenMethodsOnFooBarAbs struct {
     	fb FooBarAbs
     }
     
     func NewFooBarGo() FooBarGo {
    -	om := &overwritenMethodsOnFooBarAbs{}
    +	om := &overwrittenMethodsOnFooBarAbs{}
     	fb := NewDirectorFooBarAbs(om)
     	om.fb = fb // Backlink causes cycle as fb.v = om!
     
    @@ -1032,7 +1032,7 @@ func (fbgs *fooBarGo) IsFooBarGo() {}
     
     // Go type that defines the DirectorInterface. It contains the Foo and Bar
     // methods that overwrite the respective virtual C++ methods on FooBarAbs.
    -type overwritenMethodsOnFooBarAbs struct {
    +type overwrittenMethodsOnFooBarAbs struct {
     	// Backlink to FooBarAbs so that the rest of the class can be used by the
     	// overridden methods.
     	fb FooBarAbs
    @@ -1041,22 +1041,22 @@ type overwritenMethodsOnFooBarAbs struct {
     	// stored here so that the overriden methods can use them.
     }
     
    -func (om *overwritenMethodsOnFooBarAbs) Foo() string {
    +func (om *overwrittenMethodsOnFooBarAbs) Foo() string {
     	// DirectorFooBarAbsFoo calls the base method FooBarAbs::Foo.
     	return "Go " + DirectorFooBarAbsFoo(om.fb)
     }
     
    -func (om *overwritenMethodsOnFooBarAbs) Bar() string {
    +func (om *overwrittenMethodsOnFooBarAbs) Bar() string {
     	return "Go Bar"
     }
     
     func NewFooBarGo() FooBarGo {
     	// Instantiate FooBarAbs with selected methods overridden.  The methods that
    -	// will be overwritten are defined on overwritenMethodsOnFooBarAbs and have
    +	// will be overwritten are defined on overwrittenMethodsOnFooBarAbs and have
     	// a compatible signature to the respective virtual C++ methods.
     	// Furthermore additional constructor arguments will be typically stored in
    -	// the overwritenMethodsOnFooBarAbs struct.
    -	om := &overwritenMethodsOnFooBarAbs{}
    +	// the overwrittenMethodsOnFooBarAbs struct.
    +	om := &overwrittenMethodsOnFooBarAbs{}
     	fb := NewDirectorFooBarAbs(om)
     	om.fb = fb // Backlink causes cycle as fb.v = om!
     
    diff --git a/Examples/go/director/director.go b/Examples/go/director/director.go
    index c3132d217..a5078fe58 100644
    --- a/Examples/go/director/director.go
    +++ b/Examples/go/director/director.go
    @@ -25,7 +25,7 @@ func (fbgs *fooBarGo) IsFooBarGo() {}
     
     // Go type that defines the DirectorInterface. It contains the Foo and Bar
     // methods that overwrite the respective virtual C++ methods on FooBarAbs.
    -type overwritenMethodsOnFooBarAbs struct {
    +type overwrittenMethodsOnFooBarAbs struct {
     	// Backlink to FooBarAbs so that the rest of the class can be used by the
     	// overridden methods.
     	fb FooBarAbs
    @@ -34,22 +34,22 @@ type overwritenMethodsOnFooBarAbs struct {
     	// stored here so that the overriden methods can use them.
     }
     
    -func (om *overwritenMethodsOnFooBarAbs) Foo() string {
    +func (om *overwrittenMethodsOnFooBarAbs) Foo() string {
     	// DirectorFooBarAbsFoo calls the base method FooBarAbs::Foo.
     	return "Go " + DirectorFooBarAbsFoo(om.fb)
     }
     
    -func (om *overwritenMethodsOnFooBarAbs) Bar() string {
    +func (om *overwrittenMethodsOnFooBarAbs) Bar() string {
     	return "Go Bar"
     }
     
     func NewFooBarGo() FooBarGo {
     	// Instantiate FooBarAbs with selected methods overridden.  The methods that
    -	// will be overwritten are defined on overwritenMethodsOnFooBarAbs and have
    +	// will be overwritten are defined on overwrittenMethodsOnFooBarAbs and have
     	// a compatible signature to the respective virtual C++ methods.
     	// Furthermore additional constructor arguments will be typically stored in
    -	// the overwritenMethodsOnFooBarAbs struct.
    -	om := &overwritenMethodsOnFooBarAbs{}
    +	// the overwrittenMethodsOnFooBarAbs struct.
    +	om := &overwrittenMethodsOnFooBarAbs{}
     	fb := NewDirectorFooBarAbs(om)
     	om.fb = fb // Backlink causes cycle as fb.v = om!
     
    -- 
    cgit v1.2.1
    
    
    From 736613e26c911645237594980f6fa3064f634701 Mon Sep 17 00:00:00 2001
    From: Michael Schaller 
    Date: Wed, 5 Aug 2015 10:01:15 +0200
    Subject: [Go] Documentation cleanup of obsolete 'callback' and 'extend'
     examples.
    
    After commit 17b1c1c (pull request 447; issue 418) the 'callback' and 'extend'
    examples have been removed in favor of the 'director' example.
    ---
     Examples/go/callback/Makefile     | 16 --------
     Examples/go/callback/callback.cxx |  4 --
     Examples/go/callback/example.h    | 23 -----------
     Examples/go/callback/example.i    | 11 ------
     Examples/go/callback/index.html   | 81 ---------------------------------------
     Examples/go/callback/runme.go     | 41 --------------------
     Examples/go/check.list            |  2 -
     Examples/go/extend/Makefile       | 16 --------
     Examples/go/extend/example.h      | 56 ---------------------------
     Examples/go/extend/example.i      | 15 --------
     Examples/go/extend/extend.cxx     |  4 --
     Examples/go/extend/index.html     | 27 -------------
     Examples/go/extend/runme.go       | 76 ------------------------------------
     Examples/go/index.html            |  7 ++--
     14 files changed, 3 insertions(+), 376 deletions(-)
     delete mode 100644 Examples/go/callback/Makefile
     delete mode 100644 Examples/go/callback/callback.cxx
     delete mode 100644 Examples/go/callback/example.h
     delete mode 100644 Examples/go/callback/example.i
     delete mode 100644 Examples/go/callback/index.html
     delete mode 100644 Examples/go/callback/runme.go
     delete mode 100644 Examples/go/extend/Makefile
     delete mode 100644 Examples/go/extend/example.h
     delete mode 100644 Examples/go/extend/example.i
     delete mode 100644 Examples/go/extend/extend.cxx
     delete mode 100644 Examples/go/extend/index.html
     delete mode 100644 Examples/go/extend/runme.go
    
    diff --git a/Examples/go/callback/Makefile b/Examples/go/callback/Makefile
    deleted file mode 100644
    index bf5275f14..000000000
    --- a/Examples/go/callback/Makefile
    +++ /dev/null
    @@ -1,16 +0,0 @@
    -TOP        = ../..
    -SWIG       = $(TOP)/../preinst-swig
    -CXXSRCS    = callback.cxx
    -TARGET     = example
    -INTERFACE  = example.i
    -SWIGOPT    =
    -
    -check: build
    -	$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run
    -
    -build:
    -	$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
    -	SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp
    -
    -clean:
    -	$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean
    diff --git a/Examples/go/callback/callback.cxx b/Examples/go/callback/callback.cxx
    deleted file mode 100644
    index 450d75608..000000000
    --- a/Examples/go/callback/callback.cxx
    +++ /dev/null
    @@ -1,4 +0,0 @@
    -/* File : example.cxx */
    -
    -#include "example.h"
    -
    diff --git a/Examples/go/callback/example.h b/Examples/go/callback/example.h
    deleted file mode 100644
    index 1a0e8c432..000000000
    --- a/Examples/go/callback/example.h
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -/* File : example.h */
    -
    -#include 
    -#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/go/callback/example.i b/Examples/go/callback/example.i
    deleted file mode 100644
    index cf61ef9d2..000000000
    --- a/Examples/go/callback/example.i
    +++ /dev/null
    @@ -1,11 +0,0 @@
    -/* File : example.i */
    -%module(directors="1") example
    -%{
    -#include "example.h"
    -%}
    -
    -/* turn on director wrapping Callback */
    -%feature("director") Callback;
    -
    -%include "example.h"
    -
    diff --git a/Examples/go/callback/index.html b/Examples/go/callback/index.html
    deleted file mode 100644
    index b053cf547..000000000
    --- a/Examples/go/callback/index.html
    +++ /dev/null
    @@ -1,81 +0,0 @@
    -
    -
    -SWIG:Examples:go:callback
    -
    -
    -
    -
    -
    -SWIG/Examples/go/callback/
    -
    - -

    Implementing C++ callbacks in Go

    - -

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

    - -

    -Because Go and C++ use inheritance differently, you must call a -different function to create a class which uses callbacks. Instead of -calling the usual constructor function whose name is New -followed by the capitalized name of the class, you call a function -named NewDirector followed by the capitalized name of the -class. -

    - -

    -The first argument to the NewDirector function is an instance -of a type. The NewDirector function will return an interface -value as usual. However, when calling any method on the returned -value, the program will first check whether the value passed -to NewDirector implements that method. If it does, the -method will be called in Go. This is true whether the method is -called from Go code or C++ code. -

    - -

    -Note that the Go code will be called with just the Go value, not the -C++ value. If the Go code needs to call a C++ method on itself, you -need to get a copy of the C++ object. This is typically done as -follows: - -

    -
    -type Child struct { abi Parent }
    -func (p *Child) ChildMethod() {
    -	p.abi.ParentMethod()
    -}
    -func f() {
    -	p := &Child{nil}
    -	d := NewDirectorParent(p)
    -	p.abi = d
    -	...
    -}
    -
    -
    - -In other words, we first create the Go value. We pass that to -the NewDirector function to create the C++ value; this C++ -value will be created with an association to the Go value. We then -store the C++ value in the Go value, giving us the reverse -association. That permits us to call parent methods from the child. - -

    - -

    -To delete a director object, use the function DeleteDirector -followed by the capitalized name of the class. -

    - -

    -

    - -
    - - diff --git a/Examples/go/callback/runme.go b/Examples/go/callback/runme.go deleted file mode 100644 index 2eef77fdb..000000000 --- a/Examples/go/callback/runme.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - . "./example" - "fmt" -) - -func main() { - fmt.Println("Adding and calling a normal C++ callback") - fmt.Println("----------------------------------------") - - caller := NewCaller() - callback := NewCallback() - - caller.SetCallback(callback) - caller.Call() - caller.DelCallback() - - callback = NewDirectorCallback(new(GoCallback)) - - fmt.Println() - fmt.Println("Adding and calling a Go callback") - fmt.Println("------------------------------------") - - caller.SetCallback(callback) - caller.Call() - caller.DelCallback() - - // Test that a double delete does not occur as the object has - // already been deleted from the C++ layer. - DeleteDirectorCallback(callback) - - fmt.Println() - fmt.Println("Go exit") -} - -type GoCallback struct{} - -func (p *GoCallback) Run() { - fmt.Println("GoCallback.Run") -} diff --git a/Examples/go/check.list b/Examples/go/check.list index b3f34b306..25322352a 100644 --- a/Examples/go/check.list +++ b/Examples/go/check.list @@ -1,10 +1,8 @@ # see top-level Makefile.in -callback class constants director enum -extend funcptr multimap pointer diff --git a/Examples/go/extend/Makefile b/Examples/go/extend/Makefile deleted file mode 100644 index 290694210..000000000 --- a/Examples/go/extend/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -TOP = ../.. -SWIG = $(TOP)/../preinst-swig -CXXSRCS = extend.cxx -TARGET = example -INTERFACE = example.i -SWIGOPT = - -check: build - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run - -build: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ - SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp - -clean: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/extend/example.h b/Examples/go/extend/example.h deleted file mode 100644 index ca1aed28f..000000000 --- a/Examples/go/extend/example.h +++ /dev/null @@ -1,56 +0,0 @@ -/* 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", (void *)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/go/extend/example.i b/Examples/go/extend/example.i deleted file mode 100644 index c8ec32e09..000000000 --- a/Examples/go/extend/example.i +++ /dev/null @@ -1,15 +0,0 @@ -/* 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/go/extend/extend.cxx b/Examples/go/extend/extend.cxx deleted file mode 100644 index 450d75608..000000000 --- a/Examples/go/extend/extend.cxx +++ /dev/null @@ -1,4 +0,0 @@ -/* File : example.cxx */ - -#include "example.h" - diff --git a/Examples/go/extend/index.html b/Examples/go/extend/index.html deleted file mode 100644 index 471fa9cdc..000000000 --- a/Examples/go/extend/index.html +++ /dev/null @@ -1,27 +0,0 @@ - - -SWIG:Examples:go:extend - - - - - -SWIG/Examples/go/extend/ -
    - -

    Extending a simple C++ class in Go

    - -

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

    -

    - -
    - - diff --git a/Examples/go/extend/runme.go b/Examples/go/extend/runme.go deleted file mode 100644 index 770e27802..000000000 --- a/Examples/go/extend/runme.go +++ /dev/null @@ -1,76 +0,0 @@ -// This file illustrates the cross language polymorphism using directors. - -package main - -import ( - . "./example" - "fmt" -) - -type CEO struct{} - -func (p *CEO) GetPosition() string { - return "CEO" -} - -func main() { - // Create an instance of CEO, a class derived from the Go - // proxy of the underlying C++ class. The calls to getName() - // and getPosition() are standard, the call to getTitle() uses - // the director wrappers to call CEO.getPosition(). - - e := NewDirectorManager(new(CEO), "Alice") - fmt.Println(e.GetName(), " is a ", e.GetPosition()) - fmt.Println("Just call her \"", e.GetTitle(), "\"") - fmt.Println("----------------------") - - // 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 := NewEmployeeList() - - // EmployeeList owns its items, so we must surrender ownership - // of objects we add. - // e.DisownMemory() - list.AddEmployee(e) - fmt.Println("----------------------") - - // 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, all methods - // resolve in C++. For item 3, our CEO, GetTitle calls - // GetPosition which resolves in Go. The call to GetPosition - // is slightly different, however, because of the overridden - // GetPosition() call, since now the object reference has been - // "laundered" by passing through EmployeeList as an - // Employee*. Previously, Go resolved the call immediately in - // CEO, but now Go thinks the object is an instance of class - // Employee. So the call passes through the Employee proxy - // class and on to the C wrappers and C++ director, eventually - // ending up back at the Java 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 Java implementation - // in CEO. All this routing takes place transparently. - - fmt.Println("(position, title) for items 0-3:") - - fmt.Println(" ", list.Get_item(0).GetPosition(), ", \"", list.Get_item(0).GetTitle(), "\"") - fmt.Println(" ", list.Get_item(1).GetPosition(), ", \"", list.Get_item(1).GetTitle(), "\"") - fmt.Println(" ", list.Get_item(2).GetPosition(), ", \"", list.Get_item(2).GetTitle(), "\"") - fmt.Println(" ", list.Get_item(3).GetPosition(), ", \"", list.Get_item(3).GetTitle(), "\"") - fmt.Println("----------------------") - - // Time to delete the EmployeeList, which will delete all the - // Employee* items it contains. The last item is our CEO, - // which gets destroyed as well. - DeleteEmployeeList(list) - fmt.Println("----------------------") - - // All done. - - fmt.Println("Go exit") -} diff --git a/Examples/go/index.html b/Examples/go/index.html index 21dda21b5..4c07af3f0 100644 --- a/Examples/go/index.html +++ b/Examples/go/index.html @@ -21,8 +21,7 @@ certain C declarations are turned into constants.
  • pointer. Simple pointer handling.
  • funcptr. Pointers to functions.
  • template. C++ templates. -
  • callback. C++ callbacks using directors. -
  • extend. Polymorphism using directors. +
  • director. Example how to utilize the director feature.

    Compilation Issues

    @@ -46,7 +45,7 @@ the 6g or 8g compiler, the steps look like this
     % swig -go interface.i
     % gcc -fpic -c interface_wrap.c
    -% gcc -shared interface_wrap.o $(OBJS) -o interfacemodule.so 
    +% gcc -shared interface_wrap.o $(OBJS) -o interfacemodule.so
     % 6g interface.go
     % 6c interface_gc.c
     % gopack grc interface.a interface.6 interface_gc.6
    @@ -83,7 +82,7 @@ All of the examples were last tested with the following configuration
     
  • gcc-4.2.4 -Your mileage may vary. If you experience a problem, please let us know by +Your mileage may vary. If you experience a problem, please let us know by contacting us on the mailing lists. -- cgit v1.2.1 From 95a08b3950ea1f43846ccff11969c9179f2eeddd Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 5 Aug 2015 07:19:05 -0700 Subject: [Go] update build instructions in Examples/go/index.html --- Examples/go/index.html | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/Examples/go/index.html b/Examples/go/index.html index 4c07af3f0..b7d7017d3 100644 --- a/Examples/go/index.html +++ b/Examples/go/index.html @@ -36,20 +36,23 @@ certain C declarations are turned into constants.
  • On Unix the compilation of examples is done using the -file Example/Makefile. This makefile performs a manual -module compilation which is platform specific. When using -the 6g or 8g compiler, the steps look like this +file Example/Makefile. Normally builds are done simply +using go build. For testing purposes this makefile performs +a manual module compilation that is platform specific. When using +the gc compiler, the steps look approximately like this (GNU/Linux):
    -% swig -go interface.i
    -% gcc -fpic -c interface_wrap.c
    -% gcc -shared interface_wrap.o $(OBJS) -o interfacemodule.so
    -% 6g interface.go
    -% 6c interface_gc.c
    -% gopack grc interface.a interface.6 interface_gc.6
    -% 6l program.6
    +% swig -go -cgo interface.i
    +% mkdir -p gopath/src/interface
    +% cp interface_wrap.c interface_wrap.h interface.go gopath/src/interface
    +% GOPATH=`pwd`/gopath
    +% export GOPATH
    +% cd gopath/src/interface
    +% go build
    +% go tool compile $(SRCDIR)/runme.go
    +% go tool link -o runme runme.o
     
    @@ -57,10 +60,15 @@ the 6g or 8g compiler, the steps look like this
    -% swig -go interface.i
    -% gcc -c interface_wrap.c
    -% gccgo -c interface.go
    -% gccgo program.o interface.o interface_wrap.o
    +% swig -go -cgo interface.i
    +% mkdir -p gopath/src/interface
    +% cp interface_wrap.c interface_wrap.h interface.go gopath/src/interface
    +% GOPATH=`pwd`/gopath
    +% export GOPATH
    +% cd gopath/src/interface
    +% go build
    +% gccgo -c $(SRCDIR)/runme.go
    +% gccgo -o runme runme.o interface.a
     
    All of the examples were last tested with the following configuration -(10 May 2010): +(5 August 2015):
      -
    • Ubuntu Hardy -
    • gcc-4.2.4 +
    • Ubuntu Trusty +
    • gcc-4.8.4
    Your mileage may vary. If you experience a problem, please let us know by -- cgit v1.2.1 From a1bddd56eb3404c9a069a48fa7b391fd255a7905 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 6 Aug 2015 00:10:51 +0200 Subject: Make (char*, size_t) typemap usable for strings of other types in Java. Notably it now works for "unsigned char*" strings. Add a test to check that it now works in Java and also showing that it already worked for the other languages with support for this typemap. --- CHANGES.current | 4 ++++ Examples/test-suite/char_binary.i | 4 ++++ Examples/test-suite/java/char_binary_runme.java | 6 ++++++ Examples/test-suite/javascript/char_binary_runme.js | 10 ++++++++++ Examples/test-suite/perl5/char_binary_runme.pl | 5 ++++- Examples/test-suite/python/char_binary_runme.py | 7 +++++++ Lib/java/java.swg | 4 ++-- 7 files changed, 37 insertions(+), 3 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index c0694f657..f78f6bb48 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -4,3 +4,7 @@ See the RELEASENOTES file for a summary of changes in each release. Version 3.0.8 (in progress) =========================== + +2015-08-05: vadz + [Java] Make (char* STRING, size_t LENGTH) typemaps usable for + strings of other types, e.g. "unsigned char*". diff --git a/Examples/test-suite/char_binary.i b/Examples/test-suite/char_binary.i index 778792946..394565438 100644 --- a/Examples/test-suite/char_binary.i +++ b/Examples/test-suite/char_binary.i @@ -5,12 +5,16 @@ A test case for testing non null terminated char pointers. %module char_binary %apply (char *STRING, size_t LENGTH) { (const char *str, size_t len) } +%apply (char *STRING, size_t LENGTH) { (const unsigned char *str, size_t len) } %inline %{ struct Test { size_t strlen(const char *str, size_t len) { return len; } + size_t ustrlen(const unsigned char *str, size_t len) { + return len; + } }; typedef char namet[5]; diff --git a/Examples/test-suite/java/char_binary_runme.java b/Examples/test-suite/java/char_binary_runme.java index 9227f8617..bc811ef5d 100644 --- a/Examples/test-suite/java/char_binary_runme.java +++ b/Examples/test-suite/java/char_binary_runme.java @@ -20,5 +20,11 @@ public class char_binary_runme { if (t.strlen(hil0) != 4) throw new RuntimeException("bad multi-arg typemap"); + + if (t.ustrlen(hile) != 4) + throw new RuntimeException("bad multi-arg typemap"); + + if (t.ustrlen(hil0) != 4) + throw new RuntimeException("bad multi-arg typemap"); } } diff --git a/Examples/test-suite/javascript/char_binary_runme.js b/Examples/test-suite/javascript/char_binary_runme.js index b2aac920c..01b72ebe1 100644 --- a/Examples/test-suite/javascript/char_binary_runme.js +++ b/Examples/test-suite/javascript/char_binary_runme.js @@ -5,10 +5,17 @@ if (t.strlen('hile') != 4) { print(t.strlen('hile')); throw("bad multi-arg typemap 1"); } +if (t.ustrlen('hile') != 4) { + print(t.ustrlen('hile')); + throw("bad multi-arg typemap 1"); +} if (t.strlen('hil\0') != 4) { throw("bad multi-arg typemap 2"); } +if (t.ustrlen('hil\0') != 4) { + throw("bad multi-arg typemap 2"); +} /* * creating a raw char* @@ -24,6 +31,9 @@ char_binary.pchar_setitem(pc, 4, 0); if (t.strlen(pc) != 4) { throw("bad multi-arg typemap (3)"); } +if (t.ustrlen(pc) != 4) { + throw("bad multi-arg typemap (3)"); +} char_binary.var_pchar = pc; if (char_binary.var_pchar != "hola") { diff --git a/Examples/test-suite/perl5/char_binary_runme.pl b/Examples/test-suite/perl5/char_binary_runme.pl index 4c50ee700..f97d740a6 100644 --- a/Examples/test-suite/perl5/char_binary_runme.pl +++ b/Examples/test-suite/perl5/char_binary_runme.pl @@ -1,14 +1,16 @@ use strict; use warnings; -use Test::More tests => 7; +use Test::More tests => 10; BEGIN { use_ok('char_binary') } require_ok('char_binary'); my $t = char_binary::Test->new(); is($t->strlen('hile'), 4, "string typemap"); +is($t->ustrlen('hile'), 4, "unsigned string typemap"); is($t->strlen("hil\0"), 4, "string typemap"); +is($t->ustrlen("hil\0"), 4, "unsigned string typemap"); # # creating a raw char* @@ -22,6 +24,7 @@ char_binary::pchar_setitem($pc, 4, 0); is($t->strlen($pc), 4, "string typemap"); +is($t->ustrlen($pc), 4, "unsigned string typemap"); $char_binary::var_pchar = $pc; is($char_binary::var_pchar, "hola", "pointer case"); diff --git a/Examples/test-suite/python/char_binary_runme.py b/Examples/test-suite/python/char_binary_runme.py index 13457253f..34caa3208 100644 --- a/Examples/test-suite/python/char_binary_runme.py +++ b/Examples/test-suite/python/char_binary_runme.py @@ -4,9 +4,14 @@ t = Test() if t.strlen('hile') != 4: print t.strlen('hile') raise RuntimeError, "bad multi-arg typemap" +if t.ustrlen('hile') != 4: + print t.ustrlen('hile') + raise RuntimeError, "bad multi-arg typemap" if t.strlen('hil\0') != 4: raise RuntimeError, "bad multi-arg typemap" +if t.ustrlen('hil\0') != 4: + raise RuntimeError, "bad multi-arg typemap" # # creating a raw char* @@ -21,6 +26,8 @@ pchar_setitem(pc, 4, 0) if t.strlen(pc) != 4: raise RuntimeError, "bad multi-arg typemap" +if t.ustrlen(pc) != 4: + raise RuntimeError, "bad multi-arg typemap" cvar.var_pchar = pc if cvar.var_pchar != "hola": diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 2e106796c..0ff487d80 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -1330,8 +1330,8 @@ SWIG_PROXY_CONSTRUCTOR(true, true, SWIGTYPE) %typemap(freearg) (char *STRING, size_t LENGTH) "" %typemap(in) (char *STRING, size_t LENGTH) { if ($input) { - $1 = (char *) JCALL2(GetByteArrayElements, jenv, $input, 0); - $2 = (size_t) JCALL1(GetArrayLength, jenv, $input); + $1 = ($1_ltype) JCALL2(GetByteArrayElements, jenv, $input, 0); + $2 = ($2_type) JCALL1(GetArrayLength, jenv, $input); } else { $1 = 0; $2 = 0; -- cgit v1.2.1 From 92328a2016bd0d3e5e383cbc30a6713c28c60470 Mon Sep 17 00:00:00 2001 From: xantares Date: Mon, 13 Apr 2015 11:15:18 +0200 Subject: pep257 & numpydoc conforming docstrings --- Doc/Manual/Python.html | 37 ++--- Examples/test-suite/autodoc.i | 4 +- Examples/test-suite/python/autodoc_runme.py | 222 +++++++++++++++------------- Source/Modules/python.cxx | 17 ++- 4 files changed, 156 insertions(+), 124 deletions(-) diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 57a2cd3ef..3af79e8d6 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -5273,8 +5273,8 @@ def function_name(*args, **kwargs):

    Level "2" results in the function prototype as per level "0". In addition, a line of -documentation is generated for each parameter. Using the previous example, the generated -code will be: +documentation is generated for each parameter using numpydoc style. +Using the previous example, the generated code will be:

    @@ -5283,11 +5283,12 @@ def function_name(*args, **kwargs): """ function_name(x, y, foo=None, bar=None) -> bool - Parameters: - x: int - y: int - foo: Foo * - bar: Bar * + Parameters + ---------- + x: int + y: int + foo: Foo * + bar: Bar * """ ... @@ -5318,11 +5319,12 @@ def function_name(*args, **kwargs): """ function_name(x, y, foo=None, bar=None) -> bool - Parameters: - x (C++ type: int) -- Input x dimension - y: int - foo: Foo * - bar: Bar * + Parameters + ---------- + x (C++ type: int) -- Input x dimension + y: int + foo: Foo * + bar: Bar * """
  • @@ -5341,11 +5343,12 @@ def function_name(*args, **kwargs): """ function_name(int x, int y, Foo foo=None, Bar bar=None) -> bool - Parameters: - x: int - y: int - foo: Foo * - bar: Bar * + Parameters + ---------- + x: int + y: int + foo: Foo * + bar: Bar * """ ... diff --git a/Examples/test-suite/autodoc.i b/Examples/test-suite/autodoc.i index 07afa5794..eda04d293 100644 --- a/Examples/test-suite/autodoc.i +++ b/Examples/test-suite/autodoc.i @@ -1,4 +1,4 @@ -%module(docstring="hello") autodoc +%module(docstring="hello.") autodoc %feature("autodoc"); @@ -27,7 +27,7 @@ %feature("autodoc","2") A::variable_c; // extended %feature("autodoc","3") A::variable_d; // extended + types -%feature("autodoc","just a string") A::funk; // names +%feature("autodoc","just a string.") A::funk; // names %inline { diff --git a/Examples/test-suite/python/autodoc_runme.py b/Examples/test-suite/python/autodoc_runme.py index f5b6b7ce6..7256669d9 100644 --- a/Examples/test-suite/python/autodoc_runme.py +++ b/Examples/test-suite/python/autodoc_runme.py @@ -23,8 +23,8 @@ if not is_new_style_class(A): # skip builtin check - the autodoc is missing, but it probably should not be skip = True -check(A.__doc__, "Proxy of C++ A class", "::A") -check(A.funk.__doc__, "just a string") +check(A.__doc__, "Proxy of C++ A class.", "::A") +check(A.funk.__doc__, "just a string.") check(A.func0.__doc__, "func0(self, arg2, hello) -> int", "func0(arg2, hello) -> int") @@ -35,17 +35,19 @@ check(A.func2.__doc__, "\n" " func2(self, arg2, hello) -> int\n" "\n" - " Parameters:\n" - " arg2: short\n" - " hello: int tuple[2]\n" + " Parameters\n" + " ----------\n" + " arg2: short\n" + " hello: int tuple[2]\n" "\n" " ", "\n" "func2(arg2, hello) -> int\n" "\n" - "Parameters:\n" - " arg2: short\n" - " hello: int tuple[2]\n" + "Parameters\n" + "----------\n" + "arg2: short\n" + "hello: int tuple[2]\n" "\n" "" ) @@ -53,17 +55,19 @@ check(A.func3.__doc__, "\n" " func3(A self, short arg2, Tuple hello) -> int\n" "\n" - " Parameters:\n" - " arg2: short\n" - " hello: int tuple[2]\n" + " Parameters\n" + " ----------\n" + " arg2: short\n" + " hello: int tuple[2]\n" "\n" " ", "\n" "func3(short arg2, Tuple hello) -> int\n" "\n" - "Parameters:\n" - " arg2: short\n" - " hello: int tuple[2]\n" + "Parameters\n" + "----------\n" + "arg2: short\n" + "hello: int tuple[2]\n" "\n" "" ) @@ -92,35 +96,39 @@ check(A.func2default.__doc__, "\n" " func2default(self, e, arg3, hello, f=2) -> int\n" "\n" - " Parameters:\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" - " f: double\n" + " Parameters\n" + " ----------\n" + " e: A *\n" + " arg3: short\n" + " hello: int tuple[2]\n" + " f: double\n" "\n" " func2default(self, e, arg3, hello) -> int\n" "\n" - " Parameters:\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" + " Parameters\n" + " ----------\n" + " e: A *\n" + " arg3: short\n" + " hello: int tuple[2]\n" "\n" " ", "\n" "func2default(e, arg3, hello, f=2) -> int\n" "\n" - "Parameters:\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" - " f: double\n" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg3: short\n" + "hello: int tuple[2]\n" + "f: double\n" "\n" "func2default(e, arg3, hello) -> int\n" "\n" - "Parameters:\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg3: short\n" + "hello: int tuple[2]\n" "\n" "" ) @@ -128,35 +136,39 @@ check(A.func3default.__doc__, "\n" " func3default(A self, A e, short arg3, Tuple hello, double f=2) -> int\n" "\n" - " Parameters:\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" - " f: double\n" + " Parameters\n" + " ----------\n" + " e: A *\n" + " arg3: short\n" + " hello: int tuple[2]\n" + " f: double\n" "\n" " func3default(A self, A e, short arg3, Tuple hello) -> int\n" "\n" - " Parameters:\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" + " Parameters\n" + " ----------\n" + " e: A *\n" + " arg3: short\n" + " hello: int tuple[2]\n" "\n" " ", "\n" "func3default(A e, short arg3, Tuple hello, double f=2) -> int\n" "\n" - "Parameters:\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" - " f: double\n" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg3: short\n" + "hello: int tuple[2]\n" + "f: double\n" "\n" "func3default(A e, short arg3, Tuple hello) -> int\n" "\n" - "Parameters:\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg3: short\n" + "hello: int tuple[2]\n" "\n" "" ) @@ -185,35 +197,39 @@ check(A.func2static.__doc__, "\n" " func2static(e, arg2, hello, f=2) -> int\n" "\n" - " Parameters:\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" - " f: double\n" + " Parameters\n" + " ----------\n" + " e: A *\n" + " arg2: short\n" + " hello: int tuple[2]\n" + " f: double\n" "\n" " func2static(e, arg2, hello) -> int\n" "\n" - " Parameters:\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" + " Parameters\n" + " ----------\n" + " e: A *\n" + " arg2: short\n" + " hello: int tuple[2]\n" "\n" " ", "\n" "func2static(e, arg2, hello, f=2) -> int\n" "\n" - "Parameters:\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" - " f: double\n" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg2: short\n" + "hello: int tuple[2]\n" + "f: double\n" "\n" "func2static(e, arg2, hello) -> int\n" "\n" - "Parameters:\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg2: short\n" + "hello: int tuple[2]\n" "\n" "" ) @@ -221,35 +237,39 @@ check(A.func3static.__doc__, "\n" " func3static(A e, short arg2, Tuple hello, double f=2) -> int\n" "\n" - " Parameters:\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" - " f: double\n" + " Parameters\n" + " ----------\n" + " e: A *\n" + " arg2: short\n" + " hello: int tuple[2]\n" + " f: double\n" "\n" " func3static(A e, short arg2, Tuple hello) -> int\n" "\n" - " Parameters:\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" + " Parameters\n" + " ----------\n" + " e: A *\n" + " arg2: short\n" + " hello: int tuple[2]\n" "\n" " ", "\n" "func3static(A e, short arg2, Tuple hello, double f=2) -> int\n" "\n" - "Parameters:\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" - " f: double\n" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg2: short\n" + "hello: int tuple[2]\n" + "f: double\n" "\n" "func3static(A e, short arg2, Tuple hello) -> int\n" "\n" - "Parameters:\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg2: short\n" + "hello: int tuple[2]\n" "\n" "" ) @@ -268,8 +288,9 @@ if sys.version_info[0:2] > (2, 4): "\n" "A_variable_c_get(self) -> int\n" "\n" - "Parameters:\n" - " self: A *\n" + "Parameters\n" + "----------\n" + "self: A *\n" "\n", "A.variable_c" ) @@ -277,14 +298,15 @@ if sys.version_info[0:2] > (2, 4): "\n" "A_variable_d_get(A self) -> int\n" "\n" - "Parameters:\n" - " self: A *\n" + "Parameters\n" + "----------\n" + "self: A *\n" "\n", "A.variable_d" ) check(B.__doc__, - "Proxy of C++ B class", + "Proxy of C++ B class.", "::B" ) check(C.__init__.__doc__, "__init__(self, a, b, h) -> C", None, skip) @@ -294,10 +316,11 @@ check(E.__init__.__doc__, "\n" " __init__(self, a, b, h) -> E\n" "\n" - " Parameters:\n" - " a: special comment for parameter a\n" - " b: another special comment for parameter b\n" - " h: enum Hola\n" + " Parameters\n" + " ----------\n" + " a: special comment for parameter a\n" + " b: another special comment for parameter b\n" + " h: enum Hola\n" "\n" " ", None, skip ) @@ -305,10 +328,11 @@ check(F.__init__.__doc__, "\n" " __init__(F self, int a, int b, Hola h) -> F\n" "\n" - " Parameters:\n" - " a: special comment for parameter a\n" - " b: another special comment for parameter b\n" - " h: enum Hola\n" + " Parameters\n" + " ----------\n" + " a: special comment for parameter a\n" + " b: another special comment for parameter b\n" + " h: enum Hola\n" "\n" " ", None, skip ) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 5670d9581..362a40929 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -799,7 +799,11 @@ public: Swig_register_filebyname("python", f_shadow); if (mod_docstring && Len(mod_docstring)) { - Printv(f_shadow, "\"\"\"\n", mod_docstring, "\n\"\"\"\n\n", NIL); + const char *triple_double = "\"\"\""; + // follow PEP257 rules: https://www.python.org/dev/peps/pep-0257/ + // reported by pep257: https://github.com/GreenSteam/pep257 + const bool multi_line_ds = Strchr(mod_docstring, '\n'); + Printv(f_shadow, triple_double, multi_line_ds?"\n":"", mod_docstring, multi_line_ds?"\n":"", triple_double, "\n\n", NIL); Delete(mod_docstring); mod_docstring = NULL; } @@ -1795,8 +1799,9 @@ public: Append(doc, name); if (pdoc) { if (!pdocs) - pdocs = NewString("\nParameters:\n"); - Printf(pdocs, " %s\n", pdoc); + // numpydoc style: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt + pdocs = NewString("\nParameters\n----------\n"); + Printf(pdocs, "%s\n", pdoc); } // Write the function annotation if (func_annotation) @@ -1892,9 +1897,9 @@ public: Delete(rname); } else { if (CPlusPlus) { - Printf(doc, "Proxy of C++ %s class", real_classname); + Printf(doc, "Proxy of C++ %s class.", real_classname); } else { - Printf(doc, "Proxy of C %s struct", real_classname); + Printf(doc, "Proxy of C %s struct.", real_classname); } } } @@ -4329,7 +4334,7 @@ public: if (have_docstring(n)) { String *str = docstring(n, AUTODOC_CLASS, tab4); if (str && Len(str)) - Printv(f_shadow, tab4, str, "\n", NIL); + Printv(f_shadow, tab4, str, "\n\n", NIL); } if (!modern) { -- cgit v1.2.1 From 19a20c794bea67fb7e3530da362473c05cf87cad Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 7 Aug 2015 22:23:31 +0100 Subject: Changes entry for numpydoc conforming docstrings. Changes entry for 92328a. Closes #383. --- CHANGES.current | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index f78f6bb48..49d59891c 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,14 @@ See the RELEASENOTES file for a summary of changes in each release. Version 3.0.8 (in progress) =========================== +2015-08-07: xantares + [Python] pep257 & numpydoc conforming docstrings: + - Mono-line module docsstring + - Rewrite autodoc parameters section in numpydoc style: + https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt + - One line summary should end with "." + - Adds a blank line after class docstring + 2015-08-05: vadz [Java] Make (char* STRING, size_t LENGTH) typemaps usable for strings of other types, e.g. "unsigned char*". -- cgit v1.2.1 From 8ac4a8147b2dc2c47c89f9ea3ded933ceee9372f Mon Sep 17 00:00:00 2001 From: Robert Stone Date: Sat, 8 Aug 2015 11:32:55 -0700 Subject: capture the current behavior of perlprimtypes.swg is more detail --- Examples/test-suite/perl5/overload_simple_runme.pl | 39 +++++++++++++++++++- Examples/test-suite/perl5/wrapmacro_runme.pl | 43 +++++++++++++++++++++- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/perl5/overload_simple_runme.pl b/Examples/test-suite/perl5/overload_simple_runme.pl index 624d428c6..57a585a22 100644 --- a/Examples/test-suite/perl5/overload_simple_runme.pl +++ b/Examples/test-suite/perl5/overload_simple_runme.pl @@ -2,7 +2,7 @@ use overload_simple; use vars qw/$DOWARN/; use strict; -use Test::More tests => 75; +use Test::More tests => 97; pass("loaded"); @@ -196,3 +196,40 @@ is(overload_simple::int_object(1), 1, "int_object(1)"); is(overload_simple::int_object(0), 0, "int_object(0)"); is(overload_simple::int_object(undef), 999, "int_object(Spam*)"); is(overload_simple::int_object($s), 999, "int_object(Spam*)"); + +# some of this section is duplication of above tests, but I want to see +# parity with the coverage in wrapmacro_runme.pl. + +sub check { + my($args, $want) = @_; + my($s, $rslt) = defined $want ? ($want, "bar:$want") : ('*boom*', undef); + is(eval("overload_simple::Spam::bar($args)"), $rslt, "bar($args) => $s"); +} + +# normal use patterns +check("11", 'int'); +check("11.0", 'double'); +check("'11'", 'char *'); +check("'11.0'", 'char *'); +check("-13", 'int'); +check("-13.0", 'double'); +check("'-13'", 'char *'); +check("'-13.0'", 'char *'); + +check("' '", 'char *'); +check("' 11 '", 'char *'); +# TypeError explosions +check("\\*STDIN", undef); +check("[]", undef); +check("{}", undef); +check("sub {}", undef); + +# regression cases +check("''", 'char *'); +check("' 11'", 'char *'); +check("' 11.0'", 'char *'); +check("' -11.0'", 'char *'); +check("\"11\x{0}\"", 'char *'); +check("\"\x{0}\"", 'char *'); +check("\"\x{9}11\x{0}this is not eleven.\"", 'char *'); +check("\"\x{9}11.0\x{0}this is also not eleven.\"", 'char *'); diff --git a/Examples/test-suite/perl5/wrapmacro_runme.pl b/Examples/test-suite/perl5/wrapmacro_runme.pl index 8e0154057..f2478b51b 100644 --- a/Examples/test-suite/perl5/wrapmacro_runme.pl +++ b/Examples/test-suite/perl5/wrapmacro_runme.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl use strict; use warnings; -use Test::More tests => 5; +use Test::More tests => 27; BEGIN { use_ok('wrapmacro') } require_ok('wrapmacro'); @@ -12,3 +12,44 @@ my $b = -1; is(wrapmacro::maximum($a,$b), 2); is(wrapmacro::maximum($a/7.0, -$b*256), 256); is(wrapmacro::GUINT16_SWAP_LE_BE_CONSTANT(1), 256); + +# some of this section is duplication of above tests, but I want to see +# parity with the coverage in overload_simple_runme.pl. + +sub check { + my($args, $rslt) = @_; + my $s = defined $rslt ? $rslt : '*boom*'; + is(eval("wrapmacro::maximum($args)"), $rslt, "max($args) => $s"); +} + +# normal use patterns +check("0, 11", 11); +check("0, 11.0", 11); +check("0, '11'", 11); +check("0, '11.0'", 11); +check("11, -13", 11); +check("11, -13.0", 11); +{ local $TODO = 'strtoull() handles /^\s*-\d+$/ amusingly'; +check("11, '-13'", 11); +} +check("11, '-13.0'", 11); + +# TypeError explosions +check("0, ' '", undef); +check("0, ' 11 '", undef); +check("0, \\*STDIN", undef); +check("0, []", undef); +check("0, {}", undef); +check("0, sub {}", undef); + +# regression cases +{ local $TODO = 'strtol() and friends have edge cases we should guard against'; +check("-11, ''", undef); +check("0, ' 11'", undef); +check("0, ' 11.0'", undef); +check("-13, ' -11.0'", undef); +check("0, \"11\x{0}\"", undef); +check("0, \"\x{0}\"", undef); +check("0, \"\x{9}11\x{0}this is not eleven.\"", undef); +check("0, \"\x{9}11.0\x{0}this is also not eleven.\"", undef); +} -- cgit v1.2.1 From 9d1964014176e15411cc91ee160bde3f80c275a6 Mon Sep 17 00:00:00 2001 From: Robert Stone Date: Sat, 8 Aug 2015 11:33:32 -0700 Subject: check ranges in perlprimtype.swg more carefully to avoid clang warnings --- Lib/perl5/perlprimtypes.swg | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Lib/perl5/perlprimtypes.swg b/Lib/perl5/perlprimtypes.swg index d7ac6f94e..6dd18b61f 100644 --- a/Lib/perl5/perlprimtypes.swg +++ b/Lib/perl5/perlprimtypes.swg @@ -37,7 +37,7 @@ SWIGINTERNINLINE SV * SWIG_From_dec(long)(long value) { SV *sv; - if (value >= IV_MIN && value <= IV_MAX) + if (IVSIZE >= sizeof(value) || (value >= IV_MIN && value <= IV_MAX)) sv = newSViv(value); else sv = newSVpvf("%ld", value); @@ -46,20 +46,22 @@ SWIG_From_dec(long)(long value) } %fragment(SWIG_AsVal_frag(long),"header", + fragment="", + fragment="", fragment="SWIG_CanCastAsInteger") { SWIGINTERN int SWIG_AsVal_dec(long)(SV *obj, long* val) { if (SvUOK(obj)) { UV v = SvUV(obj); - if (v <= LONG_MAX) { + if (UVSIZE < sizeof(*val) || v <= LONG_MAX) { if (val) *val = v; return SWIG_OK; } return SWIG_OverflowError; } else if (SvIOK(obj)) { IV v = SvIV(obj); - if (v >= LONG_MIN && v <= LONG_MAX) { + if (IVSIZE <= sizeof(*val) || (v >= LONG_MIN && v <= LONG_MAX)) { if(val) *val = v; return SWIG_OK; } @@ -102,7 +104,7 @@ SWIGINTERNINLINE SV * SWIG_From_dec(unsigned long)(unsigned long value) { SV *sv; - if (value <= UV_MAX) + if (UVSIZE >= sizeof(value) || value <= UV_MAX) sv = newSVuv(value); else sv = newSVpvf("%lu", value); @@ -111,20 +113,22 @@ SWIG_From_dec(unsigned long)(unsigned long value) } %fragment(SWIG_AsVal_frag(unsigned long),"header", + fragment="", + fragment="", fragment="SWIG_CanCastAsInteger") { SWIGINTERN int SWIG_AsVal_dec(unsigned long)(SV *obj, unsigned long *val) { if (SvUOK(obj)) { UV v = SvUV(obj); - if (v <= ULONG_MAX) { + if (UVSIZE <= sizeof(*val) || v <= ULONG_MAX) { if (val) *val = v; return SWIG_OK; } return SWIG_OverflowError; } else if (SvIOK(obj)) { IV v = SvIV(obj); - if (v >= 0 && v <= ULONG_MAX) { + if (v >= 0 && (IVSIZE <= sizeof(*val) || v <= ULONG_MAX)) { if (val) *val = v; return SWIG_OK; } @@ -164,13 +168,12 @@ SWIG_AsVal_dec(unsigned long)(SV *obj, unsigned long *val) %fragment(SWIG_From_frag(long long),"header", fragment=SWIG_From_frag(long), - fragment="", fragment="") { SWIGINTERNINLINE SV * SWIG_From_dec(long long)(long long value) { SV *sv; - if (value >= IV_MIN && value <= IV_MAX) + if (IVSIZE >= sizeof(value) || (value >= IV_MIN && value <= IV_MAX)) sv = newSViv((IV)(value)); else { //sv = newSVpvf("%lld", value); doesn't work in non 64bit Perl @@ -192,14 +195,15 @@ SWIG_AsVal_dec(long long)(SV *obj, long long *val) { if (SvUOK(obj)) { UV v = SvUV(obj); - if (v < LLONG_MAX) { + /* pretty sure this could allow v == LLONG MAX */ + if (UVSIZE < sizeof(*val) || v < LLONG_MAX) { if (val) *val = v; return SWIG_OK; } return SWIG_OverflowError; } else if (SvIOK(obj)) { IV v = SvIV(obj); - if (v >= LLONG_MIN && v <= LLONG_MAX) { + if (IVSIZE <= sizeof(*val) || (v >= LLONG_MIN && v <= LLONG_MAX)) { if (val) *val = v; return SWIG_OK; } @@ -241,13 +245,12 @@ SWIG_AsVal_dec(long long)(SV *obj, long long *val) %fragment(SWIG_From_frag(unsigned long long),"header", fragment=SWIG_From_frag(long long), - fragment="", fragment="") { SWIGINTERNINLINE SV * SWIG_From_dec(unsigned long long)(unsigned long long value) { SV *sv; - if (value <= UV_MAX) + if (UVSIZE >= sizeof(value) || value <= UV_MAX) sv = newSVuv((UV)(value)); else { //sv = newSVpvf("%llu", value); doesn't work in non 64bit Perl @@ -267,11 +270,13 @@ SWIGINTERN int SWIG_AsVal_dec(unsigned long long)(SV *obj, unsigned long long *val) { if (SvUOK(obj)) { + /* pretty sure this should be conditional on + * (UVSIZE <= sizeof(*val) || v <= ULLONG_MAX) */ if (val) *val = SvUV(obj); return SWIG_OK; } else if (SvIOK(obj)) { IV v = SvIV(obj); - if (v >= 0 && v <= ULLONG_MAX) { + if (v >= 0 && (IVSIZE <= sizeof(*val) || v <= ULLONG_MAX)) { if (val) *val = v; return SWIG_OK; } else { -- cgit v1.2.1 From 96e282b791ffbf9b9d6d3a1740945f14438f42cd Mon Sep 17 00:00:00 2001 From: Robert Stone Date: Sat, 8 Aug 2015 13:21:24 -0700 Subject: update CHANGES.current --- CHANGES.current | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 49d59891c..8c269f295 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,9 @@ See the RELEASENOTES file for a summary of changes in each release. Version 3.0.8 (in progress) =========================== +2015-08-07: talby + [Perl] tidy -Wtautological-constant-out-of-range-compare warnings when building generated code under clang + 2015-08-07: xantares [Python] pep257 & numpydoc conforming docstrings: - Mono-line module docsstring -- cgit v1.2.1 From a941e5b605670a8b4686cec5f0d87562846552e2 Mon Sep 17 00:00:00 2001 From: Michael Schaller Date: Sat, 8 Aug 2015 19:44:41 +0200 Subject: [Go] Revert commit 5e88857 to undelete the 'callback' and 'extend' examples. The 'callback' and 'extend' examples were presumed to be obsoleted by the new 'director' example. The examples are helpful though to have similar examples across target languages and hence the commit @5e88857 which removed these examples got reverted. --- Examples/go/callback/Makefile | 16 ++++++++ Examples/go/callback/callback.cxx | 4 ++ Examples/go/callback/example.h | 23 +++++++++++ Examples/go/callback/example.i | 11 ++++++ Examples/go/callback/index.html | 81 +++++++++++++++++++++++++++++++++++++++ Examples/go/callback/runme.go | 41 ++++++++++++++++++++ Examples/go/check.list | 2 + Examples/go/extend/Makefile | 16 ++++++++ Examples/go/extend/example.h | 56 +++++++++++++++++++++++++++ Examples/go/extend/example.i | 15 ++++++++ Examples/go/extend/extend.cxx | 4 ++ Examples/go/extend/index.html | 27 +++++++++++++ Examples/go/extend/runme.go | 76 ++++++++++++++++++++++++++++++++++++ Examples/go/index.html | 3 +- 14 files changed, 374 insertions(+), 1 deletion(-) create mode 100644 Examples/go/callback/Makefile create mode 100644 Examples/go/callback/callback.cxx create mode 100644 Examples/go/callback/example.h create mode 100644 Examples/go/callback/example.i create mode 100644 Examples/go/callback/index.html create mode 100644 Examples/go/callback/runme.go create mode 100644 Examples/go/extend/Makefile create mode 100644 Examples/go/extend/example.h create mode 100644 Examples/go/extend/example.i create mode 100644 Examples/go/extend/extend.cxx create mode 100644 Examples/go/extend/index.html create mode 100644 Examples/go/extend/runme.go diff --git a/Examples/go/callback/Makefile b/Examples/go/callback/Makefile new file mode 100644 index 000000000..bf5275f14 --- /dev/null +++ b/Examples/go/callback/Makefile @@ -0,0 +1,16 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = callback.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/callback/callback.cxx b/Examples/go/callback/callback.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/go/callback/callback.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/go/callback/example.h b/Examples/go/callback/example.h new file mode 100644 index 000000000..1a0e8c432 --- /dev/null +++ b/Examples/go/callback/example.h @@ -0,0 +1,23 @@ +/* File : example.h */ + +#include +#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/go/callback/example.i b/Examples/go/callback/example.i new file mode 100644 index 000000000..cf61ef9d2 --- /dev/null +++ b/Examples/go/callback/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +/* turn on director wrapping Callback */ +%feature("director") Callback; + +%include "example.h" + diff --git a/Examples/go/callback/index.html b/Examples/go/callback/index.html new file mode 100644 index 000000000..b053cf547 --- /dev/null +++ b/Examples/go/callback/index.html @@ -0,0 +1,81 @@ + + +SWIG:Examples:go:callback + + + + + +SWIG/Examples/go/callback/ +
    + +

    Implementing C++ callbacks in Go

    + +

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

    + +

    +Because Go and C++ use inheritance differently, you must call a +different function to create a class which uses callbacks. Instead of +calling the usual constructor function whose name is New +followed by the capitalized name of the class, you call a function +named NewDirector followed by the capitalized name of the +class. +

    + +

    +The first argument to the NewDirector function is an instance +of a type. The NewDirector function will return an interface +value as usual. However, when calling any method on the returned +value, the program will first check whether the value passed +to NewDirector implements that method. If it does, the +method will be called in Go. This is true whether the method is +called from Go code or C++ code. +

    + +

    +Note that the Go code will be called with just the Go value, not the +C++ value. If the Go code needs to call a C++ method on itself, you +need to get a copy of the C++ object. This is typically done as +follows: + +

    +
    +type Child struct { abi Parent }
    +func (p *Child) ChildMethod() {
    +	p.abi.ParentMethod()
    +}
    +func f() {
    +	p := &Child{nil}
    +	d := NewDirectorParent(p)
    +	p.abi = d
    +	...
    +}
    +
    +
    + +In other words, we first create the Go value. We pass that to +the NewDirector function to create the C++ value; this C++ +value will be created with an association to the Go value. We then +store the C++ value in the Go value, giving us the reverse +association. That permits us to call parent methods from the child. + +

    + +

    +To delete a director object, use the function DeleteDirector +followed by the capitalized name of the class. +

    + +

    +

    + +
    + + diff --git a/Examples/go/callback/runme.go b/Examples/go/callback/runme.go new file mode 100644 index 000000000..2eef77fdb --- /dev/null +++ b/Examples/go/callback/runme.go @@ -0,0 +1,41 @@ +package main + +import ( + . "./example" + "fmt" +) + +func main() { + fmt.Println("Adding and calling a normal C++ callback") + fmt.Println("----------------------------------------") + + caller := NewCaller() + callback := NewCallback() + + caller.SetCallback(callback) + caller.Call() + caller.DelCallback() + + callback = NewDirectorCallback(new(GoCallback)) + + fmt.Println() + fmt.Println("Adding and calling a Go callback") + fmt.Println("------------------------------------") + + caller.SetCallback(callback) + caller.Call() + caller.DelCallback() + + // Test that a double delete does not occur as the object has + // already been deleted from the C++ layer. + DeleteDirectorCallback(callback) + + fmt.Println() + fmt.Println("Go exit") +} + +type GoCallback struct{} + +func (p *GoCallback) Run() { + fmt.Println("GoCallback.Run") +} diff --git a/Examples/go/check.list b/Examples/go/check.list index 25322352a..b3f34b306 100644 --- a/Examples/go/check.list +++ b/Examples/go/check.list @@ -1,8 +1,10 @@ # see top-level Makefile.in +callback class constants director enum +extend funcptr multimap pointer diff --git a/Examples/go/extend/Makefile b/Examples/go/extend/Makefile new file mode 100644 index 000000000..290694210 --- /dev/null +++ b/Examples/go/extend/Makefile @@ -0,0 +1,16 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = extend.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/extend/example.h b/Examples/go/extend/example.h new file mode 100644 index 000000000..ca1aed28f --- /dev/null +++ b/Examples/go/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", (void *)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/go/extend/example.i b/Examples/go/extend/example.i new file mode 100644 index 000000000..c8ec32e09 --- /dev/null +++ b/Examples/go/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/go/extend/extend.cxx b/Examples/go/extend/extend.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/go/extend/extend.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/go/extend/index.html b/Examples/go/extend/index.html new file mode 100644 index 000000000..471fa9cdc --- /dev/null +++ b/Examples/go/extend/index.html @@ -0,0 +1,27 @@ + + +SWIG:Examples:go:extend + + + + + +SWIG/Examples/go/extend/ +
    + +

    Extending a simple C++ class in Go

    + +

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

    +

    + +
    + + diff --git a/Examples/go/extend/runme.go b/Examples/go/extend/runme.go new file mode 100644 index 000000000..770e27802 --- /dev/null +++ b/Examples/go/extend/runme.go @@ -0,0 +1,76 @@ +// This file illustrates the cross language polymorphism using directors. + +package main + +import ( + . "./example" + "fmt" +) + +type CEO struct{} + +func (p *CEO) GetPosition() string { + return "CEO" +} + +func main() { + // Create an instance of CEO, a class derived from the Go + // proxy of the underlying C++ class. The calls to getName() + // and getPosition() are standard, the call to getTitle() uses + // the director wrappers to call CEO.getPosition(). + + e := NewDirectorManager(new(CEO), "Alice") + fmt.Println(e.GetName(), " is a ", e.GetPosition()) + fmt.Println("Just call her \"", e.GetTitle(), "\"") + fmt.Println("----------------------") + + // 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 := NewEmployeeList() + + // EmployeeList owns its items, so we must surrender ownership + // of objects we add. + // e.DisownMemory() + list.AddEmployee(e) + fmt.Println("----------------------") + + // 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, all methods + // resolve in C++. For item 3, our CEO, GetTitle calls + // GetPosition which resolves in Go. The call to GetPosition + // is slightly different, however, because of the overridden + // GetPosition() call, since now the object reference has been + // "laundered" by passing through EmployeeList as an + // Employee*. Previously, Go resolved the call immediately in + // CEO, but now Go thinks the object is an instance of class + // Employee. So the call passes through the Employee proxy + // class and on to the C wrappers and C++ director, eventually + // ending up back at the Java 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 Java implementation + // in CEO. All this routing takes place transparently. + + fmt.Println("(position, title) for items 0-3:") + + fmt.Println(" ", list.Get_item(0).GetPosition(), ", \"", list.Get_item(0).GetTitle(), "\"") + fmt.Println(" ", list.Get_item(1).GetPosition(), ", \"", list.Get_item(1).GetTitle(), "\"") + fmt.Println(" ", list.Get_item(2).GetPosition(), ", \"", list.Get_item(2).GetTitle(), "\"") + fmt.Println(" ", list.Get_item(3).GetPosition(), ", \"", list.Get_item(3).GetTitle(), "\"") + fmt.Println("----------------------") + + // Time to delete the EmployeeList, which will delete all the + // Employee* items it contains. The last item is our CEO, + // which gets destroyed as well. + DeleteEmployeeList(list) + fmt.Println("----------------------") + + // All done. + + fmt.Println("Go exit") +} diff --git a/Examples/go/index.html b/Examples/go/index.html index b7d7017d3..ed6a6b707 100644 --- a/Examples/go/index.html +++ b/Examples/go/index.html @@ -21,7 +21,8 @@ certain C declarations are turned into constants.
  • pointer. Simple pointer handling.
  • funcptr. Pointers to functions.
  • template. C++ templates. -
  • director. Example how to utilize the director feature. +
  • callback. C++ callbacks using directors. +
  • extend. Polymorphism using directors.

    Compilation Issues

    -- cgit v1.2.1 From 85037c3a33f4943afdcdaf0bc49b3f0433165f05 Mon Sep 17 00:00:00 2001 From: Michael Schaller Date: Sun, 9 Aug 2015 14:03:19 +0200 Subject: [Go] Updated the 'callback' and 'extend' examples to match the 'director' one. After the documentation update on how to utilize the director feature with commit @17b1c1c the 'callback' and 'extend' examples needed an update as well. --- Examples/go/callback/Makefile | 12 +++++-- Examples/go/callback/example.h | 1 - Examples/go/callback/gocallback.go | 41 ++++++++++++++++++++++++ Examples/go/callback/index.html | 64 +++++--------------------------------- Examples/go/callback/runme.go | 16 +++------- Examples/go/director/Makefile | 11 ++++--- Examples/go/extend/Makefile | 12 +++++-- Examples/go/extend/ceo.go | 37 ++++++++++++++++++++++ Examples/go/extend/example.h | 2 +- Examples/go/extend/index.html | 13 +++++--- Examples/go/extend/runme.go | 20 +++--------- Examples/go/index.html | 1 + 12 files changed, 130 insertions(+), 100 deletions(-) create mode 100644 Examples/go/callback/gocallback.go create mode 100644 Examples/go/extend/ceo.go diff --git a/Examples/go/callback/Makefile b/Examples/go/callback/Makefile index bf5275f14..7441e09bd 100644 --- a/Examples/go/callback/Makefile +++ b/Examples/go/callback/Makefile @@ -1,6 +1,7 @@ TOP = ../.. SWIG = $(TOP)/../preinst-swig CXXSRCS = callback.cxx +GOSRCS = gocallback.go TARGET = example INTERFACE = example.i SWIGOPT = @@ -9,8 +10,15 @@ check: build $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run build: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ - SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + if [ -n '$(SRCDIR)' ]; then \ + cp $(GOSRCS:%=$(SRCDIR)/%) .; \ + fi + @# Note: example.go gets generated by SWIG + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' GOSRCS='example.go $(GOSRCS)' \ + SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp clean: + if [ -n '$(SRCDIR)' ]; then \ + rm $(GOSRCS) || true; \ + fi $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/callback/example.h b/Examples/go/callback/example.h index 1a0e8c432..74ddad954 100644 --- a/Examples/go/callback/example.h +++ b/Examples/go/callback/example.h @@ -20,4 +20,3 @@ public: void setCallback(Callback *cb) { delCallback(); _callback = cb; } void call() { if (_callback) _callback->run(); } }; - diff --git a/Examples/go/callback/gocallback.go b/Examples/go/callback/gocallback.go new file mode 100644 index 000000000..20fd0627a --- /dev/null +++ b/Examples/go/callback/gocallback.go @@ -0,0 +1,41 @@ +package example + +import ( + "fmt" +) + +type GoCallback interface { + Callback + deleteCallback() + IsGoCallback() +} + +type goCallback struct { + Callback +} + +func (p *goCallback) deleteCallback() { + DeleteDirectorCallback(p.Callback) +} + +func (p *goCallback) IsGoCallback() {} + +type overwrittenMethodsOnCallback struct { + p Callback +} + +func NewGoCallback() GoCallback { + om := &overwrittenMethodsOnCallback{} + p := NewDirectorCallback(om) + om.p = p + + return &goCallback{Callback: p} +} + +func DeleteGoCallback(p GoCallback) { + p.deleteCallback() +} + +func (p *goCallback) Run() { + fmt.Println("GoCallback.Run") +} diff --git a/Examples/go/callback/index.html b/Examples/go/callback/index.html index b053cf547..9a53065b0 100644 --- a/Examples/go/callback/index.html +++ b/Examples/go/callback/index.html @@ -12,67 +12,17 @@

    Implementing C++ callbacks in Go

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

    - -

    -Because Go and C++ use inheritance differently, you must call a -different function to create a class which uses callbacks. Instead of -calling the usual constructor function whose name is New -followed by the capitalized name of the class, you call a function -named NewDirector followed by the capitalized name of the -class. -

    - -

    -The first argument to the NewDirector function is an instance -of a type. The NewDirector function will return an interface -value as usual. However, when calling any method on the returned -value, the program will first check whether the value passed -to NewDirector implements that method. If it does, the -method will be called in Go. This is true whether the method is -called from Go code or C++ code. -

    - -

    -Note that the Go code will be called with just the Go value, not the -C++ value. If the Go code needs to call a C++ method on itself, you -need to get a copy of the C++ object. This is typically done as -follows: - -

    -
    -type Child struct { abi Parent }
    -func (p *Child) ChildMethod() {
    -	p.abi.ParentMethod()
    -}
    -func f() {
    -	p := &Child{nil}
    -	d := NewDirectorParent(p)
    -	p.abi = d
    -	...
    -}
    -
    -
    - -In other words, we first create the Go value. We pass that to -the NewDirector function to create the C++ value; this C++ -value will be created with an association to the Go value. We then -store the C++ value in the Go value, giving us the reverse -association. That permits us to call parent methods from the child. - -

    - -

    -To delete a director object, use the function DeleteDirector -followed by the capitalized name of the class. +This example illustrates how to use directors to implement C++ callbacks in Go. +See the Go Director +Classes documentation subsection for an in-depth explanation how to use the +director feature.

    diff --git a/Examples/go/callback/runme.go b/Examples/go/callback/runme.go index 2eef77fdb..03ab0c5e2 100644 --- a/Examples/go/callback/runme.go +++ b/Examples/go/callback/runme.go @@ -16,26 +16,18 @@ func main() { caller.Call() caller.DelCallback() - callback = NewDirectorCallback(new(GoCallback)) + go_callback := NewGoCallback() fmt.Println() fmt.Println("Adding and calling a Go callback") - fmt.Println("------------------------------------") + fmt.Println("--------------------------------") - caller.SetCallback(callback) + caller.SetCallback(go_callback) caller.Call() caller.DelCallback() - // Test that a double delete does not occur as the object has - // already been deleted from the C++ layer. - DeleteDirectorCallback(callback) + DeleteGoCallback(go_callback) fmt.Println() fmt.Println("Go exit") } - -type GoCallback struct{} - -func (p *GoCallback) Run() { - fmt.Println("GoCallback.Run") -} diff --git a/Examples/go/director/Makefile b/Examples/go/director/Makefile index 84de5855d..2e9e87b89 100644 --- a/Examples/go/director/Makefile +++ b/Examples/go/director/Makefile @@ -1,7 +1,7 @@ TOP = ../.. SWIG = $(TOP)/../preinst-swig -CXXSRCS = -GOSRCS = example.go director.go # example.go gets generated by SWIG +CXXSRCS = +GOSRCS = director.go TARGET = example INTERFACE = example.i SWIGOPT = @@ -11,13 +11,14 @@ check: build build: if [ -n '$(SRCDIR)' ]; then \ - cp $(SRCDIR)/director.go .; \ + cp $(GOSRCS:%=$(SRCDIR)/%) .; \ fi - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' GOSRCS='$(GOSRCS)' \ + @# Note: example.go gets generated by SWIG + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' GOSRCS='example.go $(GOSRCS)' \ SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp clean: if [ -n '$(SRCDIR)' ]; then \ - rm director.go || true; \ + rm $(GOSRCS) || true; \ fi $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/extend/Makefile b/Examples/go/extend/Makefile index 290694210..a9f2d8d7d 100644 --- a/Examples/go/extend/Makefile +++ b/Examples/go/extend/Makefile @@ -1,6 +1,7 @@ TOP = ../.. SWIG = $(TOP)/../preinst-swig CXXSRCS = extend.cxx +GOSRCS = ceo.go TARGET = example INTERFACE = example.i SWIGOPT = @@ -9,8 +10,15 @@ check: build $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run build: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ - SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + if [ -n '$(SRCDIR)' ]; then \ + cp $(GOSRCS:%=$(SRCDIR)/%) .; \ + fi + @# Note: example.go gets generated by SWIG + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' GOSRCS='example.go $(GOSRCS)' \ + SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp clean: + if [ -n '$(SRCDIR)' ]; then \ + rm $(GOSRCS) || true; \ + fi $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/extend/ceo.go b/Examples/go/extend/ceo.go new file mode 100644 index 000000000..8f00c92f2 --- /dev/null +++ b/Examples/go/extend/ceo.go @@ -0,0 +1,37 @@ +package example + +type CEO interface { + Manager + deleteManager() + IsCEO() +} + +type ceo struct { + Manager +} + +func (p *ceo) deleteManager() { + DeleteDirectorManager(p.Manager) +} + +func (p *ceo) IsCEO() {} + +type overwrittenMethodsOnManager struct { + p Manager +} + +func NewCEO(name string) CEO { + om := &overwrittenMethodsOnManager{} + p := NewDirectorManager(om, name) + om.p = p + + return &ceo{Manager: p} +} + +func DeleteCEO(p CEO) { + p.deleteManager() +} + +func (p *ceo) GetPosition() string { + return "CEO" +} diff --git a/Examples/go/extend/example.h b/Examples/go/extend/example.h index ca1aed28f..0c3b721bd 100644 --- a/Examples/go/extend/example.h +++ b/Examples/go/extend/example.h @@ -44,7 +44,7 @@ public: const Employee *get_item(int i) { return list[i]; } - ~EmployeeList() { + ~EmployeeList() { std::vector::iterator i; std::cout << "~EmployeeList, deleting " << list.size() << " employees." << std::endl; for (i=list.begin(); i!=list.end(); i++) { diff --git a/Examples/go/extend/index.html b/Examples/go/extend/index.html index 471fa9cdc..31788b2aa 100644 --- a/Examples/go/extend/index.html +++ b/Examples/go/extend/index.html @@ -12,13 +12,16 @@

    Extending a simple C++ class in Go

    -This example illustrates the extending of a C++ class with cross -language polymorphism. - +This example illustrates how to inherit from a C++ class in Go. +See the Go Director +Classes documentation subsection for an in-depth explanation how to use the +director feature.

    +

      -
    • example.h. Header file containing some enums. -
    • example.i. Interface file. +
    • ceo.go. Go source with the definition of the CEO class. +
    • example.h. Header with the definition of the Employee, Manager and EmployeeList classes. +
    • example.i. SWIG interface file.
    • runme.go. Sample Go program.
    diff --git a/Examples/go/extend/runme.go b/Examples/go/extend/runme.go index 770e27802..a56968937 100644 --- a/Examples/go/extend/runme.go +++ b/Examples/go/extend/runme.go @@ -7,19 +7,12 @@ import ( "fmt" ) -type CEO struct{} - -func (p *CEO) GetPosition() string { - return "CEO" -} - func main() { // Create an instance of CEO, a class derived from the Go // proxy of the underlying C++ class. The calls to getName() // and getPosition() are standard, the call to getTitle() uses // the director wrappers to call CEO.getPosition(). - - e := NewDirectorManager(new(CEO), "Alice") + e := NewCEO("Alice") fmt.Println(e.GetName(), " is a ", e.GetPosition()) fmt.Println("Just call her \"", e.GetTitle(), "\"") fmt.Println("----------------------") @@ -27,7 +20,6 @@ func main() { // 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 := NewEmployeeList() // EmployeeList owns its items, so we must surrender ownership @@ -49,15 +41,13 @@ func main() { // CEO, but now Go thinks the object is an instance of class // Employee. So the call passes through the Employee proxy // class and on to the C wrappers and C++ director, eventually - // ending up back at the Java CEO implementation of + // ending up back at the Go 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 Java implementation + // through the C++ director class to the Go implementation // in CEO. All this routing takes place transparently. - fmt.Println("(position, title) for items 0-3:") - fmt.Println(" ", list.Get_item(0).GetPosition(), ", \"", list.Get_item(0).GetTitle(), "\"") fmt.Println(" ", list.Get_item(1).GetPosition(), ", \"", list.Get_item(1).GetTitle(), "\"") fmt.Println(" ", list.Get_item(2).GetPosition(), ", \"", list.Get_item(2).GetTitle(), "\"") @@ -66,11 +56,11 @@ func main() { // Time to delete the EmployeeList, which will delete all the // Employee* items it contains. The last item is our CEO, - // which gets destroyed as well. + // which gets destroyed as well and hence there is no need to + // call DeleteCEO. DeleteEmployeeList(list) fmt.Println("----------------------") // All done. - fmt.Println("Go exit") } diff --git a/Examples/go/index.html b/Examples/go/index.html index ed6a6b707..467f4ecb7 100644 --- a/Examples/go/index.html +++ b/Examples/go/index.html @@ -23,6 +23,7 @@ certain C declarations are turned into constants.
  • template. C++ templates.
  • callback. C++ callbacks using directors.
  • extend. Polymorphism using directors. +
  • director. Example how to utilize the director feature.

    Compilation Issues

    -- cgit v1.2.1 From 608ef60ecf7774533b3344622be5b8df64bf133e Mon Sep 17 00:00:00 2001 From: Michael Schaller Date: Sun, 9 Aug 2015 14:32:23 +0200 Subject: [Go] Renamed 'FooBarAbs' to 'FooBarAbstract' in the documentation and examples. --- Doc/Manual/Go.html | 196 ++++++++++++++++++++------------------- Examples/go/director/director.go | 74 ++++++++------- Examples/go/director/director.h | 10 +- Examples/go/director/example.i | 2 +- Examples/go/director/index.html | 2 +- 5 files changed, 144 insertions(+), 140 deletions(-) diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html index c008ef22c..ca12410ad 100644 --- a/Doc/Manual/Go.html +++ b/Doc/Manual/Go.html @@ -606,22 +606,22 @@ completely to avoid common pitfalls with directors in Go.

    23.4.7.1 Example C++ code

    -The step by step guide is based on two example C++ classes. FooBarAbs is an -abstract C++ class and the FooBarCpp class inherits from it. This guide +The step by step guide is based on two example C++ classes. FooBarAbstract is +an abstract C++ class and the FooBarCpp class inherits from it. This guide explains how to implement a FooBarGo class similar to the FooBarCpp class.

    -FooBarAbs abstract C++ class: +FooBarAbstract abstract C++ class:

    -class FooBarAbs
    +class FooBarAbstract
     {
     public:
    -	FooBarAbs() {};
    -	virtual ~FooBarAbs() {};
    +	FooBarAbstract() {};
    +	virtual ~FooBarAbstract() {};
     
     	std::string FooBar() {
     		return this->Foo() + ", " + this->Bar();
    @@ -643,11 +643,11 @@ protected:
     
     
    -class FooBarCpp : public FooBarAbs
    +class FooBarCpp : public FooBarAbstract
     {
     protected:
     	virtual std::string Foo() {
    -		return "C++ " + FooBarAbs::Foo();
    +		return "C++ " + FooBarAbstract::Foo();
     	}
     
     	virtual std::string Bar() {
    @@ -691,14 +691,14 @@ directive, like this:
     
     

    Second, you must use the %feature("director") directive to tell SWIG which -classes should get directors. In the example the FooBarAbs class needs the +classes should get directors. In the example the FooBarAbstract class needs the director feature enabled so that the FooBarGo class can inherit from it, like this:

    -%feature("director") FooBarAbs;
    +%feature("director") FooBarAbstract;
     
    @@ -782,21 +782,21 @@ As an example see part of the FooBarGo class:
    -type overwrittenMethodsOnFooBarAbs struct {
    -	fb FooBarAbs
    +type overwrittenMethodsOnFooBarAbstract struct {
    +	fb FooBarAbstract
     }
     
    -func (om *overwrittenMethodsOnFooBarAbs) Foo() string {
    +func (om *overwrittenMethodsOnFooBarAbstract) Foo() string {
     	...
     }
     
    -func (om *overwrittenMethodsOnFooBarAbs) Bar() string {
    +func (om *overwrittenMethodsOnFooBarAbstract) Bar() string {
     	...
     }
     
     func NewFooBarGo() FooBarGo {
    -	om := &overwrittenMethodsOnFooBarAbs{}
    -	fb := NewDirectorFooBarAbs(om)
    +	om := &overwrittenMethodsOnFooBarAbstract{}
    +	fb := NewDirectorFooBarAbstract(om)
     	om.fb = fb
     	...
     }
    @@ -806,25 +806,25 @@ func NewFooBarGo() FooBarGo {
     

    The complete example, including the FooBarGoo class implementation, can be found in the end of the guide. In -this part of the example the virtual methods FooBarAbs::Foo and -FooBarAbs::Bar have been overwritten with Go methods similarly to how -the FooBarAbs virtual methods are overwritten by the FooBarCpp -class. +this part of the example the virtual methods FooBarAbstract::Foo and +FooBarAbstract::Bar have been overwritten with Go methods similarly to +how the FooBarAbstract virtual methods are overwritten by the +FooBarCpp class.

    The DirectorInterface in the example is implemented by the -overwrittenMethodsOnFooBarAbs Go struct type. A pointer to a -overwrittenMethodsOnFooBarAbs struct instance will be given to the -NewDirectorFooBarAbs constructor function. The constructor return -value implements the FooBarAbs interface. -overwrittenMethodsOnFooBarAbs could in theory be any Go type but in -practice a struct is used as it typically contains at least a value of the +overwrittenMethodsOnFooBarAbstract Go struct type. A pointer to a +overwrittenMethodsOnFooBarAbstract struct instance will be given to the +NewDirectorFooBarAbstract constructor function. The constructor return +value implements the FooBarAbstract interface. +overwrittenMethodsOnFooBarAbstract could in theory be any Go type but +in practice a struct is used as it typically contains at least a value of the C++ class interface so that the overwritten methods can use the rest of the C++ class. If the FooBarGo class would receive additional constructor arguments then these would also typically be stored in the -overwrittenMethodsOnFooBarAbs struct so that they can be used by the -Go methods. +overwrittenMethodsOnFooBarAbstract struct so that they can be used by +the Go methods.

    @@ -840,7 +840,7 @@ the method in the base class. This is also the case for the
     virtual std::string Foo() {
    -	return "C++ " + FooBarAbs::Foo();
    +	return "C++ " + FooBarAbstract::Foo();
     }
     
    @@ -853,8 +853,8 @@ The FooBarGo.Foo implementation in the example looks like this:
    -func (om *overwrittenMethodsOnFooBarAbs) Foo() string {
    -	return "Go " + DirectorFooBarAbsFoo(om.fb)
    +func (om *overwrittenMethodsOnFooBarAbstract) Foo() string {
    +	return "Go " + DirectorFooBarAbstractFoo(om.fb)
     }
     
    @@ -887,31 +887,31 @@ this:
     type FooBarGo interface {
    -	FooBarAbs
    -	deleteFooBarAbs()
    +	FooBarAbstract
    +	deleteFooBarAbstract()
     	IsFooBarGo()
     }
     
     type fooBarGo struct {
    -	FooBarAbs
    +	FooBarAbstract
     }
     
    -func (fbgs *fooBarGo) deleteFooBarAbs() {
    -	DeleteDirectorFooBarAbs(fbgs.FooBarAbs)
    +func (fbgs *fooBarGo) deleteFooBarAbstract() {
    +	DeleteDirectorFooBarAbstract(fbgs.FooBarAbstract)
     }
     
     func (fbgs *fooBarGo) IsFooBarGo() {}
     
     func NewFooBarGo() FooBarGo {
    -	om := &overwrittenMethodsOnFooBarAbs{}
    -	fb := NewDirectorFooBarAbs(om)
    +	om := &overwrittenMethodsOnFooBarAbstract{}
    +	fb := NewDirectorFooBarAbstract(om)
     	om.fb = fb
     
    -	return &fooBarGo{FooBarAbs: fb}
    +	return &fooBarGo{FooBarAbstract: fb}
     }
     
     func DeleteFooBarGo(fbg FooBarGo) {
    -	fbg.deleteFooBarAbs()
    +	fbg.deleteFooBarAbstract()
     }
     
    @@ -921,12 +921,12 @@ func DeleteFooBarGo(fbg FooBarGo) { The complete example, including the FooBarGoo class implementation, can be found in the end of the guide. In this part of the example the private fooBarGo struct embeds -FooBarAbs which lets the fooBarGo Go type "inherit" all the -methods of the FooBarAbs C++ class by means of embedding. The public -FooBarGo interface type includes the FooBarAbs interface and -hence FooBarGo can be used as a drop in replacement for -FooBarAbs while the reverse isn't possible and would raise a compile -time error. Furthemore the constructor and destructor functions +FooBarAbstract which lets the fooBarGo Go type "inherit" all the +methods of the FooBarAbstract C++ class by means of embedding. The +public FooBarGo interface type includes the FooBarAbstract +interface and hence FooBarGo can be used as a drop in replacement for +FooBarAbstract while the reverse isn't possible and would raise a +compile time error. Furthemore the constructor and destructor functions NewFooBarGo and DeleteFooBarGo take care of all the director specifics and to the user the class appears as any other SWIG wrapped C++ class. @@ -946,13 +946,13 @@ in the FooBarGo class is here:
    -type overwrittenMethodsOnFooBarAbs struct {
    -	fb FooBarAbs
    +type overwrittenMethodsOnFooBarAbstract struct {
    +	fb FooBarAbstract
     }
     
     func NewFooBarGo() FooBarGo {
    -	om := &overwrittenMethodsOnFooBarAbs{}
    -	fb := NewDirectorFooBarAbs(om) // fb.v = om
    +	om := &overwrittenMethodsOnFooBarAbstract{}
    +	fb := NewDirectorFooBarAbstract(om) // fb.v = om
     	om.fb = fb // Backlink causes cycle as fb.v = om!
     	...
     }
    @@ -963,27 +963,27 @@ func NewFooBarGo() FooBarGo {
     In order to be able to use runtime.SetFinalizer nevertheless the
     finalizer needs to be set on something that isn't in a cycle and that references
     the director object instance.  In the FooBarGo class example the 
    -FooBarAbs director instance can be automatically deleted by setting the
    -finalizer on fooBarGo:
    +FooBarAbstract director instance can be automatically deleted by setting
    +the finalizer on fooBarGo:
     

     type fooBarGo struct {
    -	FooBarAbs
    +	FooBarAbstract
     }
     
    -type overwrittenMethodsOnFooBarAbs struct {
    -	fb FooBarAbs
    +type overwrittenMethodsOnFooBarAbstract struct {
    +	fb FooBarAbstract
     }
     
     func NewFooBarGo() FooBarGo {
    -	om := &overwrittenMethodsOnFooBarAbs{}
    -	fb := NewDirectorFooBarAbs(om)
    +	om := &overwrittenMethodsOnFooBarAbstract{}
    +	fb := NewDirectorFooBarAbstract(om)
     	om.fb = fb // Backlink causes cycle as fb.v = om!
     
    -	fbgs := &fooBarGo{FooBarAbs: fb}
    -	runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs)
    +	fbgs := &fooBarGo{FooBarAbstract: fb}
    +	runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract)
     	return fbgs
     }
     
    @@ -1007,73 +1007,75 @@ The complete and annotated FooBarGo class looks like this:
    -// FooBarGo is a superset of FooBarAbs and hence FooBarGo can be used as a drop
    -// in replacement for FooBarAbs but the reverse causes a compile time error.
    +// FooBarGo is a superset of FooBarAbstract and hence FooBarGo can be used as a
    +// drop in replacement for FooBarAbstract but the reverse causes a compile time
    +// error.
     type FooBarGo interface {
    -	FooBarAbs
    -	deleteFooBarAbs()
    +	FooBarAbstract
    +	deleteFooBarAbstract()
     	IsFooBarGo()
     }
     
    -// Via embedding fooBarGo "inherits" all methods of FooBarAbs.
    +// Via embedding fooBarGo "inherits" all methods of FooBarAbstract.
     type fooBarGo struct {
    -	FooBarAbs
    +	FooBarAbstract
     }
     
    -func (fbgs *fooBarGo) deleteFooBarAbs() {
    -	DeleteDirectorFooBarAbs(fbgs.FooBarAbs)
    +func (fbgs *fooBarGo) deleteFooBarAbstract() {
    +	DeleteDirectorFooBarAbstract(fbgs.FooBarAbstract)
     }
     
    -// The IsFooBarGo method ensures that FooBarGo is a superset of FooBarAbs.
    +// The IsFooBarGo method ensures that FooBarGo is a superset of FooBarAbstract.
     // This is also how the class hierarchy gets represented by the SWIG generated
    -// wrapper code.  For an instance FooBarCpp has the IsFooBarAbs and IsFooBarCpp
    -// methods.
    +// wrapper code.  For an instance FooBarCpp has the IsFooBarAbstract and
    +// IsFooBarCpp methods.
     func (fbgs *fooBarGo) IsFooBarGo() {}
     
     // Go type that defines the DirectorInterface. It contains the Foo and Bar
    -// methods that overwrite the respective virtual C++ methods on FooBarAbs.
    -type overwrittenMethodsOnFooBarAbs struct {
    -	// Backlink to FooBarAbs so that the rest of the class can be used by the
    -	// overridden methods.
    -	fb FooBarAbs
    +// methods that overwrite the respective virtual C++ methods on FooBarAbstract.
    +type overwrittenMethodsOnFooBarAbstract struct {
    +	// Backlink to FooBarAbstract so that the rest of the class can be used by
    +	// the overridden methods.
    +	fb FooBarAbstract
     
     	// If additional constructor arguments have been given they are typically
     	// stored here so that the overriden methods can use them.
     }
     
    -func (om *overwrittenMethodsOnFooBarAbs) Foo() string {
    -	// DirectorFooBarAbsFoo calls the base method FooBarAbs::Foo.
    -	return "Go " + DirectorFooBarAbsFoo(om.fb)
    +func (om *overwrittenMethodsOnFooBarAbstract) Foo() string {
    +	// DirectorFooBarAbstractFoo calls the base method FooBarAbstract::Foo.
    +	return "Go " + DirectorFooBarAbstractFoo(om.fb)
     }
     
    -func (om *overwrittenMethodsOnFooBarAbs) Bar() string {
    +func (om *overwrittenMethodsOnFooBarAbstract) Bar() string {
     	return "Go Bar"
     }
     
     func NewFooBarGo() FooBarGo {
    -	// Instantiate FooBarAbs with selected methods overridden.  The methods that
    -	// will be overwritten are defined on overwrittenMethodsOnFooBarAbs and have
    -	// a compatible signature to the respective virtual C++ methods.
    -	// Furthermore additional constructor arguments will be typically stored in
    -	// the overwrittenMethodsOnFooBarAbs struct.
    -	om := &overwrittenMethodsOnFooBarAbs{}
    -	fb := NewDirectorFooBarAbs(om)
    +	// Instantiate FooBarAbstract with selected methods overridden.  The methods
    +	// that will be overwritten are defined on
    +	// overwrittenMethodsOnFooBarAbstract and have a compatible signature to the
    +	// respective virtual C++ methods. Furthermore additional constructor
    +	// arguments will be typically stored in the
    +	// overwrittenMethodsOnFooBarAbstract struct.
    +	om := &overwrittenMethodsOnFooBarAbstract{}
    +	fb := NewDirectorFooBarAbstract(om)
     	om.fb = fb // Backlink causes cycle as fb.v = om!
     
    -	fbgs := &fooBarGo{FooBarAbs: fb}
    -	// The memory of the FooBarAbs director object instance can be automatically
    -	// freed once the FooBarGo instance is garbage collected by uncommenting the
    -	// following line.  Please make sure to understand the runtime.SetFinalizer
    -	// specific gotchas before doing this.  Furthemore DeleteFooBarGo should be
    -	// deleted if a finalizer is in use or the fooBarGo struct needs additional
    -	// data to prevent double deletion.
    -	// runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs)
    +	fbgs := &fooBarGo{FooBarAbstract: fb}
    +	// The memory of the FooBarAbstract director object instance can be
    +	// automatically freed once the FooBarGo instance is garbage collected by
    +	// uncommenting the following line.  Please make sure to understand the
    +	// runtime.SetFinalizer specific gotchas before doing this.  Furthemore
    +	// DeleteFooBarGo should be deleted if a finalizer is in use or the fooBarGo
    +	// struct needs additional data to prevent double deletion.
    +	// runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract)
     	return fbgs
     }
     
     // Recommended to be removed if runtime.SetFinalizer is in use.
     func DeleteFooBarGo(fbg FooBarGo) {
    -	fbg.deleteFooBarAbs()
    +	fbg.deleteFooBarAbstract()
     }
     
    @@ -1094,11 +1096,11 @@ For comparison the FooBarCpp class looks like this:
    -class FooBarCpp : public FooBarAbs
    +class FooBarCpp : public FooBarAbstract
     {
     protected:
     	virtual std::string Foo() {
    -		return "C++ " + FooBarAbs::Foo();
    +		return "C++ " + FooBarAbstract::Foo();
     	}
     
     	virtual std::string Bar() {
    diff --git a/Examples/go/director/director.go b/Examples/go/director/director.go
    index a5078fe58..4f99bfc6d 100644
    --- a/Examples/go/director/director.go
    +++ b/Examples/go/director/director.go
    @@ -1,70 +1,72 @@
     package example
     
    -// FooBarGo is a superset of FooBarAbs and hence FooBarGo can be used as a drop
    -// in replacement for FooBarAbs but the reverse causes a compile time error.
    +// FooBarGo is a superset of FooBarAbstract and hence FooBarGo can be used as a
    +// drop in replacement for FooBarAbstract but the reverse causes a compile time
    +// error.
     type FooBarGo interface {
    -	FooBarAbs
    -	deleteFooBarAbs()
    +	FooBarAbstract
    +	deleteFooBarAbstract()
     	IsFooBarGo()
     }
     
    -// Via embedding fooBarGo "inherits" all methods of FooBarAbs.
    +// Via embedding fooBarGo "inherits" all methods of FooBarAbstract.
     type fooBarGo struct {
    -	FooBarAbs
    +	FooBarAbstract
     }
     
    -func (fbgs *fooBarGo) deleteFooBarAbs() {
    -	DeleteDirectorFooBarAbs(fbgs.FooBarAbs)
    +func (fbgs *fooBarGo) deleteFooBarAbstract() {
    +	DeleteDirectorFooBarAbstract(fbgs.FooBarAbstract)
     }
     
    -// The IsFooBarGo method ensures that FooBarGo is a superset of FooBarAbs.
    +// The IsFooBarGo method ensures that FooBarGo is a superset of FooBarAbstract.
     // This is also how the class hierarchy gets represented by the SWIG generated
    -// wrapper code.  For an instance FooBarCpp has the IsFooBarAbs and IsFooBarCpp
    -// methods.
    +// wrapper code.  For an instance FooBarCpp has the IsFooBarAbstract and
    +// IsFooBarCpp methods.
     func (fbgs *fooBarGo) IsFooBarGo() {}
     
     // Go type that defines the DirectorInterface. It contains the Foo and Bar
    -// methods that overwrite the respective virtual C++ methods on FooBarAbs.
    -type overwrittenMethodsOnFooBarAbs struct {
    -	// Backlink to FooBarAbs so that the rest of the class can be used by the
    -	// overridden methods.
    -	fb FooBarAbs
    +// methods that overwrite the respective virtual C++ methods on FooBarAbstract.
    +type overwrittenMethodsOnFooBarAbstract struct {
    +	// Backlink to FooBarAbstract so that the rest of the class can be used by
    +	// the overridden methods.
    +	fb FooBarAbstract
     
     	// If additional constructor arguments have been given they are typically
     	// stored here so that the overriden methods can use them.
     }
     
    -func (om *overwrittenMethodsOnFooBarAbs) Foo() string {
    -	// DirectorFooBarAbsFoo calls the base method FooBarAbs::Foo.
    -	return "Go " + DirectorFooBarAbsFoo(om.fb)
    +func (om *overwrittenMethodsOnFooBarAbstract) Foo() string {
    +	// DirectorFooBarAbstractFoo calls the base method FooBarAbstract::Foo.
    +	return "Go " + DirectorFooBarAbstractFoo(om.fb)
     }
     
    -func (om *overwrittenMethodsOnFooBarAbs) Bar() string {
    +func (om *overwrittenMethodsOnFooBarAbstract) Bar() string {
     	return "Go Bar"
     }
     
     func NewFooBarGo() FooBarGo {
    -	// Instantiate FooBarAbs with selected methods overridden.  The methods that
    -	// will be overwritten are defined on overwrittenMethodsOnFooBarAbs and have
    -	// a compatible signature to the respective virtual C++ methods.
    -	// Furthermore additional constructor arguments will be typically stored in
    -	// the overwrittenMethodsOnFooBarAbs struct.
    -	om := &overwrittenMethodsOnFooBarAbs{}
    -	fb := NewDirectorFooBarAbs(om)
    +	// Instantiate FooBarAbstract with selected methods overridden.  The methods
    +	// that will be overwritten are defined on
    +	// overwrittenMethodsOnFooBarAbstract and have a compatible signature to the
    +	// respective virtual C++ methods. Furthermore additional constructor
    +	// arguments will be typically stored in the
    +	// overwrittenMethodsOnFooBarAbstract struct.
    +	om := &overwrittenMethodsOnFooBarAbstract{}
    +	fb := NewDirectorFooBarAbstract(om)
     	om.fb = fb // Backlink causes cycle as fb.v = om!
     
    -	fbgs := &fooBarGo{FooBarAbs: fb}
    -	// The memory of the FooBarAbs director object instance can be automatically
    -	// freed once the FooBarGo instance is garbage collected by uncommenting the
    -	// following line.  Please make sure to understand the runtime.SetFinalizer
    -	// specific gotchas before doing this.  Furthemore DeleteFooBarGo should be
    -	// deleted if a finalizer is in use or the fooBarGo struct needs additional
    -	// data to prevent double deletion.
    -	// runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs)
    +	fbgs := &fooBarGo{FooBarAbstract: fb}
    +	// The memory of the FooBarAbstract director object instance can be
    +	// automatically freed once the FooBarGo instance is garbage collected by
    +	// uncommenting the following line.  Please make sure to understand the
    +	// runtime.SetFinalizer specific gotchas before doing this.  Furthemore
    +	// DeleteFooBarGo should be deleted if a finalizer is in use or the fooBarGo
    +	// struct needs additional data to prevent double deletion.
    +	// runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract)
     	return fbgs
     }
     
     // Recommended to be removed if runtime.SetFinalizer is in use.
     func DeleteFooBarGo(fbg FooBarGo) {
    -	fbg.deleteFooBarAbs()
    +	fbg.deleteFooBarAbstract()
     }
    diff --git a/Examples/go/director/director.h b/Examples/go/director/director.h
    index e08c11594..339a9adcd 100644
    --- a/Examples/go/director/director.h
    +++ b/Examples/go/director/director.h
    @@ -6,11 +6,11 @@
     #include 
     
     
    -class FooBarAbs
    +class FooBarAbstract
     {
     public:
    -	FooBarAbs() {};
    -	virtual ~FooBarAbs() {};
    +	FooBarAbstract() {};
    +	virtual ~FooBarAbstract() {};
     
     	std::string FooBar() {
     		return this->Foo() + ", " + this->Bar();
    @@ -25,11 +25,11 @@ protected:
     };
     
     
    -class FooBarCpp : public FooBarAbs
    +class FooBarCpp : public FooBarAbstract
     {
     protected:
     	virtual std::string Foo() {
    -		return "C++ " + FooBarAbs::Foo();
    +		return "C++ " + FooBarAbstract::Foo();
     	}
     
     	virtual std::string Bar() {
    diff --git a/Examples/go/director/example.i b/Examples/go/director/example.i
    index b56998e6d..e832bd8c6 100644
    --- a/Examples/go/director/example.i
    +++ b/Examples/go/director/example.i
    @@ -7,5 +7,5 @@
     #include "director.h"
     %}
     
    -%feature("director") FooBarAbs;
    +%feature("director") FooBarAbstract;
     %include "director.h"
    diff --git a/Examples/go/director/index.html b/Examples/go/director/index.html
    index d1d5a74bc..b93e780e5 100644
    --- a/Examples/go/director/index.html
    +++ b/Examples/go/director/index.html
    @@ -18,7 +18,7 @@ Classes documentation subsection for an explanation of this example.
     

    • director.go. Go source with the definition of the FooBarGo class. -
    • director.h. Header with the definition of the FooBarAbs and FooBarCpp classes. +
    • director.h. Header with the definition of the FooBarAbstract and FooBarCpp classes.
    • example.i. SWIG interface file.
    • runme.go. Sample Go program.
    -- cgit v1.2.1 From da1c6c60d38d0b6206200247056a2a36ac227b74 Mon Sep 17 00:00:00 2001 From: Richard Beare Date: Wed, 17 Jun 2015 20:14:40 +1000 Subject: This is a modification to support use of tricky enumerations in R. It includes the addition of a _runme for an existing test - preproc_constants that was previously not run. That tests includes a preprocessor based setting of an enumeration which is ignored by the existing r enumeration infrastructure. The new version correctly reports the enumeration value as 4 - previous versions set it to 0. Traditional enumerations are unchanged. The approach used to deal with these enumerations is similar to that of other languages, and requires a call to a C function at runtime to return the enumeration value. The previous approach figured out the values statically and this is still used where possible. The need for a runtime call leads to changes in when swig code is used in packages - see below. One test that previously passed now fails - namely the R sourcing of preproc_constants.R, as the enumeration code requires the shared library, which isn't loaded by that script. There is also a modification to the way the R _runme.R files are used. The call to R CMD BATCH now includes a --args option that indicates the source folder for the unittest.R file, and the first couple of lines of the _runme.R files deal with correctly locating this. Out of source tests now run correctly. This work was motivated by problems generating the SimpleITK binding, specifically with some of the more complex enumerations. This approach does have some issues wrt to code in packages, but I can't see an alternative. The problem with packages is that the R code setting up the enumeration structures requires the shared library so that the C functions returning enumeration values can be called. The enumeration setup code thus needs to be moved to the package initialisation section. For SimpleITK I do this using an R script, which I think is an acceptable solution. The core part of the process is the following function. I dump all the enumeration stuff into a .onload function. This is only necessary if some of the enumerations are tricky. splitSwigFile <- function(filename, onloadfile, mainfile) { p1 <- parse(file=filename) getdefineEnum <- function(X) { return (is.call(X) & (X[[1]]=="defineEnumeration")) } dd <- sapply(p1, getdefineEnum) enums <- p1[dd] enums <- unlist(lapply(enums, deparse)) enums <- c(".onLoad <- function(libname, pkgname) {", enums, "}") everythingelse <- p1[!dd] everythingelse <- unlist(lapply(everythingelse, deparse)) writeLines(everythingelse, mainfile) writeLines(enums, onloadfile) } --- Examples/test-suite/r/Makefile.in | 3 +- Examples/test-suite/r/arrays_dimensionless_runme.R | 4 +- Examples/test-suite/r/funcptr_runme.R | 4 +- Examples/test-suite/r/ignore_parameter_runme.R | 4 +- Examples/test-suite/r/integers_runme.R | 4 +- Examples/test-suite/r/overload_method_runme.R | 4 +- Examples/test-suite/r/preproc_constants_runme.R | 11 + Examples/test-suite/r/r_copy_struct_runme.R | 4 +- Examples/test-suite/r/r_legacy_runme.R | 4 +- Examples/test-suite/r/r_sexp_runme.R | 4 +- Examples/test-suite/r/rename_simple_runme.R | 4 +- Examples/test-suite/r/simple_array_runme.R | 3 +- Examples/test-suite/r/unions_runme.R | 3 +- Source/Modules/r.cxx | 2081 ++++++++++---------- 14 files changed, 1072 insertions(+), 1065 deletions(-) create mode 100644 Examples/test-suite/r/preproc_constants_runme.R diff --git a/Examples/test-suite/r/Makefile.in b/Examples/test-suite/r/Makefile.in index d0489531f..2c9a2c3f2 100644 --- a/Examples/test-suite/r/Makefile.in +++ b/Examples/test-suite/r/Makefile.in @@ -5,7 +5,7 @@ LANGUAGE = r SCRIPTSUFFIX = _runme.R WRAPSUFFIX = .R -RUNR = R CMD BATCH --no-save --no-restore +RUNR = R CMD BATCH --no-save --no-restore '--args $(SCRIPTDIR)' srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -44,6 +44,7 @@ include $(srcdir)/../common.mk +$(swig_and_compile_multi_cpp) $(run_multitestcase) + # Runs the testcase. # # Run the runme if it exists. If not just load the R wrapper to diff --git a/Examples/test-suite/r/arrays_dimensionless_runme.R b/Examples/test-suite/r/arrays_dimensionless_runme.R index 9b97de2d8..4fc2541ff 100644 --- a/Examples/test-suite/r/arrays_dimensionless_runme.R +++ b/Examples/test-suite/r/arrays_dimensionless_runme.R @@ -1,4 +1,6 @@ -source("unittest.R") +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + dyn.load(paste("arrays_dimensionless", .Platform$dynlib.ext, sep="")) source("arrays_dimensionless.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/funcptr_runme.R b/Examples/test-suite/r/funcptr_runme.R index 3d5281bfa..c6127ef68 100644 --- a/Examples/test-suite/r/funcptr_runme.R +++ b/Examples/test-suite/r/funcptr_runme.R @@ -1,4 +1,6 @@ -source("unittest.R") +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + dyn.load(paste("funcptr", .Platform$dynlib.ext, sep="")) source("funcptr.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/ignore_parameter_runme.R b/Examples/test-suite/r/ignore_parameter_runme.R index 89e461d71..612b70013 100644 --- a/Examples/test-suite/r/ignore_parameter_runme.R +++ b/Examples/test-suite/r/ignore_parameter_runme.R @@ -1,4 +1,6 @@ -source("unittest.R") +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + dyn.load(paste("ignore_parameter", .Platform$dynlib.ext, sep="")) source("ignore_parameter.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/integers_runme.R b/Examples/test-suite/r/integers_runme.R index e31099a3b..6e2f63b70 100644 --- a/Examples/test-suite/r/integers_runme.R +++ b/Examples/test-suite/r/integers_runme.R @@ -1,4 +1,6 @@ -source("unittest.R") +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + dyn.load(paste("integers", .Platform$dynlib.ext, sep="")) source("integers.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/overload_method_runme.R b/Examples/test-suite/r/overload_method_runme.R index afb590a74..790f3df10 100644 --- a/Examples/test-suite/r/overload_method_runme.R +++ b/Examples/test-suite/r/overload_method_runme.R @@ -1,4 +1,6 @@ -source("unittest.R") +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + dyn.load(paste("overload_method", .Platform$dynlib.ext, sep="")) source("overload_method.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/preproc_constants_runme.R b/Examples/test-suite/r/preproc_constants_runme.R new file mode 100644 index 000000000..2a4a601eb --- /dev/null +++ b/Examples/test-suite/r/preproc_constants_runme.R @@ -0,0 +1,11 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + +dyn.load(paste("preproc_constants", .Platform$dynlib.ext, sep="")) +source("preproc_constants.R") +cacheMetaData(1) + +v <- enumToInteger('kValue', '_MyEnum') +print(v) +unittest(v,4) +q(save="no") diff --git a/Examples/test-suite/r/r_copy_struct_runme.R b/Examples/test-suite/r/r_copy_struct_runme.R index 21bd93b64..deadc61fe 100644 --- a/Examples/test-suite/r/r_copy_struct_runme.R +++ b/Examples/test-suite/r/r_copy_struct_runme.R @@ -1,4 +1,6 @@ -source("unittest.R") +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + dyn.load(paste("r_copy_struct", .Platform$dynlib.ext, sep="")) source("r_copy_struct.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/r_legacy_runme.R b/Examples/test-suite/r/r_legacy_runme.R index 7e5ade87f..3ca229ff8 100644 --- a/Examples/test-suite/r/r_legacy_runme.R +++ b/Examples/test-suite/r/r_legacy_runme.R @@ -1,4 +1,6 @@ -source("unittest.R") +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + dyn.load(paste("r_legacy", .Platform$dynlib.ext, sep="")) source("r_legacy.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/r_sexp_runme.R b/Examples/test-suite/r/r_sexp_runme.R index 96b36e8af..e7b28a965 100644 --- a/Examples/test-suite/r/r_sexp_runme.R +++ b/Examples/test-suite/r/r_sexp_runme.R @@ -1,4 +1,6 @@ -source("unittest.R") +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + dyn.load(paste("r_sexp", .Platform$dynlib.ext, sep="")) source("r_sexp.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/rename_simple_runme.R b/Examples/test-suite/r/rename_simple_runme.R index b25aeb844..0628ca6c9 100644 --- a/Examples/test-suite/r/rename_simple_runme.R +++ b/Examples/test-suite/r/rename_simple_runme.R @@ -1,4 +1,6 @@ -source("unittest.R") +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + dyn.load(paste("rename_simple", .Platform$dynlib.ext, sep="")) source("rename_simple.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/simple_array_runme.R b/Examples/test-suite/r/simple_array_runme.R index a6758dedd..fe70dc324 100644 --- a/Examples/test-suite/r/simple_array_runme.R +++ b/Examples/test-suite/r/simple_array_runme.R @@ -1,4 +1,5 @@ -source("unittest.R") +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) dyn.load(paste("simple_array", .Platform$dynlib.ext, sep="")) source("simple_array.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/unions_runme.R b/Examples/test-suite/r/unions_runme.R index 76870d10c..fd148c7ef 100644 --- a/Examples/test-suite/r/unions_runme.R +++ b/Examples/test-suite/r/unions_runme.R @@ -1,4 +1,5 @@ -source("unittest.R") +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) dyn.load(paste("unions", .Platform$dynlib.ext, sep="")) source("unions.R") cacheMetaData(1) diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 0e8e23063..9f4455fd9 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * This file is part of SWIG, which is licensed as a whole under version 3 + * This file is part of SWIG, which is licensed as a whole under version 3 * (or any later version) of the GNU General Public License. Some additional * terms also apply to certain portions of SWIG. The full details of the SWIG * license and copyrights can be found in the LICENSE and COPYRIGHT files @@ -12,11 +12,11 @@ * ----------------------------------------------------------------------------- */ #include "swigmod.h" +#include static const double DEFAULT_NUMBER = .0000123456712312312323; -static String* replaceInitialDash(const String *name) -{ +static String *replaceInitialDash(const String *name) { String *retval; if (!Strncmp(name, "_", 1)) { retval = Copy(name); @@ -27,42 +27,57 @@ static String* replaceInitialDash(const String *name) return retval; } -static String * getRTypeName(SwigType *t, int *outCount = NULL) { +static String *getRTypeName(SwigType *t, int *outCount = NULL) { String *b = SwigType_base(t); List *els = SwigType_split(t); int count = 0; int i; - - if(Strncmp(b, "struct ", 7) == 0) + + if (Strncmp(b, "struct ", 7) == 0) Replace(b, "struct ", "", DOH_REPLACE_FIRST); - + /* Printf(stdout, " %s,base = %s\n", t, b); - for(i = 0; i < Len(els); i++) + for(i = 0; i < Len(els); i++) Printf(stdout, "%d) %s, ", i, Getitem(els,i)); Printf(stdout, "\n"); */ - - for(i = 0; i < Len(els); i++) { + + for (i = 0; i < Len(els); i++) { String *el = Getitem(els, i); - if(Strcmp(el, "p.") == 0 || Strncmp(el, "a(", 2) == 0) { + if (Strcmp(el, "p.") == 0 || Strncmp(el, "a(", 2) == 0) { count++; Append(b, "Ref"); } } - if(outCount) + if (outCount) *outCount = count; - + String *tmp = NewString(""); char *retName = Char(SwigType_manglestr(t)); Insert(tmp, 0, retName); return tmp; - + /* - if(count) - return(b); - - Delete(b); - return(NewString("")); - */ + if(count) + return(b); + + Delete(b); + return(NewString("")); + */ +} + +static String *getNamespacePrefix(const String *enumRef) { + // for use from enumDeclaration. + // returns the namespace part of a string + // Do we have any "::"? + String *name = NewString(enumRef); + + while (Strstr(name, "::")) { + name = NewStringf("%s", Strchr(name, ':') + 2); + } + String *result = NewStringWithSize(enumRef, Len(enumRef) - Len(name)); + + Delete(name); + return (result); } /********************* @@ -71,16 +86,16 @@ static String * getRTypeName(SwigType *t, int *outCount = NULL) { Now handles arrays, i.e. struct A[2] ****************/ -static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) { +static String *getRClassName(String *retType, int /*addRef */ = 1, int upRef = 0) { String *tmp = NewString(""); SwigType *resolved = SwigType_typedef_resolve_all(retType); char *retName = Char(SwigType_manglestr(resolved)); if (upRef) { Printf(tmp, "_p%s", retName); - } else{ + } else { Insert(tmp, 0, retName); } - + return tmp; /* #if 1 @@ -89,33 +104,33 @@ static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) { if(!l || n == 0) { #ifdef R_SWIG_VERBOSE if (debugMode) - Printf(stdout, "SwigType_split return an empty list for %s\n", - retType); + Printf(stdout, "SwigType_split return an empty list for %s\n", + retType); #endif return(tmp); } - - + + String *el = Getitem(l, n-1); char *ptr = Char(el); if(strncmp(ptr, "struct ", 7) == 0) ptr += 7; - + Printf(tmp, "%s", ptr); - + if(addRef) { for(int i = 0; i < n; i++) { - if(Strcmp(Getitem(l, i), "p.") == 0 || - Strncmp(Getitem(l, i), "a(", 2) == 0) - Printf(tmp, "Ref"); + if(Strcmp(Getitem(l, i), "p.") == 0 || + Strncmp(Getitem(l, i), "a(", 2) == 0) + Printf(tmp, "Ref"); } } - + #else char *retName = Char(SwigType_manglestr(retType)); if(!retName) return(tmp); - + if(addRef) { while(retName && strlen(retName) > 1 && strncmp(retName, "_p", 2) == 0) { retName += 2; @@ -126,7 +141,7 @@ static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) { retName ++; Insert(tmp, 0, retName); #endif - + return tmp; */ } @@ -137,50 +152,47 @@ static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) { Now handles arrays, i.e. struct A[2] ****************/ -static String * getRClassNameCopyStruct(String *retType, int addRef) { +static String *getRClassNameCopyStruct(String *retType, int addRef) { String *tmp = NewString(""); - + #if 1 List *l = SwigType_split(retType); int n = Len(l); - if(!l || n == 0) { + if (!l || n == 0) { #ifdef R_SWIG_VERBOSE Printf(stdout, "SwigType_split return an empty list for %s\n", retType); #endif - return(tmp); + return (tmp); } - - - String *el = Getitem(l, n-1); + + + String *el = Getitem(l, n - 1); char *ptr = Char(el); - if(strncmp(ptr, "struct ", 7) == 0) + if (strncmp(ptr, "struct ", 7) == 0) ptr += 7; - + Printf(tmp, "%s", ptr); - - if(addRef) { - for(int i = 0; i < n; i++) { - if(Strcmp(Getitem(l, i), "p.") == 0 || - Strncmp(Getitem(l, i), "a(", 2) == 0) - Printf(tmp, "Ref"); + + if (addRef) { + for (int i = 0; i < n; i++) { + if (Strcmp(Getitem(l, i), "p.") == 0 || Strncmp(Getitem(l, i), "a(", 2) == 0) + Printf(tmp, "Ref"); } } - #else char *retName = Char(SwigType_manglestr(retType)); - if(!retName) - return(tmp); - - if(addRef) { - while(retName && strlen(retName) > 1 && - strncmp(retName, "_p", 2) == 0) { + if (!retName) + return (tmp); + + if (addRef) { + while (retName && strlen(retName) > 1 && strncmp(retName, "_p", 2) == 0) { retName += 2; Printf(tmp, "Ref"); } } - - if(retName[0] == '_') - retName ++; + + if (retName[0] == '_') + retName++; Insert(tmp, 0, retName); #endif @@ -197,11 +209,8 @@ static String * getRClassNameCopyStruct(String *retType, int addRef) { static void writeListByLine(List *l, File *out, bool quote = 0) { int i, n = Len(l); - for(i = 0; i < n; i++) - Printf(out, "%s%s%s%s%s\n", tab8, - quote ? "\"" :"", - Getitem(l, i), - quote ? "\"" :"", i < n-1 ? "," : ""); + for (i = 0; i < n; i++) + Printf(out, "%s%s%s%s%s\n", tab8, quote ? "\"" : "", Getitem(l, i), quote ? "\"" : "", i < n - 1 ? "," : ""); } @@ -231,10 +240,13 @@ static void showUsage() { } static bool expandTypedef(SwigType *t) { - if (SwigType_isenum(t)) return false; + if (SwigType_isenum(t)) + return false; String *prefix = SwigType_prefix(t); - if (Strncmp(prefix, "f", 1)) return false; - if (Strncmp(prefix, "p.f", 3)) return false; + if (Strncmp(prefix, "f", 1)) + return false; + if (Strncmp(prefix, "p.f", 3)) + return false; return true; } @@ -246,11 +258,11 @@ static bool expandTypedef(SwigType *t) { static int addCopyParameter(SwigType *type) { int ok = 0; ok = Strncmp(type, "struct ", 7) == 0 || Strncmp(type, "p.struct ", 9) == 0; - if(!ok) { + if (!ok) { ok = Strncmp(type, "p.", 2); } - return(ok); + return (ok); } static void replaceRClass(String *tm, SwigType *type) { @@ -260,25 +272,28 @@ static void replaceRClass(String *tm, SwigType *type) { Replaceall(tm, "$R_class", tmp); Replaceall(tm, "$*R_class", tmp_base); Replaceall(tm, "$&R_class", tmp_ref); - Delete(tmp); Delete(tmp_base); Delete(tmp_ref); + Delete(tmp); + Delete(tmp_base); + Delete(tmp_ref); } static double getNumber(String *value) { double d = DEFAULT_NUMBER; - if(Char(value)) { - if(sscanf(Char(value), "%lf", &d) != 1) - return(DEFAULT_NUMBER); + if (Char(value)) { + if (sscanf(Char(value), "%lf", &d) != 1) + return (DEFAULT_NUMBER); } - return(d); + return (d); } -class R : public Language { + +class R:public Language { public: R(); void registerClass(Node *n); void main(int argc, char *argv[]); int top(Node *n); - + void dispatchFunction(Node *n); int functionWrapper(Node *n); int constantWrapper(Node *n); @@ -290,99 +305,90 @@ public: int membervariableHandler(Node *n); int typedefHandler(Node *n); - static List *Swig_overload_rank(Node *n, - bool script_lang_wrapping); + static List *Swig_overload_rank(Node *n, bool script_lang_wrapping); int memberfunctionHandler(Node *n) { if (debugMode) - Printf(stdout, " %s %s\n", - Getattr(n, "name"), - Getattr(n, "type")); + Printf(stdout, " %s %s\n", Getattr(n, "name"), Getattr(n, "type")); member_name = Getattr(n, "sym:name"); processing_class_member_function = 1; - int status = Language::memberfunctionHandler(n); - processing_class_member_function = 0; - return status; + int status = Language::memberfunctionHandler(n); + processing_class_member_function = 0; + return status; } - - /* Grab the name of the current class being processed so that we can - deal with members of that class. */ - int classHandler(Node *n){ - if(!ClassMemberTable) + /* Grab the name of the current class being processed so that we can + deal with members of that class. */ int classHandler(Node *n) { + if (!ClassMemberTable) ClassMemberTable = NewHash(); - + class_name = Getattr(n, "name"); int status = Language::classHandler(n); - + class_name = NULL; return status; } // Not used: String *runtimeCode(); - + protected: int addRegistrationRoutine(String *rname, int nargs); int outputRegistrationRoutines(File *out); - + int outputCommandLineArguments(File *out); - int generateCopyRoutines(Node *n); + int generateCopyRoutines(Node *n); int DumpCode(Node *n); - + int OutputMemberReferenceMethod(String *className, int isSet, List *el, File *out); int OutputArrayMethod(String *className, List *el, File *out); int OutputClassMemberTable(Hash *tb, File *out); int OutputClassMethodsTable(File *out); int OutputClassAccessInfo(Hash *tb, File *out); - + int defineArrayAccessors(SwigType *type); - + void addNamespaceFunction(String *name) { - if(!namespaceFunctions) + if (!namespaceFunctions) namespaceFunctions = NewList(); Append(namespaceFunctions, name); } void addNamespaceMethod(String *name) { - if(!namespaceMethods) + if (!namespaceMethods) namespaceMethods = NewList(); Append(namespaceMethods, name); } - - String* processType(SwigType *t, Node *n, int *nargs = NULL); + + String *processType(SwigType *t, Node *n, int *nargs = NULL); String *createFunctionPointerHandler(SwigType *t, Node *n, int *nargs); int addFunctionPointerProxy(String *name, Node *n, SwigType *t, String *s_paramTypes) { /*XXX Do we need to put the t in there to get the return type later. */ - if(!functionPointerProxyTable) + if (!functionPointerProxyTable) functionPointerProxyTable = NewHash(); - + Setattr(functionPointerProxyTable, name, n); - + Setattr(SClassDefs, name, name); - Printv(s_classes, "setClass('", - name, - "',\n", tab8, - "prototype = list(parameterTypes = c(", s_paramTypes, "),\n", - tab8, tab8, tab8, - "returnType = '", SwigType_manglestr(t), "'),\n", tab8, - "contains = 'CRoutinePointer')\n\n##\n", NIL); - + Printv(s_classes, "setClass('", + name, + "',\n", tab8, + "prototype = list(parameterTypes = c(", s_paramTypes, "),\n", + tab8, tab8, tab8, "returnType = '", SwigType_manglestr(t), "'),\n", tab8, "contains = 'CRoutinePointer')\n\n##\n", NIL); + return SWIG_OK; } - - - void addSMethodInfo(String *name, - String *argType, int nargs); - // Simple initialization such as constant strings that can be reused. - void init(); - - - void addAccessor(String *memberName, Wrapper *f, - String *name, int isSet = -1); - + + + void addSMethodInfo(String *name, String *argType, int nargs); + // Simple initialization such as constant strings that can be reused. + void init(); + + + void addAccessor(String *memberName, Wrapper *f, String *name, int isSet = -1); + static int getFunctionPointerNumArgs(Node *n, SwigType *tt); -protected: +protected: bool copyStruct; bool memoryProfile; bool aggressiveGc; @@ -400,95 +406,88 @@ protected: String *s_init; String *s_init_routine; String *s_namespace; - - // State variables that carry information across calls to functionWrapper() - // from member accessors and class declarations. + + // State variables that carry information across calls to functionWrapper() + // from member accessors and class declarations. String *opaqueClassDeclaration; int processing_variable; int processing_member_access_function; String *member_name; String *class_name; - - + + int processing_class_member_function; List *class_member_functions; List *class_member_set_functions; - + /* */ Hash *ClassMemberTable; Hash *ClassMethodsTable; Hash *SClassDefs; Hash *SMethodInfo; - - // Information about routines that are generated and to be registered with - // R for dynamic lookup. + + // Information about routines that are generated and to be registered with + // R for dynamic lookup. Hash *registrationTable; Hash *functionPointerProxyTable; - + List *namespaceFunctions; List *namespaceMethods; - List *namespaceClasses; // Probably can do this from ClassMemberTable. - - - // Store a copy of the command line. - // Need only keep a string that has it formatted. + List *namespaceClasses; // Probably can do this from ClassMemberTable. + + + // Store a copy of the command line. + // Need only keep a string that has it formatted. char **Argv; - int Argc; + int Argc; bool inCPlusMode; - + // State variables that we remember from the command line settings // potentially that govern the code we generate. String *DllName; String *Rpackage; - bool noInitializationCode; - bool outputNamespaceInfo; - + bool noInitializationCode; + bool outputNamespaceInfo; + String *UnProtectWrapupCode; // Static members static bool debugMode; }; -R::R() : - copyStruct(false), - memoryProfile(false), - aggressiveGc(false), - sfile(0), - f_init(0), - s_classes(0), - f_begin(0), - f_runtime(0), - f_wrapper(0), - s_header(0), - f_wrappers(0), - s_init(0), - s_init_routine(0), - s_namespace(0), - opaqueClassDeclaration(0), - processing_variable(0), - processing_member_access_function(0), - member_name(0), - class_name(0), - processing_class_member_function(0), - class_member_functions(0), - class_member_set_functions(0), - ClassMemberTable(0), - ClassMethodsTable(0), - SClassDefs(0), - SMethodInfo(0), - registrationTable(0), - functionPointerProxyTable(0), - namespaceFunctions(0), - namespaceMethods(0), - namespaceClasses(0), - Argv(0), - Argc(0), - inCPlusMode(false), - DllName(0), - Rpackage(0), - noInitializationCode(false), - outputNamespaceInfo(false), - UnProtectWrapupCode(0) { +R::R(): +copyStruct(false), +memoryProfile(false), +aggressiveGc(false), +sfile(0), +f_init(0), +s_classes(0), +f_begin(0), +f_runtime(0), +f_wrapper(0), +s_header(0), +f_wrappers(0), +s_init(0), +s_init_routine(0), +s_namespace(0), +opaqueClassDeclaration(0), +processing_variable(0), +processing_member_access_function(0), +member_name(0), +class_name(0), +processing_class_member_function(0), +class_member_functions(0), +class_member_set_functions(0), +ClassMemberTable(0), +ClassMethodsTable(0), +SClassDefs(0), +SMethodInfo(0), +registrationTable(0), +functionPointerProxyTable(0), +namespaceFunctions(0), +namespaceMethods(0), +namespaceClasses(0), +Argv(0), Argc(0), inCPlusMode(false), DllName(0), Rpackage(0), noInitializationCode(false), outputNamespaceInfo(false), UnProtectWrapupCode(0) { } bool R::debugMode = false; @@ -508,43 +507,44 @@ int R::getFunctionPointerNumArgs(Node *n, SwigType *tt) { void R::addSMethodInfo(String *name, String *argType, int nargs) { (void) argType; - - if(!SMethodInfo) + + if (!SMethodInfo) SMethodInfo = NewHash(); if (debugMode) Printf(stdout, "[addMethodInfo] %s\n", name); Hash *tb = Getattr(SMethodInfo, name); - if(!tb) { + if (!tb) { tb = NewHash(); Setattr(SMethodInfo, name, tb); } String *str = Getattr(tb, "max"); int max = -1; - if(str) + if (str) max = atoi(Char(str)); - if(max < nargs) { - if(str) Delete(str); + if (max < nargs) { + if (str) + Delete(str); str = NewStringf("%d", max); Setattr(tb, "max", str); } } - + /* Returns the name of the new routine. */ -String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { +String *R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { String *funName = SwigType_manglestr(t); - + /* See if we have already processed this one. */ - if(functionPointerProxyTable && Getattr(functionPointerProxyTable, funName)) + if (functionPointerProxyTable && Getattr(functionPointerProxyTable, funName)) return funName; - + if (debugMode) - Printf(stdout, " Defining %s\n", t); - + Printf(stdout, " Defining %s\n", t); + SwigType *rettype = Copy(Getattr(n, "type")); SwigType *funcparams = SwigType_functionpointer_decompose(rettype); String *rtype = SwigType_str(rettype, 0); @@ -558,13 +558,13 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { Printf(stdout, "Type: %s\n", t); Printf(stdout, "Return type: %s\n", SwigType_base(t)); } - + bool isVoidType = Strcmp(rettype, "void") == 0; if (debugMode) Printf(stdout, "%s is void ? %s (%s)\n", funName, isVoidType ? "yes" : "no", rettype); - + Wrapper *f = NewWrapper(); - + /* Go through argument list, attach lnames for arguments */ int i = 0; Parm *p = parms; @@ -573,14 +573,14 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { String *lname; if (!arg && Cmp(Getattr(p, "type"), "void")) { - lname = NewStringf("s_arg%d", i+1); + lname = NewStringf("s_arg%d", i + 1); Setattr(p, "name", lname); } else lname = arg; Setattr(p, "lname", lname); } - + Swig_typemap_attach_parms("out", parms, f); Swig_typemap_attach_parms("scoerceout", parms, f); Swig_typemap_attach_parms("scheck", parms, f); @@ -595,9 +595,9 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { Wrapper_add_local(f, "r_swig_cb_data", "RCallbackFunctionData *r_swig_cb_data = R_SWIG_getCallbackFunctionData()"); String *lvar = NewString("r_swig_cb_data"); - Wrapper_add_local(f, "r_tmp", "SEXP r_tmp"); // for use in converting arguments to R objects for call. - Wrapper_add_local(f, "r_nprotect", "int r_nprotect = 0"); // for use in converting arguments to R objects for call. - Wrapper_add_local(f, "r_vmax", "char * r_vmax= 0"); // for use in converting arguments to R objects for call. + Wrapper_add_local(f, "r_tmp", "SEXP r_tmp"); // for use in converting arguments to R objects for call. + Wrapper_add_local(f, "r_nprotect", "int r_nprotect = 0"); // for use in converting arguments to R objects for call. + Wrapper_add_local(f, "r_vmax", "char * r_vmax= 0"); // for use in converting arguments to R objects for call. // Add local for error code in return value. This is not in emit_return_variable because that assumes an out typemap // whereas the type makes are reverse @@ -605,136 +605,125 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { p = parms; int nargs = ParmList_len(parms); - if(numArgs) { + if (numArgs) { *numArgs = nargs; if (debugMode) Printf(stdout, "Setting number of parameters to %d\n", *numArgs); - } + } String *setExprElements = NewString(""); - + String *s_paramTypes = NewString(""); - for(i = 0; p; i++) { + for (i = 0; p; i++) { SwigType *tt = Getattr(p, "type"); SwigType *name = Getattr(p, "name"); String *tm = Getattr(p, "tmap:out"); - Printf(f->def, "%s %s", SwigType_str(tt, 0), name); - if(tm) { + Printf(f->def, "%s %s", SwigType_str(tt, 0), name); + if (tm) { Replaceall(tm, "$1", name); if (SwigType_isreference(tt)) { - String *tmp = NewString(""); + String *tmp = NewString(""); Append(tmp, "*"); - Append(tmp, name); - Replaceall(tm, tmp, name); + Append(tmp, name); + Replaceall(tm, tmp, name); } Replaceall(tm, "$result", "r_tmp"); - replaceRClass(tm, Getattr(p,"type")); - Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); - } - + replaceRClass(tm, Getattr(p, "type")); + Replaceall(tm, "$owner", "R_SWIG_EXTERNAL"); + } + Printf(setExprElements, "%s\n", tm); Printf(setExprElements, "SETCAR(r_swig_cb_data->el, %s);\n", "r_tmp"); Printf(setExprElements, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n"); - + Printf(s_paramTypes, "'%s'", SwigType_manglestr(tt)); - - + + p = nextSibling(p); - if(p) { + if (p) { Printf(f->def, ", "); Printf(s_paramTypes, ", "); } } - - Printf(f->def, ") {\n"); - + + Printf(f->def, ") {\n"); + Printf(f->code, "Rf_protect(%s->expr = Rf_allocVector(LANGSXP, %d));\n", lvar, nargs + 1); Printf(f->code, "r_nprotect++;\n"); Printf(f->code, "r_swig_cb_data->el = r_swig_cb_data->expr;\n\n"); - + Printf(f->code, "SETCAR(r_swig_cb_data->el, r_swig_cb_data->fun);\n"); Printf(f->code, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n"); - + Printf(f->code, "%s\n\n", setExprElements); - - Printv(f->code, "r_swig_cb_data->retValue = R_tryEval(", - "r_swig_cb_data->expr,", - " R_GlobalEnv,", - " &r_swig_cb_data->errorOccurred", - ");\n", - NIL); - + + Printv(f->code, "r_swig_cb_data->retValue = R_tryEval(", "r_swig_cb_data->expr,", " R_GlobalEnv,", " &r_swig_cb_data->errorOccurred", ");\n", NIL); + Printv(f->code, "\n", - "if(r_swig_cb_data->errorOccurred) {\n", - "R_SWIG_popCallbackFunctionData(1);\n", - "Rf_error(\"error in calling R function as a function pointer (", - funName, - ")\");\n", - "}\n", - NIL); - - - - if(!isVoidType) { - /* Need to deal with the return type of the function pointer, not the function pointer itself. + "if(r_swig_cb_data->errorOccurred) {\n", + "R_SWIG_popCallbackFunctionData(1);\n", "Rf_error(\"error in calling R function as a function pointer (", funName, ")\");\n", "}\n", NIL); + + + + if (!isVoidType) { + /* Need to deal with the return type of the function pointer, not the function pointer itself. So build a new node that has the relevant pieces. 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? - */ + */ Parm *bbase = NewParmNode(rettype, n); String *returnTM = Swig_typemap_lookup("in", bbase, Swig_cresult_name(), f); - if(returnTM) { + if (returnTM) { String *tm = returnTM; - Replaceall(tm,"$input", "r_swig_cb_data->retValue"); - Replaceall(tm,"$target", Swig_cresult_name()); + Replaceall(tm, "$input", "r_swig_cb_data->retValue"); + Replaceall(tm, "$target", Swig_cresult_name()); replaceRClass(tm, rettype); - Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); - Replaceall(tm,"$disown","0"); + Replaceall(tm, "$owner", "R_SWIG_EXTERNAL"); + Replaceall(tm, "$disown", "0"); Printf(f->code, "%s\n", tm); } Delete(bbase); } - + Printv(f->code, "R_SWIG_popCallbackFunctionData(1);\n", NIL); Printv(f->code, "\n", UnProtectWrapupCode, NIL); - if (SwigType_isreference(rettype)) { - Printv(f->code, "return *", Swig_cresult_name(), ";\n", NIL); - } else if(!isVoidType) - Printv(f->code, "return ", Swig_cresult_name(), ";\n", NIL); - + if (SwigType_isreference(rettype)) { + Printv(f->code, "return *", Swig_cresult_name(), ";\n", NIL); + } else if (!isVoidType) + Printv(f->code, "return ", Swig_cresult_name(), ";\n", NIL); + Printv(f->code, "\n}\n", NIL); Replaceall(f->code, "SWIG_exception_fail", "SWIG_exception_noreturn"); - + /* To coerce correctly in S, we really want to have an extra/intermediate - function that handles the scoerceout. + function that handles the scoerceout. We need to check if any of the argument types have an entry in that map. If none do, the ignore and call the function straight. Otherwise, generate the a marshalling function. Need to be able to find it in S. Or use an entirely generic one that evaluates the expressions. Handle errors in the evaluation of the function by restoring - the stack, if there is one in use for this function (i.e. no + the stack, if there is one in use for this function (i.e. no userData). - */ - + */ + Wrapper_print(f, f_wrapper); - + addFunctionPointerProxy(funName, n, t, s_paramTypes); Delete(s_paramTypes); Delete(rtype); Delete(rettype); Delete(funcparams); DelWrapper(f); - + return funName; } void R::init() { - UnProtectWrapupCode = - NewStringf("%s", "vmaxset(r_vmax);\nif(r_nprotect) Rf_unprotect(r_nprotect);\n\n"); - + UnProtectWrapupCode = NewStringf("%s", "vmaxset(r_vmax);\nif(r_nprotect) Rf_unprotect(r_nprotect);\n\n"); + SClassDefs = NewHash(); - + sfile = NewString(""); f_init = NewString(""); s_header = NewString(""); @@ -761,18 +750,18 @@ int R::cDeclaration(Node *n) { /** Method from Language that is called to start the entire - processing off, i.e. the generation of the code. + processing off, i.e. the generation of the code. It is called after the input has been read and parsed. Here we open the output streams and generate the code. ***/ int R::top(Node *n) { String *module = Getattr(n, "name"); - if(!Rpackage) + if (!Rpackage) Rpackage = Copy(module); - if(!DllName) + if (!DllName) DllName = Copy(module); - if(outputNamespaceInfo) { + if (outputNamespaceInfo) { s_namespace = NewString(""); Swig_register_filebyname("snamespace", s_namespace); Printf(s_namespace, "useDynLib(%s)\n", DllName); @@ -797,7 +786,7 @@ int R::top(Node *n) { Printf(f_runtime, "#define SWIGR\n"); Printf(f_runtime, "\n"); - + Swig_banner_target_lang(s_init, "#"); outputCommandLineArguments(s_init); @@ -812,17 +801,17 @@ int R::top(Node *n) { Printf(f_wrapper, "#endif\n"); String *type_table = NewString(""); - SwigType_emit_type_table(f_runtime,f_wrapper); + SwigType_emit_type_table(f_runtime, f_wrapper); Delete(type_table); - if(ClassMemberTable) { + if (ClassMemberTable) { //XXX OutputClassAccessInfo(ClassMemberTable, sfile); Delete(ClassMemberTable); ClassMemberTable = NULL; } - Printf(f_init,"}\n"); - if(registrationTable) + Printf(f_init, "}\n"); + if (registrationTable) outputRegistrationRoutines(f_init); /* Now arrange to write the 2 files - .S and .c. */ @@ -848,35 +837,35 @@ int R::top(Node *n) { ****************************************************/ int R::DumpCode(Node *n) { String *output_filename = NewString(""); - - + + /* The name of the file in which we will generate the S code. */ Printf(output_filename, "%s%s.R", SWIG_output_directory(), Rpackage); - + #ifdef R_SWIG_VERBOSE Printf(stdout, "Writing S code to %s\n", output_filename); #endif - + File *scode = NewFile(output_filename, "w", SWIG_output_files()); if (!scode) { FileErrorDisplay(output_filename); SWIG_exit(EXIT_FAILURE); } Delete(output_filename); - - + + Printf(scode, "%s\n\n", s_init); Printf(scode, "%s\n\n", s_classes); Printf(scode, "%s\n", sfile); - + Delete(scode); - String *outfile = Getattr(n,"outfile"); - File *runtime = NewFile(outfile,"w", SWIG_output_files()); + String *outfile = Getattr(n, "outfile"); + File *runtime = NewFile(outfile, "w", SWIG_output_files()); if (!runtime) { FileErrorDisplay(outfile); SWIG_exit(EXIT_FAILURE); } - + Printf(runtime, "%s", f_begin); Printf(runtime, "%s\n", f_runtime); Printf(runtime, "%s\n", s_header); @@ -885,7 +874,7 @@ int R::DumpCode(Node *n) { Delete(runtime); - if(outputNamespaceInfo) { + if (outputNamespaceInfo) { output_filename = NewString(""); Printf(output_filename, "%sNAMESPACE", SWIG_output_directory()); File *ns = NewFile(output_filename, "w", SWIG_output_files()); @@ -894,7 +883,7 @@ int R::DumpCode(Node *n) { SWIG_exit(EXIT_FAILURE); } Delete(output_filename); - + Printf(ns, "%s\n", s_namespace); Printf(ns, "\nexport(\n"); @@ -913,7 +902,7 @@ int R::DumpCode(Node *n) { /* - We may need to do more.... so this is left as a + We may need to do more.... so this is left as a stub for the moment. */ int R::OutputClassAccessInfo(Hash *tb, File *out) { @@ -925,28 +914,28 @@ int R::OutputClassAccessInfo(Hash *tb, File *out) { /************************************************************************ Currently this just writes the information collected about the different methods of the C++ classes that have been processed - to the console. + to the console. This will be used later to define S4 generics and methods. **************************************************************************/ int R::OutputClassMethodsTable(File *) { Hash *tb = ClassMethodsTable; - - if(!tb) + + if (!tb) return SWIG_OK; - + List *keys = Keys(tb); String *key; int i, n = Len(keys); if (debugMode) { - for(i = 0; i < n ; i++ ) { + for (i = 0; i < n; i++) { key = Getitem(keys, i); Printf(stdout, "%d) %s\n", i, key); List *els = Getattr(tb, key); int nels = Len(els); Printf(stdout, "\t"); - for(int j = 0; j < nels; j+=2) { - Printf(stdout, "%s%s", Getitem(els, j), j < nels - 1 ? ", " : ""); - Printf(stdout, "%s\n", Getitem(els, j+1)); + for (int j = 0; j < nels; j += 2) { + Printf(stdout, "%s%s", Getitem(els, j), j < nels - 1 ? ", " : ""); + Printf(stdout, "%s\n", Getitem(els, j + 1)); } Printf(stdout, "\n"); } @@ -957,89 +946,88 @@ int R::OutputClassMethodsTable(File *) { /* - Iterate over the _set and <>_get + Iterate over the _set and <>_get elements and generate the $ and $<- functions that provide constrained access to the member fields in these elements. tb - a hash table that is built up in functionWrapper as we process each membervalueHandler. - The entries are indexed by _set and + The entries are indexed by _set and _get. Each entry is a List *. - + out - the stram where the code is to be written. This is the S code stream as we generate only S code here.. */ int R::OutputClassMemberTable(Hash *tb, File *out) { List *keys = Keys(tb), *el; - + String *key; int i, n = Len(keys); /* Loop over all the _set and _get entries in the table. */ - - if(n && outputNamespaceInfo) { + + if (n && outputNamespaceInfo) { Printf(s_namespace, "exportClasses("); } - for(i = 0; i < n; i++) { + for (i = 0; i < n; i++) { key = Getitem(keys, i); el = Getattr(tb, key); - + String *className = Getitem(el, 0); char *ptr = Char(key); ptr = &ptr[Len(key) - 3]; int isSet = strcmp(ptr, "set") == 0; - - // OutputArrayMethod(className, el, out); + + // OutputArrayMethod(className, el, out); OutputMemberReferenceMethod(className, isSet, el, out); - - if(outputNamespaceInfo) - Printf(s_namespace, "\"%s\"%s", className, i < n-1 ? "," : ""); + + if (outputNamespaceInfo) + Printf(s_namespace, "\"%s\"%s", className, i < n - 1 ? "," : ""); } - if(n && outputNamespaceInfo) { + if (n && outputNamespaceInfo) { Printf(s_namespace, ")\n"); } - + return n; } /******************************************************************* - Write the methods for $ or $<- for accessing a member field in an + Write the methods for $ or $<- for accessing a member field in an struct or union (or class). className - the name of the struct or union (e.g. Bar for struct Bar) - isSet - a logical value indicating whether the method is for + isSet - a logical value indicating whether the method is for modifying ($<-) or accessing ($) the member field. el - a list of length 2 * # accessible member elements + 1. - The first element is the name of the class. + The first element is the name of the class. The other pairs are member name and the name of the R function to access it. out - the stream where we write the code. ********************************************************************/ -int R::OutputMemberReferenceMethod(String *className, int isSet, - List *el, File *out) { +int R::OutputMemberReferenceMethod(String *className, int isSet, List *el, File *out) { int numMems = Len(el), j; int varaccessor = 0; - if (numMems == 0) + if (numMems == 0) return SWIG_OK; - + Wrapper *f = NewWrapper(), *attr = NewWrapper(); - + Printf(f->def, "function(x, name%s)", isSet ? ", value" : ""); Printf(attr->def, "function(x, i, j, ...%s)", isSet ? ", value" : ""); - + Printf(f->code, "{\n"); Printf(f->code, "%saccessorFuns = list(", tab8); Node *itemList = NewHash(); bool has_prev = false; - for(j = 0; j < numMems; j+=3) { + for (j = 0; j < numMems; j += 3) { String *item = Getitem(el, j); - if (Getattr(itemList, item)) + if (Getattr(itemList, item)) continue; Setattr(itemList, item, "1"); - + String *dup = Getitem(el, j + 1); char *ptr = Char(dup); ptr = &ptr[Len(dup) - 3]; - + if (!strcmp(ptr, "get")) varaccessor++; @@ -1055,7 +1043,7 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, } else { pitem = Copy(item); } - if (has_prev) + if (has_prev) Printf(f->code, ", "); Printf(f->code, "'%s' = %s", pitem, dup); has_prev = true; @@ -1063,114 +1051,102 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, } Delete(itemList); Printf(f->code, ");\n"); - + if (!isSet && varaccessor > 0) { Printf(f->code, "%svaccessors = c(", tab8); int vcount = 0; - for(j = 0; j < numMems; j+=3) { + for (j = 0; j < numMems; j += 3) { String *item = Getitem(el, j); String *dup = Getitem(el, j + 1); char *ptr = Char(dup); ptr = &ptr[Len(dup) - 3]; - + if (!strcmp(ptr, "get")) { - vcount++; - Printf(f->code, "'%s'%s", item, vcount < varaccessor ? ", " : ""); + vcount++; + Printf(f->code, "'%s'%s", item, vcount < varaccessor ? ", " : ""); } } Printf(f->code, ");\n"); } - - + + /* Printv(f->code, tab8, - "idx = pmatch(name, names(accessorFuns))\n", - tab8, - "if(is.na(idx)) {\n", - tab8, tab4, - "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", - tab8, - "if(is.na(idx)) \n", - tab8, tab4, NIL); - Printf(f->code, "return(callNextMethod(x, name%s));\n", - isSet ? ", value" : ""); + "idx = pmatch(name, names(accessorFuns))\n", + tab8, + "if(is.na(idx)) {\n", + tab8, tab4, + "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", tab8, "if(is.na(idx)) \n", tab8, tab4, NIL); + Printf(f->code, "return(callNextMethod(x, name%s));\n", isSet ? ", value" : ""); Printv(f->code, tab8, "f = accessorFuns[[idx]];\n", NIL); - if(isSet) { + 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. } else { if (varaccessor) { - Printv(f->code, tab8, - "if (is.na(match(name, vaccessors))) function(...){f(x, ...)} else f(x);\n", NIL); + Printv(f->code, tab8, "if (is.na(match(name, vaccessors))) function(...){f(x, ...)} else f(x);\n", NIL); } else { Printv(f->code, tab8, "function(...){f(x, ...)};\n", NIL); } } Printf(f->code, "}\n"); - - + + Printf(out, "# Start of accessor method for %s\n", className); - Printf(out, "setMethod('$%s', '_p%s', ", - isSet ? "<-" : "", - getRClassName(className)); + Printf(out, "setMethod('$%s', '_p%s', ", isSet ? "<-" : "", getRClassName(className)); Wrapper_print(f, out); Printf(out, ");\n"); - - if(isSet) { - Printf(out, "setMethod('[[<-', c('_p%s', 'character'),", - getRClassName(className)); + + if (isSet) { + Printf(out, "setMethod('[[<-', c('_p%s', 'character'),", getRClassName(className)); Insert(f->code, 2, "name = i;\n"); Printf(attr->code, "%s", f->code); Wrapper_print(attr, out); Printf(out, ");\n"); } - + DelWrapper(attr); DelWrapper(f); - + Printf(out, "# end of accessor method for %s\n", className); - + return SWIG_OK; } /******************************************************************* - Write the methods for [ or [<- for accessing a member field in an + Write the methods for [ or [<- for accessing a member field in an struct or union (or class). className - the name of the struct or union (e.g. Bar for struct Bar) el - a list of length 2 * # accessible member elements + 1. - The first element is the name of the class. + The first element is the name of the class. The other pairs are member name and the name of the R function to access it. out - the stream where we write the code. ********************************************************************/ int R::OutputArrayMethod(String *className, List *el, File *out) { int numMems = Len(el), j; - - if(!el || numMems == 0) - return(0); - + + if (!el || numMems == 0) + return (0); + Printf(out, "# start of array methods for %s\n", className); - for(j = 0; j < numMems; j+=3) { + for (j = 0; j < numMems; j += 3) { String *item = Getitem(el, j); String *dup = Getitem(el, j + 1); if (!Strcmp(item, "__getitem__")) { - Printf(out, - "setMethod('[', '_p%s', function(x, i, j, ..., drop =TRUE) ", - getRClassName(className)); + Printf(out, "setMethod('[', '_p%s', function(x, i, j, ..., drop =TRUE) ", getRClassName(className)); Printf(out, " sapply(i, function (n) %s(x, as.integer(n-1))))\n\n", dup); } if (!Strcmp(item, "__setitem__")) { - Printf(out, "setMethod('[<-', '_p%s', function(x, i, j, ..., value)", - getRClassName(className)); + Printf(out, "setMethod('[<-', '_p%s', function(x, i, j, ..., value)", getRClassName(className)); Printf(out, " sapply(1:length(i), function(n) %s(x, as.integer(i[n]-1), value[n])))\n\n", dup); } - + } - + Printf(out, "# end of array methods for %s\n", className); - + return SWIG_OK; } @@ -1183,51 +1159,129 @@ int R::OutputArrayMethod(String *className, List *el, File *out) { int R::enumDeclaration(Node *n) { String *name = Getattr(n, "name"); String *tdname = Getattr(n, "tdname"); - + + if (cplus_mode != PUBLIC) { + return (SWIG_NOWRAP); + } + /* Using name if tdname is empty. */ - - if(Len(tdname) == 0) - tdname = name; + if (Len(tdname) == 0) + tdname = name; - if(!tdname || Strcmp(tdname, "") == 0) { + if (!tdname || Strcmp(tdname, "") == 0) { Language::enumDeclaration(n); return SWIG_OK; } - + String *mangled_tdname = SwigType_manglestr(tdname); String *scode = NewString(""); - - Printv(scode, "defineEnumeration('", mangled_tdname, "'", - ",\n", tab8, tab8, tab4, ".values = c(\n", NIL); - + String *possiblescode = NewString(""); + + // Need to create some C code to return the enum values. + // Presumably a C function for each element of the enum.. + // There is probably some sneaky way to use the + // standard methods of variable/constant access, but I can't see + // it yet. + // Need to fetch the namespace part of the enum in tdname, so + // that we can address the correct enum. Perhaps there is already an + // attribute that has this info, but I can't find it. That leaves + // searching for ::. Obviously needs to work if there is no nesting. + // + // One issue is that swig is generating defineEnumeration calls for + // enums in the private part of classes. This usually isn't a + // problem, but the model in which some C code returns the + // underlying value won't compile because it is accessing a private + // type. + // + // It will be best to turn off binding to private parts of + // classes. + + String *cppcode = NewString(""); + // this is the namespace that will get used inside the functions + // returning enumerations. + String *namespaceprefix = getNamespacePrefix(tdname); + Wrapper *eW = NewWrapper(); + Node *kk; + + for (kk = firstChild(n); kk; kk = nextSibling(kk)) { + String *ename = Getattr(kk, "name"); + String *fname = NewString(""); + String *cfunctname = NewStringf("R_swigenum_%s_%s", mangled_tdname, ename); + String *rfunctname = NewStringf("R_swigenum_%s_%s_get", mangled_tdname, ename); + Printf(fname, "%s(void){", cfunctname); + Printf(cppcode, "SWIGEXPORT SEXP \n%s\n", fname); + Printf(cppcode, "int result;\n"); + Printf(cppcode, "SEXP r_ans = R_NilValue;\n"); + Printf(cppcode, "result = (int)%s%s;\n", namespaceprefix, ename); + Printf(cppcode, "r_ans = Rf_ScalarInteger(result);\n"); + Printf(cppcode, "return(r_ans);\n}\n"); + + // Now emit the r binding functions + Printf(possiblescode, "`%s` = function(.copy=FALSE) {\n", rfunctname); + Printf(possiblescode, ".Call(\'%s\', as.logical(.copy), PACKAGE=\'%s\')\n}\n\n", cfunctname, Rpackage); + Printf(possiblescode, "attr(`%s`, \'returnType\')=\'integer\'\n", rfunctname); + Printf(possiblescode, "class(`%s`) = c(\"SWIGfunction\", class(\'%s\'))\n\n", rfunctname, rfunctname); + Delete(ename); + Delete(fname); + Delete(cfunctname); + Delete(rfunctname); + } + + Printv(cppcode, "", NIL); + + Printf(eW->code, "%s", cppcode); + Delete(cppcode); + + Delete(namespaceprefix); + + Printv(scode, "defineEnumeration('", mangled_tdname, "'", ",\n", tab8, tab8, tab4, ".values = c(\n", NIL); + Node *c; - int value = -1; // First number is zero + int value = -1; // First number is zero + bool needenumfunc = false; // Track whether we need runtime C + // calls to deduce correct enum values for (c = firstChild(n); c; c = nextSibling(c)) { // const char *tag = Char(nodeType(c)); - // if (Strcmp(tag,"cdecl") == 0) { + // if (Strcmp(tag,"cdecl") == 0) { name = Getattr(c, "name"); + // This needs to match the version earlier - could have stored it. + String *rfunctname = NewStringf("R_swigenum_%s_%s_get()", mangled_tdname, name); String *val = Getattr(c, "enumvalue"); - if(val && Char(val)) { - int inval = (int) getNumber(val); - if(inval == DEFAULT_NUMBER) - value++; - else - value = inval; - } else + String *numstring = NewString(""); + + if (val && Char(val)) { + double inval = getNumber(val); + if (inval == DEFAULT_NUMBER) { + // This should indicate there is some fancy text there + // so we want to call the special R functions + needenumfunc = true; + Printf(numstring, "%s", rfunctname); + } else { + value = (int) inval; + Printf(numstring, "%d", value); + + } + } else { value++; - - Printf(scode, "%s%s%s'%s' = %d%s\n", tab8, tab8, tab8, name, value, - nextSibling(c) ? ", " : ""); - // } + Printf(numstring, "%d", value); + } + Printf(scode, "%s%s%s'%s' = %s%s\n", tab8, tab8, tab8, name, numstring, nextSibling(c) ? ", " : ""); + Delete(rfunctname); + Delete(numstring); } - + Printv(scode, "))", NIL); + + if (needenumfunc) { + Wrapper_print(eW, f_wrapper); + Printf(sfile, "%s\n", possiblescode); + } Printf(sfile, "%s\n", scode); - + Delete(scode); + Delete(possiblescode); Delete(mangled_tdname); - return SWIG_OK; } @@ -1236,30 +1290,28 @@ int R::enumDeclaration(Node *n) { **************************************************************/ int R::variableWrapper(Node *n) { String *name = Getattr(n, "sym:name"); - + processing_variable = 1; Language::variableWrapper(n); // Force the emission of the _set and _get function wrappers. processing_variable = 0; - - + + SwigType *ty = Getattr(n, "type"); int addCopyParam = addCopyParameter(ty); - + //XXX processType(ty, n); - - if(!SwigType_isconst(ty)) { + + if (!SwigType_isconst(ty)) { Wrapper *f = NewWrapper(); - Printf(f->def, "%s = \nfunction(value%s)\n{\n", - name, addCopyParam ? ", .copy = FALSE" : ""); - Printv(f->code, "if(missing(value)) {\n", - name, "_get(", addCopyParam ? ".copy" : "", ")\n}", NIL); - Printv(f->code, " else {\n", - name, "_set(value)\n}\n}", NIL); - + Printf(f->def, "%s = \nfunction(value%s)\n{\n", name, addCopyParam ? ", .copy = FALSE" : ""); + Printv(f->code, "if(missing(value)) {\n", name, "_get(", addCopyParam ? ".copy" : "", ")\n}", NIL); + Printv(f->code, " else {\n", name, "_set(value)\n}\n}", NIL); + Wrapper_print(f, sfile); DelWrapper(f); } else { + Printf(sfile, "## constant in variableWrapper\n"); Printf(sfile, "%s = %s_get\n", name, name); } @@ -1267,27 +1319,27 @@ int R::variableWrapper(Node *n) { } -void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, - int isSet) { - if(isSet < 0) { + +void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, int isSet) { + if (isSet < 0) { int n = Len(name); char *ptr = Char(name); - isSet = Strcmp(NewString(&ptr[n-3]), "set") == 0; + isSet = Strcmp(NewString(&ptr[n - 3]), "set") == 0; } - + List *l = isSet ? class_member_set_functions : class_member_functions; - - if(!l) { + + if (!l) { l = NewList(); - if(isSet) + if (isSet) class_member_set_functions = l; else class_member_functions = l; } - + Append(l, memberName); Append(l, name); - + String *tmp = NewString(""); Wrapper_print(wrapper, tmp); Append(l, tmp); @@ -1299,237 +1351,235 @@ void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, #define MAX_OVERLOAD 256 struct Overloaded { - Node *n; /* Node */ - int argc; /* Argument count */ - ParmList *parms; /* Parameters used for overload check */ - int error; /* Ambiguity error */ + Node *n; /* Node */ + int argc; /* Argument count */ + ParmList *parms; /* Parameters used for overload check */ + int error; /* Ambiguity error */ }; -List * R::Swig_overload_rank(Node *n, - bool script_lang_wrapping) { - Overloaded nodes[MAX_OVERLOAD]; - int nnodes = 0; - Node *o = Getattr(n,"sym:overloaded"); +List *R::Swig_overload_rank(Node *n, bool script_lang_wrapping) { + Overloaded nodes[MAX_OVERLOAD]; + int nnodes = 0; + Node *o = Getattr(n, "sym:overloaded"); - if (!o) return 0; + if (!o) + return 0; Node *c = o; while (c) { - if (Getattr(c,"error")) { - c = Getattr(c,"sym:nextSibling"); + if (Getattr(c, "error")) { + c = Getattr(c, "sym:nextSibling"); continue; } /* if (SmartPointer && Getattr(c,"cplus:staticbase")) { - c = Getattr(c,"sym:nextSibling"); - continue; - } */ + c = Getattr(c,"sym:nextSibling"); + continue; + } */ /* Make a list of all the declarations (methods) that are overloaded with * this one particular method name */ - if (Getattr(c,"wrap:name")) { + if (Getattr(c, "wrap:name")) { nodes[nnodes].n = c; - nodes[nnodes].parms = Getattr(c,"wrap:parms"); + nodes[nnodes].parms = Getattr(c, "wrap:parms"); nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms); nodes[nnodes].error = 0; nnodes++; } - c = Getattr(c,"sym:nextSibling"); + c = Getattr(c, "sym:nextSibling"); } - + /* Sort the declarations by required argument count */ { - int i,j; + int i, j; for (i = 0; i < nnodes; i++) { - for (j = i+1; j < nnodes; j++) { - if (nodes[i].argc > nodes[j].argc) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } + for (j = i + 1; j < nnodes; j++) { + if (nodes[i].argc > nodes[j].argc) { + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + } } } } /* Sort the declarations by argument types */ { - int i,j; - for (i = 0; i < nnodes-1; i++) { - if (nodes[i].argc == nodes[i+1].argc) { - for (j = i+1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) { - Parm *p1 = nodes[i].parms; - Parm *p2 = nodes[j].parms; - int differ = 0; - int num_checked = 0; - while (p1 && p2 && (num_checked < nodes[i].argc)) { - if (debugMode) { - Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type")); - } - if (checkAttribute(p1,"tmap:in:numinputs","0")) { - p1 = Getattr(p1,"tmap:in:next"); - continue; - } - if (checkAttribute(p2,"tmap:in:numinputs","0")) { - p2 = Getattr(p2,"tmap:in:next"); - continue; - } - String *t1 = Getattr(p1,"tmap:typecheck:precedence"); - String *t2 = Getattr(p2,"tmap:typecheck:precedence"); - if (debugMode) { - Printf(stdout,"t1 = '%s', t2 = '%s'\n", t1, t2); - } - if ((!t1) && (!nodes[i].error)) { - Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n), - "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap 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 method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n", - Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0)); - nodes[j].error = 1; - } - if (t1 && t2) { - int t1v, t2v; - t1v = atoi(Char(t1)); - t2v = atoi(Char(t2)); - differ = t1v-t2v; - } - else if (!t1 && t2) differ = 1; - else if (t1 && !t2) differ = -1; - else if (!t1 && !t2) differ = -1; - num_checked++; - if (differ > 0) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - break; - } else if ((differ == 0) && (Strcmp(t1,"0") == 0)) { - t1 = Getattr(p1,"ltype"); - if (!t1) { - t1 = SwigType_ltype(Getattr(p1,"type")); - if (Getattr(p1,"tmap:typecheck:SWIGTYPE")) { - SwigType_add_pointer(t1); - } - Setattr(p1,"ltype",t1); - } - t2 = Getattr(p2,"ltype"); - if (!t2) { - t2 = SwigType_ltype(Getattr(p2,"type")); - if (Getattr(p2,"tmap:typecheck:SWIGTYPE")) { - SwigType_add_pointer(t2); - } - Setattr(p2,"ltype",t2); - } - - /* Need subtype check here. If t2 is a subtype of t1, then we need to change the + int i, j; + for (i = 0; i < nnodes - 1; i++) { + if (nodes[i].argc == nodes[i + 1].argc) { + for (j = i + 1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) { + Parm *p1 = nodes[i].parms; + Parm *p2 = nodes[j].parms; + int differ = 0; + int num_checked = 0; + while (p1 && p2 && (num_checked < nodes[i].argc)) { + if (debugMode) { + Printf(stdout, "p1 = '%s', p2 = '%s'\n", Getattr(p1, "type"), Getattr(p2, "type")); + } + if (checkAttribute(p1, "tmap:in:numinputs", "0")) { + p1 = Getattr(p1, "tmap:in:next"); + continue; + } + if (checkAttribute(p2, "tmap:in:numinputs", "0")) { + p2 = Getattr(p2, "tmap:in:next"); + continue; + } + String *t1 = Getattr(p1, "tmap:typecheck:precedence"); + String *t2 = Getattr(p2, "tmap:typecheck:precedence"); + if (debugMode) { + Printf(stdout, "t1 = '%s', t2 = '%s'\n", t1, t2); + } + if ((!t1) && (!nodes[i].error)) { + Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n), + "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap 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 method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n", + Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0)); + nodes[j].error = 1; + } + if (t1 && t2) { + int t1v, t2v; + t1v = atoi(Char(t1)); + t2v = atoi(Char(t2)); + differ = t1v - t2v; + } else if (!t1 && t2) + differ = 1; + else if (t1 && !t2) + differ = -1; + else if (!t1 && !t2) + differ = -1; + num_checked++; + if (differ > 0) { + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + break; + } else if ((differ == 0) && (Strcmp(t1, "0") == 0)) { + t1 = Getattr(p1, "ltype"); + if (!t1) { + t1 = SwigType_ltype(Getattr(p1, "type")); + if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) { + SwigType_add_pointer(t1); + } + Setattr(p1, "ltype", t1); + } + t2 = Getattr(p2, "ltype"); + if (!t2) { + t2 = SwigType_ltype(Getattr(p2, "type")); + if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) { + SwigType_add_pointer(t2); + } + Setattr(p2, "ltype", t2); + } + + /* Need subtype check here. If t2 is a subtype of t1, then we need to change the order */ - if (SwigType_issubtype(t2,t1)) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } - - if (Strcmp(t1,t2) != 0) { - differ = 1; - break; - } - } else if (differ) { - break; - } - if (Getattr(p1,"tmap:in:next")) { - p1 = Getattr(p1,"tmap:in:next"); - } else { - p1 = nextSibling(p1); - } - if (Getattr(p2,"tmap:in:next")) { - p2 = Getattr(p2,"tmap:in:next"); - } else { - p2 = nextSibling(p2); - } - } - if (!differ) { - /* See if declarations differ by const only */ - 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); - if (SwigType_isconst(d1)) { - Delete(SwigType_pop(dq1)); - } - if (SwigType_isconst(d2)) { - Delete(SwigType_pop(dq2)); - } - 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; - } - differ = 1; - 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,\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) { - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].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; - } - } - Delete(dq1); - Delete(dq2); - } - } - if (!differ) { - if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s 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; - } - } - } + if (SwigType_issubtype(t2, t1)) { + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + } + + if (Strcmp(t1, t2) != 0) { + differ = 1; + break; + } + } else if (differ) { + break; + } + if (Getattr(p1, "tmap:in:next")) { + p1 = Getattr(p1, "tmap:in:next"); + } else { + p1 = nextSibling(p1); + } + if (Getattr(p2, "tmap:in:next")) { + p2 = Getattr(p2, "tmap:in:next"); + } else { + p2 = nextSibling(p2); + } + } + if (!differ) { + /* See if declarations differ by const only */ + 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); + if (SwigType_isconst(d1)) { + Delete(SwigType_pop(dq1)); + } + if (SwigType_isconst(d2)) { + Delete(SwigType_pop(dq2)); + } + 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; + } + differ = 1; + 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,\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) { + Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].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; + } + } + Delete(dq1); + Delete(dq2); + } + } + if (!differ) { + if (!nodes[j].error) { + if (script_lang_wrapping) { + Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), + "Overloaded method %s 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; + } + } + } } } } @@ -1539,7 +1589,7 @@ List * R::Swig_overload_rank(Node *n, for (i = 0; i < nnodes; i++) { if (nodes[i].error) Setattr(nodes[i].n, "overload:ignore", "1"); - Append(result,nodes[i].n); + Append(result, nodes[i].n); // Printf(stdout,"[ %d ] %s\n", i, ParmList_errorstr(nodes[i].parms)); // Swig_print_node(nodes[i].n); } @@ -1551,37 +1601,33 @@ void R::dispatchFunction(Node *n) { Wrapper *f = NewWrapper(); String *symname = Getattr(n, "sym:name"); String *nodeType = Getattr(n, "nodeType"); - bool constructor = (!Cmp(nodeType, "constructor")); + bool constructor = (!Cmp(nodeType, "constructor")); String *sfname = NewString(symname); if (constructor) Replace(sfname, "new_", "", DOH_REPLACE_FIRST); - Printf(f->def, - "`%s` <- function(...) {", sfname); + Printf(f->def, "`%s` <- function(...) {", sfname); if (debugMode) { Swig_print_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 ); + int nfunc = Len(dispatch); + Printv(f->code, "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; bool first_compare = true; - for (int i=0; i < nfunc; i++) { - Node *ni = Getitem(dispatch,i); - Parm *pi = Getattr(ni,"wrap:parms"); + for (int i = 0; i < nfunc; i++) { + Node *ni = Getitem(dispatch, i); + Parm *pi = Getattr(ni, "wrap:parms"); int num_arguments = emit_num_arguments(pi); - String *overname = Getattr(ni,"sym:overname"); + String *overname = Getattr(ni, "sym:overname"); if (cur_args != num_arguments) { if (cur_args != -1) { - Printv(f->code, "} else ", NIL); + Printv(f->code, "} else ", NIL); } Printf(f->code, "if (argc == %d) {", num_arguments); cur_args = num_arguments; @@ -1591,67 +1637,52 @@ void R::dispatchFunction(Node *n) { int j; if (num_arguments > 0) { if (!first_compare) { - Printv(f->code, " else ", NIL); + Printv(f->code, " else ", NIL); } else { - first_compare = false; + first_compare = false; } Printv(f->code, "if (", NIL); - for (p =pi, j = 0 ; j < num_arguments ; j++) { - if (debugMode) { - Swig_print_node(p); - } - String *tm = Swig_typemap_lookup("rtype", p, "", 0); - if(tm) { - replaceRClass(tm, Getattr(p, "type")); - } - - String *tmcheck = Swig_typemap_lookup("rtypecheck", p, "", 0); - if (tmcheck) { - String *tmp = NewString(""); - Printf(tmp, "argv[[%d]]", j+1); - Replaceall(tmcheck, "$arg", tmp); - Printf(tmp, "argtype[%d]", j+1); - Replaceall(tmcheck, "$argtype", tmp); - if (tm) { - Replaceall(tmcheck, "$rtype", tm); - } - if (debugMode) { - Printf(stdout, "%s\n", tmcheck); - } - Printf(f->code, "%s(%s)", - j == 0? "" : " && ", - tmcheck); - p = Getattr(p, "tmap:in:next"); - continue; - } - if (tm) { - if (Strcmp(tm,"numeric")==0) { - Printf(f->code, "%sis.numeric(argv[[%d]])", - j == 0 ? "" : " && ", - j+1); - } - else if (Strcmp(tm,"integer")==0) { - Printf(f->code, "%s(is.integer(argv[[%d]]) || is.numeric(argv[[%d]]))", - j == 0 ? "" : " && ", - j+1, j+1); - } - else if (Strcmp(tm,"character")==0) { - Printf(f->code, "%sis.character(argv[[%d]])", - j == 0 ? "" : " && ", - j+1); - } - else { - Printf(f->code, "%sextends(argtypes[%d], '%s')", - j == 0 ? "" : " && ", - j+1, - tm); - } - } - if (!SwigType_ispointer(Getattr(p, "type"))) { - Printf(f->code, " && length(argv[[%d]]) == 1", - j+1); - } - p = Getattr(p, "tmap:in:next"); + for (p = pi, j = 0; j < num_arguments; j++) { + if (debugMode) { + Swig_print_node(p); + } + String *tm = Swig_typemap_lookup("rtype", p, "", 0); + if (tm) { + replaceRClass(tm, Getattr(p, "type")); + } + + String *tmcheck = Swig_typemap_lookup("rtypecheck", p, "", 0); + if (tmcheck) { + String *tmp = NewString(""); + Printf(tmp, "argv[[%d]]", j + 1); + Replaceall(tmcheck, "$arg", tmp); + Printf(tmp, "argtype[%d]", j + 1); + Replaceall(tmcheck, "$argtype", tmp); + if (tm) { + Replaceall(tmcheck, "$rtype", tm); + } + if (debugMode) { + Printf(stdout, "%s\n", tmcheck); + } + Printf(f->code, "%s(%s)", j == 0 ? "" : " && ", tmcheck); + p = Getattr(p, "tmap:in:next"); + continue; + } + if (tm) { + if (Strcmp(tm, "numeric") == 0) { + Printf(f->code, "%sis.numeric(argv[[%d]])", j == 0 ? "" : " && ", j + 1); + } else if (Strcmp(tm, "integer") == 0) { + Printf(f->code, "%s(is.integer(argv[[%d]]) || is.numeric(argv[[%d]]))", j == 0 ? "" : " && ", j + 1, j + 1); + } else if (Strcmp(tm, "character") == 0) { + Printf(f->code, "%sis.character(argv[[%d]])", j == 0 ? "" : " && ", j + 1); + } else { + Printf(f->code, "%sextends(argtypes[%d], '%s')", j == 0 ? "" : " && ", j + 1, tm); + } + } + if (!SwigType_ispointer(Getattr(p, "type"))) { + Printf(f->code, " && length(argv[[%d]]) == 1", j + 1); + } + p = Getattr(p, "tmap:in:next"); } Printf(f->code, ") { f <- %s%s; }\n", sfname, overname); } else { @@ -1659,10 +1690,7 @@ void R::dispatchFunction(Node *n) { } } if (cur_args != -1) { - Printf(f->code, "} else {\n" - "stop(\"cannot find overloaded function for %s with argtypes (\"," - "toString(argtypes),\")\");\n" - "}", sfname); + Printf(f->code, "} else {\n" "stop(\"cannot find overloaded function for %s with argtypes (\"," "toString(argtypes),\")\");\n" "}", sfname); } Printv(f->code, ";\nf(...)", NIL); Printv(f->code, ";\n}", NIL); @@ -1677,86 +1705,77 @@ void R::dispatchFunction(Node *n) { int R::functionWrapper(Node *n) { String *fname = Getattr(n, "name"); String *iname = Getattr(n, "sym:name"); - String *type = Getattr(n, "type"); - + String *type = Getattr(n, "type"); + if (debugMode) { - Printf(stdout, - " %s %s %s\n", fname, iname, type); + Printf(stdout, " %s %s %s\n", fname, iname, type); } String *overname = 0; String *nodeType = Getattr(n, "nodeType"); - bool constructor = (!Cmp(nodeType, "constructor")); - bool destructor = (!Cmp(nodeType, "destructor")); - + bool constructor = (!Cmp(nodeType, "constructor")); + bool destructor = (!Cmp(nodeType, "destructor")); + String *sfname = NewString(iname); - + if (constructor) Replace(sfname, "new_", "", DOH_REPLACE_FIRST); - - if (Getattr(n,"sym:overloaded")) { - overname = Getattr(n,"sym:overname"); + + if (Getattr(n, "sym:overloaded")) { + overname = Getattr(n, "sym:overname"); Append(sfname, overname); } - - if (debugMode) - Printf(stdout, - " processing parameters\n"); - - + + if (debugMode) + Printf(stdout, " processing parameters\n"); + + ParmList *l = Getattr(n, "parms"); Parm *p; String *tm; - + p = l; - while(p) { + while (p) { SwigType *resultType = Getattr(p, "type"); - if (expandTypedef(resultType) && - SwigType_istypedef(resultType)) { - SwigType *resolved = - SwigType_typedef_resolve_all(resultType); + if (expandTypedef(resultType) && SwigType_istypedef(resultType)) { + SwigType *resolved = SwigType_typedef_resolve_all(resultType); if (expandTypedef(resolved)) { - Setattr(p, "type", Copy(resolved)); + Setattr(p, "type", Copy(resolved)); } } p = nextSibling(p); - } - - String *unresolved_return_type = - Copy(type); - if (expandTypedef(type) && - SwigType_istypedef(type)) { - SwigType *resolved = - SwigType_typedef_resolve_all(type); + } + + String *unresolved_return_type = Copy(type); + if (expandTypedef(type) && SwigType_istypedef(type)) { + SwigType *resolved = SwigType_typedef_resolve_all(type); if (expandTypedef(resolved)) { type = Copy(resolved); Setattr(n, "type", type); } } - if (debugMode) - Printf(stdout, " unresolved_return_type %s\n", - unresolved_return_type); - if(processing_member_access_function) { + if (debugMode) + Printf(stdout, " unresolved_return_type %s\n", unresolved_return_type); + if (processing_member_access_function) { if (debugMode) - Printf(stdout, " '%s' '%s' '%s' '%s'\n", - fname, iname, member_name, class_name); - - if(opaqueClassDeclaration) + Printf(stdout, " '%s' '%s' '%s' '%s'\n", fname, iname, member_name, class_name); + + if (opaqueClassDeclaration) return SWIG_OK; - - - /* Add the name of this member to a list for this class_name. + + + /* Add the name of this member to a list for this class_name. We will dump all these at the end. */ - + int n = Len(iname); char *ptr = Char(iname); - bool isSet(Strcmp(NewString(&ptr[n-3]), "set") == 0); - - + bool isSet(Strcmp(NewString(&ptr[n - 3]), "set") == 0); + + String *tmp = NewString(""); Printf(tmp, "%s_%s", class_name, isSet ? "set" : "get"); - + List *memList = Getattr(ClassMemberTable, tmp); - if(!memList) { + if (!memList) { memList = NewList(); Append(memList, class_name); Setattr(ClassMemberTable, tmp, memList); @@ -1765,29 +1784,29 @@ int R::functionWrapper(Node *n) { Append(memList, member_name); Append(memList, iname); } - + int i; int nargs; - + String *wname = Swig_name_wrapper(iname); Replace(wname, "_wrap", "R_swig", DOH_REPLACE_FIRST); - if(overname) + if (overname) Append(wname, overname); - Setattr(n,"wrap:name", wname); + Setattr(n, "wrap:name", wname); Wrapper *f = NewWrapper(); Wrapper *sfun = NewWrapper(); - + int isVoidReturnType = (Strcmp(type, "void") == 0); - // Need to use the unresolved return type since - // typedef resolution removes the const which causes a + // Need to use the unresolved return type since + // typedef resolution removes the const which causes a // mismatch with the function action emit_return_variable(n, unresolved_return_type, f); SwigType *rtype = Getattr(n, "type"); int addCopyParam = 0; - if(!isVoidReturnType) + if (!isVoidReturnType) addCopyParam = addCopyParameter(rtype); @@ -1796,15 +1815,14 @@ int R::functionWrapper(Node *n) { // if(addCopyParam) if (debugMode) - Printf(stdout, "Adding a .copy argument to %s for %s = %s\n", - iname, type, addCopyParam ? "yes" : "no"); + Printf(stdout, "Adding a .copy argument to %s for %s = %s\n", iname, type, addCopyParam ? "yes" : "no"); Printv(f->def, "SWIGEXPORT SEXP\n", wname, " ( ", NIL); - Printf(sfun->def, "# Start of %s\n", iname); + Printf(sfun->def, "# Start of %s\n", iname); Printv(sfun->def, "\n`", sfname, "` = function(", NIL); - if(outputNamespaceInfo) //XXX Need to be a little more discriminating + if (outputNamespaceInfo) //XXX Need to be a little more discriminating addNamespaceFunction(iname); Swig_typemap_attach_parms("scoercein", l, f); @@ -1812,8 +1830,8 @@ int R::functionWrapper(Node *n) { Swig_typemap_attach_parms("scheck", l, f); emit_parameter_variables(l, f); - emit_attach_parmmaps(l,f); - Setattr(n,"wrap:parms",l); + emit_attach_parmmaps(l, f); + Setattr(n, "wrap:parms", l); nargs = emit_num_arguments(l); @@ -1829,7 +1847,7 @@ int R::functionWrapper(Node *n) { bool inFirstArg = true; bool inFirstType = true; Parm *curP; - for (p =l, i = 0 ; i < nargs ; i++) { + for (p = l, i = 0; i < nargs; i++) { while (checkAttribute(p, "tmap:in:numinputs", "0")) { p = Getattr(p, "tmap:in:next"); @@ -1840,26 +1858,26 @@ int R::functionWrapper(Node *n) { String *funcptr_name = processType(tt, p, &nargs); // SwigType *tp = Getattr(p, "type"); - String *name = Getattr(p,"name"); - String *lname = Getattr(p,"lname"); + String *name = Getattr(p, "name"); + String *lname = Getattr(p, "lname"); // R keyword renaming if (name) { if (Swig_name_warning(p, 0, name, 0)) { - name = 0; + name = 0; } else { - /* If we have a :: in the parameter name because we are accessing a static member of a class, say, then - we need to remove that prefix. */ - while (Strstr(name, "::")) { - //XXX need to free. - name = NewStringf("%s", Strchr(name, ':') + 2); - if (debugMode) - Printf(stdout, "+++ parameter name with :: in it %s\n", name); - } + /* If we have a :: in the parameter name because we are accessing a static member of a class, say, then + we need to remove that prefix. */ + while (Strstr(name, "::")) { + //XXX need to free. + name = NewStringf("%s", Strchr(name, ':') + 2); + if (debugMode) + Printf(stdout, "+++ parameter name with :: in it %s\n", name); + } } } if (!name || Len(name) == 0) - name = NewStringf("s_arg%d", i+1); + name = NewStringf("s_arg%d", i + 1); name = replaceInitialDash(name); @@ -1867,13 +1885,13 @@ int R::functionWrapper(Node *n) { name = Copy(name); Insert(name, 0, "s_"); } - - if(processing_variable) { + + if (processing_variable) { name = Copy(name); Insert(name, 0, "s_"); } - if(!Strcmp(name, fname)) { + if (!Strcmp(name, fname)) { name = Copy(name); Insert(name, 0, "s_"); } @@ -1881,79 +1899,73 @@ int R::functionWrapper(Node *n) { Printf(sargs, "%s, ", name); String *tm; - if((tm = Getattr(p, "tmap:scoercein"))) { + if ((tm = Getattr(p, "tmap:scoercein"))) { Replaceall(tm, "$input", name); replaceRClass(tm, Getattr(p, "type")); - if(funcptr_name) { - //XXX need to get this to return non-zero - if(nargs == -1) - nargs = getFunctionPointerNumArgs(p, tt); - - String *snargs = NewStringf("%d", nargs); - Printv(sfun->code, "if(is.function(", name, ")) {", "\n", - "assert('...' %in% names(formals(", name, - ")) || length(formals(", name, ")) >= ", snargs, ");\n} ", NIL); - Delete(snargs); - - Printv(sfun->code, "else {\n", - "if(is.character(", name, ")) {\n", - name, " = getNativeSymbolInfo(", name, ");", - "\n};\n", - "if(is(", name, ", \"NativeSymbolInfo\")) {\n", - name, " = ", name, "$address", ";\n}\n", - "if(is(", name, ", \"ExternalReference\")) {\n", - name, " = ", name, "@ref;\n}\n", - "}; \n", - NIL); + if (funcptr_name) { + //XXX need to get this to return non-zero + if (nargs == -1) + nargs = getFunctionPointerNumArgs(p, tt); + + String *snargs = NewStringf("%d", nargs); + Printv(sfun->code, "if(is.function(", name, ")) {", "\n", + "assert('...' %in% names(formals(", name, ")) || length(formals(", name, ")) >= ", snargs, ");\n} ", NIL); + Delete(snargs); + + Printv(sfun->code, "else {\n", + "if(is.character(", name, ")) {\n", + name, " = getNativeSymbolInfo(", name, ");", + "\n};\n", + "if(is(", name, ", \"NativeSymbolInfo\")) {\n", + name, " = ", name, "$address", ";\n}\n", "if(is(", name, ", \"ExternalReference\")) {\n", name, " = ", name, "@ref;\n}\n", "}; \n", NIL); } else { - Printf(sfun->code, "%s\n", tm); + Printf(sfun->code, "%s\n", tm); } } Printv(sfun->def, inFirstArg ? "" : ", ", name, NIL); - if ((tm = Getattr(p,"tmap:scheck"))) { + if ((tm = Getattr(p, "tmap:scheck"))) { - Replaceall(tm,"$target", lname); - Replaceall(tm,"$source", name); - Replaceall(tm,"$input", name); + Replaceall(tm, "$target", lname); + Replaceall(tm, "$source", name); + Replaceall(tm, "$input", name); replaceRClass(tm, Getattr(p, "type")); - Printf(sfun->code,"%s\n",tm); + Printf(sfun->code, "%s\n", tm); } curP = p; - if ((tm = Getattr(p,"tmap:in"))) { + if ((tm = Getattr(p, "tmap:in"))) { - Replaceall(tm,"$target", lname); - Replaceall(tm,"$source", name); - Replaceall(tm,"$input", name); + Replaceall(tm, "$target", lname); + Replaceall(tm, "$source", name); + Replaceall(tm, "$input", name); - if (Getattr(p,"wrap:disown") || (Getattr(p,"tmap:in:disown"))) { - Replaceall(tm,"$disown","SWIG_POINTER_DISOWN"); + if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) { + Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN"); } else { - Replaceall(tm,"$disown","0"); + Replaceall(tm, "$disown", "0"); } - if(funcptr_name) { - /* have us a function pointer */ - Printf(f->code, "if(TYPEOF(%s) != CLOSXP) {\n", name); - Replaceall(tm,"$R_class", ""); + if (funcptr_name) { + /* have us a function pointer */ + Printf(f->code, "if(TYPEOF(%s) != CLOSXP) {\n", name); + Replaceall(tm, "$R_class", ""); } else { - replaceRClass(tm, Getattr(p, "type")); + replaceRClass(tm, Getattr(p, "type")); } - Printf(f->code,"%s\n",tm); - if(funcptr_name) - Printf(f->code, "} else {\n%s = %s;\nR_SWIG_pushCallbackFunctionData(%s, NULL);\n}\n", - lname, funcptr_name, name); + Printf(f->code, "%s\n", tm); + if (funcptr_name) + Printf(f->code, "} else {\n%s = %s;\nR_SWIG_pushCallbackFunctionData(%s, NULL);\n}\n", lname, funcptr_name, name); Printv(f->def, inFirstArg ? "" : ", ", "SEXP ", name, NIL); - if (Len(name) != 0) - inFirstArg = false; - p = Getattr(p,"tmap:in:next"); + if (Len(name) != 0) + inFirstArg = false; + p = Getattr(p, "tmap:in:next"); } else { p = nextSibling(p); @@ -1961,18 +1973,18 @@ int R::functionWrapper(Node *n) { tm = Swig_typemap_lookup("rtype", curP, "", 0); - if(tm) { + if (tm) { replaceRClass(tm, Getattr(curP, "type")); } Printf(s_inputTypes, "%s'%s'", inFirstType ? "" : ", ", tm); Printf(s_inputMap, "%s%s='%s'", inFirstType ? "" : ", ", name, tm); inFirstType = false; - if(funcptr_name) + if (funcptr_name) Delete(funcptr_name); - } /* end of looping over parameters. */ + } /* end of looping over parameters. */ - if(addCopyParam) { + if (addCopyParam) { Printf(sfun->def, "%s.copy = FALSE", nargs > 0 ? ", " : ""); Printf(f->def, "%sSEXP s_swig_copy", nargs > 0 ? ", " : ""); @@ -1997,21 +2009,21 @@ int R::functionWrapper(Node *n) { String *outargs = NewString(""); int numOutArgs = isVoidReturnType ? -1 : 0; - for(p = l, i = 0; p; i++) { - if((tm = Getattr(p, "tmap:argout"))) { + for (p = l, i = 0; p; i++) { + if ((tm = Getattr(p, "tmap:argout"))) { // String *lname = Getattr(p, "lname"); numOutArgs++; String *pos = NewStringf("%d", numOutArgs); - Replaceall(tm,"$source", Getattr(p, "lname")); - Replaceall(tm,"$result", "r_ans"); - Replaceall(tm,"$n", pos); // The position into which to store the answer. - Replaceall(tm,"$arg", Getattr(p, "emit:input")); - Replaceall(tm,"$input", Getattr(p, "emit:input")); - Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); + Replaceall(tm, "$source", Getattr(p, "lname")); + Replaceall(tm, "$result", "r_ans"); + Replaceall(tm, "$n", pos); // The position into which to store the answer. + Replaceall(tm, "$arg", Getattr(p, "emit:input")); + Replaceall(tm, "$input", Getattr(p, "emit:input")); + Replaceall(tm, "$owner", "R_SWIG_EXTERNAL"); Printf(outargs, "%s\n", tm); - p = Getattr(p,"tmap:argout:next"); + p = Getattr(p, "tmap:argout:next"); } else p = nextSibling(p); } @@ -2019,60 +2031,57 @@ int R::functionWrapper(Node *n) { String *actioncode = emit_action(n); /* Deal with the explicit return value. */ - if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) { + if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) { SwigType *retType = Getattr(n, "type"); - //Printf(stdout, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no"); + //Printf(stdout, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no"); /* if(SwigType_isarray(retType)) { - defineArrayAccessors(retType); - } */ + defineArrayAccessors(retType); + } */ - Replaceall(tm,"$1", Swig_cresult_name()); - Replaceall(tm,"$result", "r_ans"); + Replaceall(tm, "$1", Swig_cresult_name()); + Replaceall(tm, "$result", "r_ans"); replaceRClass(tm, retType); - if (GetFlag(n,"feature:new")) { + if (GetFlag(n, "feature:new")) { Replaceall(tm, "$owner", "R_SWIG_OWNER"); } else { - Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); + Replaceall(tm, "$owner", "R_SWIG_EXTERNAL"); } #if 0 - if(addCopyParam) { + if (addCopyParam) { Printf(f->code, "if(LOGICAL(s_swig_copy)[0]) {\n"); Printf(f->code, "/* Deal with returning a reference. */\nr_ans = R_NilValue;\n"); Printf(f->code, "}\n else {\n"); - } + } #endif Printf(f->code, "%s\n", tm); #if 0 - if(addCopyParam) - Printf(f->code, "}\n"); /* end of if(s_swig_copy) ... else { ... } */ + if (addCopyParam) + Printf(f->code, "}\n"); /* end of if(s_swig_copy) ... else { ... } */ #endif } else { - Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, - "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), fname); + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), fname); } - if(Len(outargs)) { + if (Len(outargs)) { Wrapper_add_local(f, "R_OutputValues", "SEXP R_OutputValues"); String *tmp = NewString(""); - if(!isVoidReturnType) + if (!isVoidReturnType) Printf(tmp, "Rf_protect(r_ans);\n"); - Printf(tmp, "Rf_protect(R_OutputValues = Rf_allocVector(VECSXP,%d));\nr_nprotect += %d;\n", - numOutArgs + !isVoidReturnType, - isVoidReturnType ? 1 : 2); + Printf(tmp, "Rf_protect(R_OutputValues = Rf_allocVector(VECSXP,%d));\nr_nprotect += %d;\n", numOutArgs + !isVoidReturnType, isVoidReturnType ? 1 : 2); - if(!isVoidReturnType) + if (!isVoidReturnType) Printf(tmp, "SET_VECTOR_ELT(R_OutputValues, 0, r_ans);\n"); Printf(tmp, "r_ans = R_OutputValues;\n"); Insert(outargs, 0, tmp); - Delete(tmp); + Delete(tmp); @@ -2088,7 +2097,7 @@ int R::functionWrapper(Node *n) { /* Look to see if there is any newfree cleanup code */ if (GetFlag(n, "feature:new")) { if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) { - Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */ + Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */ Printf(f->code, "%s\n", tm); } } @@ -2097,26 +2106,23 @@ int R::functionWrapper(Node *n) { /*If the user gave us something to convert the result in */ if ((tm = Swig_typemap_lookup("scoerceout", n, Swig_cresult_name(), sfun))) { - Replaceall(tm,"$source","ans"); - Replaceall(tm,"$result","ans"); + Replaceall(tm, "$source", "ans"); + Replaceall(tm, "$result", "ans"); replaceRClass(tm, Getattr(n, "type")); Chop(tm); } - Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname, - "', ", sargs, "PACKAGE='", Rpackage, "');\n", NIL); - if(Len(tm)) - { - Printf(sfun->code, "%s\n\n", tm); - if (constructor) - { - String *finalizer = NewString(iname); - Replace(finalizer, "new_", "", DOH_REPLACE_FIRST); - Printf(sfun->code, "reg.finalizer(ans@ref, delete_%s)\n", finalizer); - } - Printf(sfun->code, "ans\n"); + Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname, "', ", sargs, "PACKAGE='", Rpackage, "');\n", NIL); + if (Len(tm)) { + Printf(sfun->code, "%s\n\n", tm); + if (constructor) { + String *finalizer = NewString(iname); + Replace(finalizer, "new_", "", DOH_REPLACE_FIRST); + Printf(sfun->code, "reg.finalizer(ans@ref, delete_%s)\n", finalizer); } + Printf(sfun->code, "ans\n"); + } if (destructor) Printv(f->code, "R_ClearExternalPtr(self);\n", NIL); @@ -2125,27 +2131,23 @@ int R::functionWrapper(Node *n) { Printv(sfun->code, "\n}", NIL); /* Substitute the function name */ - Replaceall(f->code,"$symname",iname); + Replaceall(f->code, "$symname", iname); Wrapper_print(f, f_wrapper); Wrapper_print(sfun, sfile); Printf(sfun->code, "\n# End of %s\n", iname); tm = Swig_typemap_lookup("rtype", n, "", 0); - if(tm) { + if (tm) { SwigType *retType = Getattr(n, "type"); replaceRClass(tm, retType); - } - - Printv(sfile, "attr(`", sfname, "`, 'returnType') = '", - isVoidReturnType ? "void" : (tm ? tm : ""), - "'\n", NIL); - - if(nargs > 0) - Printv(sfile, "attr(`", sfname, "`, \"inputTypes\") = c(", - s_inputTypes, ")\n", NIL); - Printv(sfile, "class(`", sfname, "`) = c(\"SWIGFunction\", class('", - sfname, "'))\n\n", NIL); + } + + Printv(sfile, "attr(`", sfname, "`, 'returnType') = '", isVoidReturnType ? "void" : (tm ? tm : ""), "'\n", NIL); + + if (nargs > 0) + Printv(sfile, "attr(`", sfname, "`, \"inputTypes\") = c(", s_inputTypes, ")\n", NIL); + Printv(sfile, "class(`", sfname, "`) = c(\"SWIGFunction\", class('", sfname, "'))\n\n", NIL); if (memoryProfile) { Printv(sfile, "memory.profile()\n", NIL); @@ -2153,26 +2155,24 @@ int R::functionWrapper(Node *n) { if (aggressiveGc) { Printv(sfile, "gc()\n", NIL); } - // Printv(sfile, "setMethod('", name, "', '", name, "', ", iname, ")\n\n\n"); - /* If we are dealing with a method in an C++ class, then - add the name of the R function and its definition. + /* If we are dealing with a method in an C++ class, then + add the name of the R function and its definition. XXX need to figure out how to store the Wrapper if possible in the hash/list. Would like to be able to do this so that we can potentially insert - */ - if(processing_member_access_function || processing_class_member_function) { + */ + if (processing_member_access_function || processing_class_member_function) { addAccessor(member_name, sfun, iname); } - if (Getattr(n, "sym:overloaded") && - !Getattr(n, "sym:nextSibling")) { + if (Getattr(n, "sym:overloaded") && !Getattr(n, "sym:nextSibling")) { dispatchFunction(n); } - addRegistrationRoutine(wname, addCopyParam ? nargs +1 : nargs); + addRegistrationRoutine(wname, addCopyParam ? nargs + 1 : nargs); DelWrapper(f); DelWrapper(sfun); @@ -2193,21 +2193,20 @@ int R::constantWrapper(Node *n) { } /***************************************************** - Add the specified routine name to the collection of + Add the specified routine name to the collection of generated routines that are called from R functions. - This is used to register the routines with R for + This is used to register the routines with R for resolving symbols. rname - the name of the routine - nargs - the number of arguments it expects. + nargs - the number of arguments it expects. ******************************************************/ int R::addRegistrationRoutine(String *rname, int nargs) { - if(!registrationTable) + if (!registrationTable) registrationTable = NewHash(); - String *el = - NewStringf("{\"%s\", (DL_FUNC) &%s, %d}", rname, rname, nargs); - + String *el = NewStringf("{\"%s\", (DL_FUNC) &%s, %d}", rname, rname, nargs); + Setattr(registrationTable, rname, el); return SWIG_OK; @@ -2220,30 +2219,30 @@ int R::addRegistrationRoutine(String *rname, int nargs) { ******************************************************/ int R::outputRegistrationRoutines(File *out) { int i, n; - if(!registrationTable) - return(0); - if(inCPlusMode) + if (!registrationTable) + return (0); + if (inCPlusMode) Printf(out, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"); Printf(out, "#include \n\n"); - if(inCPlusMode) + if (inCPlusMode) Printf(out, "#ifdef __cplusplus\n}\n#endif\n\n"); Printf(out, "SWIGINTERN R_CallMethodDef CallEntries[] = {\n"); - + List *keys = Keys(registrationTable); n = Len(keys); - for(i = 0; i < n; i++) + for (i = 0; i < n; i++) Printf(out, " %s,\n", Getattr(registrationTable, Getitem(keys, i))); Printf(out, " {NULL, NULL, 0}\n};\n\n"); - if(!noInitializationCode) { + if (!noInitializationCode) { if (inCPlusMode) Printv(out, "extern \"C\" ", NIL); Printf(out, "SWIGEXPORT void R_init_%s(DllInfo *dll) {\n", Rpackage); Printf(out, "%sR_registerRoutines(dll, NULL, CallEntries, NULL, NULL);\n", tab4); - if(Len(s_init_routine)) { + if (Len(s_init_routine)) { Printf(out, "\n%s\n", s_init_routine); } Printf(out, "}\n"); @@ -2257,60 +2256,58 @@ int R::outputRegistrationRoutines(File *out) { /**************************************************************************** Process a struct, union or class declaration in the source code, or an anonymous typedef struct - + *****************************************************************************/ -//XXX What do we need to do here - +//XXX What do we need to do here - // Define an S4 class to refer to this. void R::registerClass(Node *n) { - String *name = Getattr(n, "name"); - String *kind = Getattr(n, "kind"); + String *name = Getattr(n, "name"); + String *kind = Getattr(n, "kind"); if (debugMode) Swig_print_node(n); String *sname = NewStringf("_p%s", SwigType_manglestr(name)); - if(!Getattr(SClassDefs, sname)) { + if (!Getattr(SClassDefs, sname)) { Setattr(SClassDefs, sname, sname); String *base; - if(Strcmp(kind, "class") == 0) { + if (Strcmp(kind, "class") == 0) { base = NewString(""); List *l = Getattr(n, "bases"); - if(Len(l)) { - Printf(base, "c("); - for(int i = 0; i < Len(l); i++) { - registerClass(Getitem(l, i)); - Printf(base, "'_p%s'%s", - SwigType_manglestr(Getattr(Getitem(l, i), "name")), - i < Len(l)-1 ? ", " : ""); - } - Printf(base, ")"); + if (Len(l)) { + Printf(base, "c("); + for (int i = 0; i < Len(l); i++) { + registerClass(Getitem(l, i)); + Printf(base, "'_p%s'%s", SwigType_manglestr(Getattr(Getitem(l, i), "name")), i < Len(l) - 1 ? ", " : ""); + } + Printf(base, ")"); } else { - base = NewString("'C++Reference'"); + base = NewString("'C++Reference'"); } - } else + } else base = NewString("'ExternalReference'"); Printf(s_classes, "setClass('%s', contains = %s)\n", sname, base); Delete(base); } - + } int R::classDeclaration(Node *n) { - String *name = Getattr(n, "name"); - String *kind = Getattr(n, "kind"); + String *name = Getattr(n, "name"); + String *kind = Getattr(n, "kind"); if (debugMode) Swig_print_node(n); registerClass(n); - + /* If we have a typedef union { ... } U, then we never get to see the typedef via a regular call to typedefHandler. Instead, */ - if(Getattr(n, "unnamed") && Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "typedef") == 0 - && Getattr(n, "tdname") && Strcmp(Getattr(n, "tdname"), name) == 0) { + if (Getattr(n, "unnamed") && Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "typedef") == 0 + && Getattr(n, "tdname") && Strcmp(Getattr(n, "tdname"), name) == 0) { if (debugMode) Printf(stdout, "Typedef in the class declaration for %s\n", name); // typedefHandler(n); @@ -2318,7 +2315,7 @@ int R::classDeclaration(Node *n) { bool opaque = GetFlag(n, "feature:opaque") ? true : false; - if(opaque) + if (opaque) opaqueClassDeclaration = name; int status = Language::classDeclaration(n); @@ -2326,76 +2323,72 @@ int R::classDeclaration(Node *n) { opaqueClassDeclaration = NULL; - // OutputArrayMethod(name, class_member_functions, sfile); + // OutputArrayMethod(name, class_member_functions, sfile); if (class_member_functions) OutputMemberReferenceMethod(name, 0, class_member_functions, sfile); if (class_member_set_functions) OutputMemberReferenceMethod(name, 1, class_member_set_functions, sfile); - if(class_member_functions) { + if (class_member_functions) { Delete(class_member_functions); class_member_functions = NULL; } - if(class_member_set_functions) { + if (class_member_set_functions) { Delete(class_member_set_functions); class_member_set_functions = NULL; } if (Getattr(n, "has_destructor")) { - Printf(sfile, "setMethod('delete', '_p%s', function(obj) {delete%s(obj)})\n", - getRClassName(Getattr(n, "name")), - getRClassName(Getattr(n, "name"))); + Printf(sfile, "setMethod('delete', '_p%s', function(obj) {delete%s(obj)})\n", getRClassName(Getattr(n, "name")), getRClassName(Getattr(n, "name"))); } - if(!opaque && !Strcmp(kind, "struct") && copyStruct) { + if (!opaque && !Strcmp(kind, "struct") && copyStruct) { - String *def = - NewStringf("setClass(\"%s\",\n%srepresentation(\n", name, tab4); + String *def = NewStringf("setClass(\"%s\",\n%srepresentation(\n", name, tab4); bool firstItem = true; - for(Node *c = firstChild(n); c; ) { + for (Node *c = firstChild(n); c;) { String *elName; String *tp; elName = Getattr(c, "name"); - + String *elKind = Getattr(c, "kind"); if (!Equal(elKind, "variable")) { - c = nextSibling(c); - continue; + c = nextSibling(c); + continue; } if (!Len(elName)) { - c = nextSibling(c); - continue; + c = nextSibling(c); + continue; } #if 0 tp = getRType(c); #else tp = Swig_typemap_lookup("rtype", c, "", 0); - if(!tp) { - c = nextSibling(c); - continue; + if (!tp) { + c = nextSibling(c); + continue; } if (Strstr(tp, "R_class")) { - c = nextSibling(c); - continue; + c = nextSibling(c); + continue; } - if (Strcmp(tp, "character") && - Strstr(Getattr(c, "decl"), "p.")) { - c = nextSibling(c); - continue; + if (Strcmp(tp, "character") && Strstr(Getattr(c, "decl"), "p.")) { + c = nextSibling(c); + continue; } if (!firstItem) { - Printf(def, ",\n"); - } - // else + Printf(def, ",\n"); + } + // else //XXX How can we tell if this is already done. - // SwigType_push(elType, elDecl); - - + // SwigType_push(elType, elDecl); + + // returns "" tp = processType(elType, c, NULL); - // Printf(stdout, " elType %p\n", elType); - // tp = getRClassNameCopyStruct(Getattr(c, "type"), 1); + // Printf(stdout, " elType %p\n", elType); + // tp = getRClassNameCopyStruct(Getattr(c, "type"), 1); #endif String *elNameT = replaceInitialDash(elName); Printf(def, "%s%s = \"%s\"", tab8, elNameT, tp); @@ -2431,13 +2424,13 @@ int R::classDeclaration(Node *n) { int R::generateCopyRoutines(Node *n) { Wrapper *copyToR = NewWrapper(); Wrapper *copyToC = NewWrapper(); - + String *name = Getattr(n, "name"); String *tdname = Getattr(n, "tdname"); String *kind = Getattr(n, "kind"); String *type; - if(Len(tdname)) { + if (Len(tdname)) { type = Copy(tdname); } else { type = NewStringf("%s %s", kind, name); @@ -2448,14 +2441,12 @@ int R::generateCopyRoutines(Node *n) { if (debugMode) Printf(stdout, "generateCopyRoutines: name = %s, %s\n", name, type); - Printf(copyToR->def, "CopyToR%s = function(value, obj = new(\"%s\"))\n{\n", - mangledName, name); - Printf(copyToC->def, "CopyToC%s = function(value, obj)\n{\n", - mangledName); + Printf(copyToR->def, "CopyToR%s = function(value, obj = new(\"%s\"))\n{\n", mangledName, name); + Printf(copyToC->def, "CopyToC%s = function(value, obj)\n{\n", mangledName); Node *c = firstChild(n); - for(; c; c = nextSibling(c)) { + for (; c; c = nextSibling(c)) { String *elName = Getattr(c, "name"); if (!Len(elName)) { continue; @@ -2466,14 +2457,13 @@ int R::generateCopyRoutines(Node *n) { } String *tp = Swig_typemap_lookup("rtype", c, "", 0); - if(!tp) { + if (!tp) { continue; } if (Strstr(tp, "R_class")) { continue; } - if (Strcmp(tp, "character") && - Strstr(Getattr(c, "decl"), "p.")) { + if (Strcmp(tp, "character") && Strstr(Getattr(c, "decl"), "p.")) { continue; } @@ -2485,26 +2475,25 @@ int R::generateCopyRoutines(Node *n) { Delete(elNameT); } 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); - + String *rclassName = getRClassNameCopyStruct(type, 0); // without the Ref. + Printf(sfile, "# Start definition of copy functions & methods for %s\n", rclassName); + Wrapper_print(copyToR, sfile); Printf(copyToC->code, "obj\n}\n\n"); Wrapper_print(copyToC, sfile); - - - Printf(sfile, "# Start definition of copy methods for %s\n", rclassName); - Printf(sfile, "setMethod('copyToR', '_p_%s', CopyToR%s);\n", rclassName, - mangledName); - Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s);\n\n", rclassName, - mangledName); - - Printf(sfile, "# End definition of copy methods for %s\n", rclassName); - Printf(sfile, "# End definition of copy functions & methods for %s\n", rclassName); - + + + Printf(sfile, "# Start definition of copy methods for %s\n", rclassName); + Printf(sfile, "setMethod('copyToR', '_p_%s', CopyToR%s);\n", rclassName, mangledName); + Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s);\n\n", rclassName, mangledName); + + Printf(sfile, "# End definition of copy methods for %s\n", rclassName); + Printf(sfile, "# End definition of copy functions & methods for %s\n", rclassName); + String *m = NewStringf("%sCopyToR", name); addNamespaceMethod(m); - char *tt = Char(m); tt[Len(m)-1] = 'C'; + char *tt = Char(m); + tt[Len(m) - 1] = 'C'; addNamespaceMethod(m); Delete(m); Delete(rclassName); @@ -2518,9 +2507,9 @@ int R::generateCopyRoutines(Node *n) { /***** - Called when there is a typedef to be invoked. + Called when there is a typedef to be invoked. - XXX Needs to be enhanced or split to handle the case where we have a + XXX Needs to be enhanced or split to handle the case where we have a typedef within a classDeclaration emission because the struct/union/etc. is anonymous. ******/ @@ -2532,14 +2521,13 @@ int R::typedefHandler(Node *n) { processType(tp, n); - if(Strncmp(type, "struct ", 7) == 0) { + if (Strncmp(type, "struct ", 7) == 0) { String *name = Getattr(n, "name"); char *trueName = Char(type); trueName += 7; if (debugMode) Printf(stdout, " Defining S class %s\n", trueName); - Printf(s_classes, "setClass('_p%s', contains = 'ExternalReference')\n", - SwigType_manglestr(name)); + Printf(s_classes, "setClass('_p%s', contains = 'ExternalReference')\n", SwigType_manglestr(name)); } return Language::typedefHandler(n); @@ -2550,21 +2538,20 @@ int R::typedefHandler(Node *n) { /********************* Called when processing a field in a "class", i.e. struct, union or actual class. We set a state variable so that we can correctly - interpret the resulting functionWrapper() call and understand that + interpret the resulting functionWrapper() call and understand that it is for a field element. **********************/ int R::membervariableHandler(Node *n) { SwigType *t = Getattr(n, "type"); processType(t, n, NULL); processing_member_access_function = 1; - member_name = Getattr(n,"sym:name"); + member_name = Getattr(n, "sym:name"); if (debugMode) - Printf(stdout, " name = %s, sym:name = %s\n", - Getattr(n, "name"), member_name); + Printf(stdout, " name = %s, sym:name = %s\n", Getattr(n, "name"), member_name); int status(Language::membervariableHandler(n)); - if(!opaqueClassDeclaration && debugMode) + if (!opaqueClassDeclaration && debugMode) Printf(stdout, " %s %s\n", Getattr(n, "name"), Getattr(n, "type")); processing_member_access_function = 0; @@ -2577,7 +2564,7 @@ int R::membervariableHandler(Node *n) { /* This doesn't seem to get used so leave it out for the moment. */ -String * R::runtimeCode() { +String *R::runtimeCode() { String *s = Swig_include_sys("rrun.swg"); if (!s) { Printf(stdout, "*** Unable to open 'rrun.swg'\n"); @@ -2588,7 +2575,7 @@ String * R::runtimeCode() { /** - Called when SWIG wants to initialize this + Called when SWIG wants to initialize this We initialize anythin we want here. Most importantly, tell SWIG where to find the files (e.g. r.swg) for this module. Use Swig_mark_arg() to tell SWIG that it is understood and not to throw an error. @@ -2610,41 +2597,41 @@ void R::main(int argc, char *argv[]) { this->Argc = argc; this->Argv = argv; - allow_overloading();// can we support this? + allow_overloading(); // can we support this? - for(int i = 0; i < argc; i++) { - if(strcmp(argv[i], "-package") == 0) { + for (int i = 0; i < argc; i++) { + if (strcmp(argv[i], "-package") == 0) { Swig_mark_arg(i); i++; Swig_mark_arg(i); Rpackage = argv[i]; - } else if(strcmp(argv[i], "-dll") == 0) { + } else if (strcmp(argv[i], "-dll") == 0) { Swig_mark_arg(i); i++; Swig_mark_arg(i); DllName = argv[i]; - } else if(strcmp(argv[i], "-help") == 0) { + } else if (strcmp(argv[i], "-help") == 0) { showUsage(); - } else if(strcmp(argv[i], "-namespace") == 0) { + } else if (strcmp(argv[i], "-namespace") == 0) { outputNamespaceInfo = true; Swig_mark_arg(i); - } else if(!strcmp(argv[i], "-no-init-code")) { + } else if (!strcmp(argv[i], "-no-init-code")) { noInitializationCode = true; Swig_mark_arg(i); - } else if(!strcmp(argv[i], "-c++")) { + } else if (!strcmp(argv[i], "-c++")) { inCPlusMode = true; Swig_mark_arg(i); Printf(s_classes, "setClass('C++Reference', contains = 'ExternalReference')\n"); - } else if(!strcmp(argv[i], "-debug")) { + } else if (!strcmp(argv[i], "-debug")) { debugMode = true; Swig_mark_arg(i); - } else if (!strcmp(argv[i],"-cppcast")) { + } else if (!strcmp(argv[i], "-cppcast")) { cppcast = true; Swig_mark_arg(i); - } else if (!strcmp(argv[i],"-nocppcast")) { + } else if (!strcmp(argv[i], "-nocppcast")) { cppcast = false; Swig_mark_arg(i); - } else if (!strcmp(argv[i],"-copystruct")) { + } else if (!strcmp(argv[i], "-copystruct")) { copyStruct = true; Swig_mark_arg(i); } else if (!strcmp(argv[i], "-nocopystruct")) { @@ -2683,13 +2670,12 @@ void R::main(int argc, char *argv[]) { Could make this work for String or File and then just store the resulting string rather than the collection of arguments and argc. */ -int R::outputCommandLineArguments(File *out) -{ - if(Argc < 1 || !Argv || !Argv[0]) - return(-1); +int R::outputCommandLineArguments(File *out) { + if (Argc < 1 || !Argv || !Argv[0]) + return (-1); Printf(out, "\n## Generated via the command line invocation:\n##\t"); - for(int i = 0; i < Argc ; i++) { + for (int i = 0; i < Argc; i++) { Printf(out, " %s", Argv[i]); } Printf(out, "\n\n\n"); @@ -2699,10 +2685,9 @@ int R::outputCommandLineArguments(File *out) -/* How SWIG instantiates an object from this module. +/* How SWIG instantiates an object from this module. See swigmain.cxx */ -extern "C" -Language *swig_r(void) { +extern "C" Language *swig_r(void) { return new R(); } @@ -2713,55 +2698,50 @@ Language *swig_r(void) { /* Needs to be reworked. */ -String * R::processType(SwigType *t, Node *n, int *nargs) { +String *R::processType(SwigType *t, Node *n, int *nargs) { //XXX Need to handle typedefs, e.g. // a type which is a typedef to a function pointer. SwigType *tmp = Getattr(n, "tdname"); if (debugMode) Printf(stdout, "processType %s (tdname = %s)\n", Getattr(n, "name"), tmp); - + SwigType *td = t; - if (expandTypedef(t) && - SwigType_istypedef(t)) { - SwigType *resolved = - SwigType_typedef_resolve_all(t); + if (expandTypedef(t) && SwigType_istypedef(t)) { + SwigType *resolved = SwigType_typedef_resolve_all(t); if (expandTypedef(resolved)) { td = Copy(resolved); } } - if(!td) { + if (!td) { int count = 0; String *b = getRTypeName(t, &count); - if(count && b && !Getattr(SClassDefs, b)) { + if (count && b && !Getattr(SClassDefs, b)) { if (debugMode) - Printf(stdout, " Defining class %s\n", b); + Printf(stdout, " Defining class %s\n", b); - Printf(s_classes, "setClass('%s', contains = 'ExternalReference')\n", b); + Printf(s_classes, "setClass('%s', contains = 'ExternalReference')\n", b); Setattr(SClassDefs, b, b); } - + } - if(td) + if (td) t = td; - if(SwigType_isfunctionpointer(t)) { + if (SwigType_isfunctionpointer(t)) { if (debugMode) - Printf(stdout, - " Defining pointer handler %s\n", t); - + Printf(stdout, " Defining pointer handler %s\n", t); + String *tmp = createFunctionPointerHandler(t, n, nargs); return tmp; } - #if 0 SwigType_isfunction(t) && SwigType_ispointer(t) #endif - - return NULL; + return NULL; } @@ -2773,8 +2753,3 @@ String * R::processType(SwigType *t, Node *n, int *nargs) { /*************************************************************************************/ - - - - - -- cgit v1.2.1 From 834a93f449bae04602c822cf8fd087814069772e Mon Sep 17 00:00:00 2001 From: Joseph C Wang Date: Tue, 11 Aug 2015 09:57:57 +0800 Subject: Revert "Merge pull request #494 from richardbeare/enumR2015B" This reverts commit cb8973f3139d4d31d731cd8020641a70c7c293b1, reversing changes made to ac3284f78c3af61027ffe4765ba50161670d929e. --- Examples/test-suite/r/Makefile.in | 3 +- Examples/test-suite/r/arrays_dimensionless_runme.R | 4 +- Examples/test-suite/r/funcptr_runme.R | 4 +- Examples/test-suite/r/ignore_parameter_runme.R | 4 +- Examples/test-suite/r/integers_runme.R | 4 +- Examples/test-suite/r/overload_method_runme.R | 4 +- Examples/test-suite/r/preproc_constants_runme.R | 11 - Examples/test-suite/r/r_copy_struct_runme.R | 4 +- Examples/test-suite/r/r_legacy_runme.R | 4 +- Examples/test-suite/r/r_sexp_runme.R | 4 +- Examples/test-suite/r/rename_simple_runme.R | 4 +- Examples/test-suite/r/simple_array_runme.R | 3 +- Examples/test-suite/r/unions_runme.R | 3 +- Source/Modules/r.cxx | 2081 ++++++++++---------- 14 files changed, 1065 insertions(+), 1072 deletions(-) delete mode 100644 Examples/test-suite/r/preproc_constants_runme.R diff --git a/Examples/test-suite/r/Makefile.in b/Examples/test-suite/r/Makefile.in index 2c9a2c3f2..d0489531f 100644 --- a/Examples/test-suite/r/Makefile.in +++ b/Examples/test-suite/r/Makefile.in @@ -5,7 +5,7 @@ LANGUAGE = r SCRIPTSUFFIX = _runme.R WRAPSUFFIX = .R -RUNR = R CMD BATCH --no-save --no-restore '--args $(SCRIPTDIR)' +RUNR = R CMD BATCH --no-save --no-restore srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -44,7 +44,6 @@ include $(srcdir)/../common.mk +$(swig_and_compile_multi_cpp) $(run_multitestcase) - # Runs the testcase. # # Run the runme if it exists. If not just load the R wrapper to diff --git a/Examples/test-suite/r/arrays_dimensionless_runme.R b/Examples/test-suite/r/arrays_dimensionless_runme.R index 4fc2541ff..9b97de2d8 100644 --- a/Examples/test-suite/r/arrays_dimensionless_runme.R +++ b/Examples/test-suite/r/arrays_dimensionless_runme.R @@ -1,6 +1,4 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) - +source("unittest.R") dyn.load(paste("arrays_dimensionless", .Platform$dynlib.ext, sep="")) source("arrays_dimensionless.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/funcptr_runme.R b/Examples/test-suite/r/funcptr_runme.R index c6127ef68..3d5281bfa 100644 --- a/Examples/test-suite/r/funcptr_runme.R +++ b/Examples/test-suite/r/funcptr_runme.R @@ -1,6 +1,4 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) - +source("unittest.R") dyn.load(paste("funcptr", .Platform$dynlib.ext, sep="")) source("funcptr.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/ignore_parameter_runme.R b/Examples/test-suite/r/ignore_parameter_runme.R index 612b70013..89e461d71 100644 --- a/Examples/test-suite/r/ignore_parameter_runme.R +++ b/Examples/test-suite/r/ignore_parameter_runme.R @@ -1,6 +1,4 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) - +source("unittest.R") dyn.load(paste("ignore_parameter", .Platform$dynlib.ext, sep="")) source("ignore_parameter.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/integers_runme.R b/Examples/test-suite/r/integers_runme.R index 6e2f63b70..e31099a3b 100644 --- a/Examples/test-suite/r/integers_runme.R +++ b/Examples/test-suite/r/integers_runme.R @@ -1,6 +1,4 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) - +source("unittest.R") dyn.load(paste("integers", .Platform$dynlib.ext, sep="")) source("integers.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/overload_method_runme.R b/Examples/test-suite/r/overload_method_runme.R index 790f3df10..afb590a74 100644 --- a/Examples/test-suite/r/overload_method_runme.R +++ b/Examples/test-suite/r/overload_method_runme.R @@ -1,6 +1,4 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) - +source("unittest.R") dyn.load(paste("overload_method", .Platform$dynlib.ext, sep="")) source("overload_method.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/preproc_constants_runme.R b/Examples/test-suite/r/preproc_constants_runme.R deleted file mode 100644 index 2a4a601eb..000000000 --- a/Examples/test-suite/r/preproc_constants_runme.R +++ /dev/null @@ -1,11 +0,0 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) - -dyn.load(paste("preproc_constants", .Platform$dynlib.ext, sep="")) -source("preproc_constants.R") -cacheMetaData(1) - -v <- enumToInteger('kValue', '_MyEnum') -print(v) -unittest(v,4) -q(save="no") diff --git a/Examples/test-suite/r/r_copy_struct_runme.R b/Examples/test-suite/r/r_copy_struct_runme.R index deadc61fe..21bd93b64 100644 --- a/Examples/test-suite/r/r_copy_struct_runme.R +++ b/Examples/test-suite/r/r_copy_struct_runme.R @@ -1,6 +1,4 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) - +source("unittest.R") dyn.load(paste("r_copy_struct", .Platform$dynlib.ext, sep="")) source("r_copy_struct.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/r_legacy_runme.R b/Examples/test-suite/r/r_legacy_runme.R index 3ca229ff8..7e5ade87f 100644 --- a/Examples/test-suite/r/r_legacy_runme.R +++ b/Examples/test-suite/r/r_legacy_runme.R @@ -1,6 +1,4 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) - +source("unittest.R") dyn.load(paste("r_legacy", .Platform$dynlib.ext, sep="")) source("r_legacy.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/r_sexp_runme.R b/Examples/test-suite/r/r_sexp_runme.R index e7b28a965..96b36e8af 100644 --- a/Examples/test-suite/r/r_sexp_runme.R +++ b/Examples/test-suite/r/r_sexp_runme.R @@ -1,6 +1,4 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) - +source("unittest.R") dyn.load(paste("r_sexp", .Platform$dynlib.ext, sep="")) source("r_sexp.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/rename_simple_runme.R b/Examples/test-suite/r/rename_simple_runme.R index 0628ca6c9..b25aeb844 100644 --- a/Examples/test-suite/r/rename_simple_runme.R +++ b/Examples/test-suite/r/rename_simple_runme.R @@ -1,6 +1,4 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) - +source("unittest.R") dyn.load(paste("rename_simple", .Platform$dynlib.ext, sep="")) source("rename_simple.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/simple_array_runme.R b/Examples/test-suite/r/simple_array_runme.R index fe70dc324..a6758dedd 100644 --- a/Examples/test-suite/r/simple_array_runme.R +++ b/Examples/test-suite/r/simple_array_runme.R @@ -1,5 +1,4 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) +source("unittest.R") dyn.load(paste("simple_array", .Platform$dynlib.ext, sep="")) source("simple_array.R") cacheMetaData(1) diff --git a/Examples/test-suite/r/unions_runme.R b/Examples/test-suite/r/unions_runme.R index fd148c7ef..76870d10c 100644 --- a/Examples/test-suite/r/unions_runme.R +++ b/Examples/test-suite/r/unions_runme.R @@ -1,5 +1,4 @@ -clargs <- commandArgs(trailing=TRUE) -source(file.path(clargs[1], "unittest.R")) +source("unittest.R") dyn.load(paste("unions", .Platform$dynlib.ext, sep="")) source("unions.R") cacheMetaData(1) diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 9f4455fd9..0e8e23063 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * This file is part of SWIG, which is licensed as a whole under version 3 + * This file is part of SWIG, which is licensed as a whole under version 3 * (or any later version) of the GNU General Public License. Some additional * terms also apply to certain portions of SWIG. The full details of the SWIG * license and copyrights can be found in the LICENSE and COPYRIGHT files @@ -12,11 +12,11 @@ * ----------------------------------------------------------------------------- */ #include "swigmod.h" -#include static const double DEFAULT_NUMBER = .0000123456712312312323; -static String *replaceInitialDash(const String *name) { +static String* replaceInitialDash(const String *name) +{ String *retval; if (!Strncmp(name, "_", 1)) { retval = Copy(name); @@ -27,57 +27,42 @@ static String *replaceInitialDash(const String *name) { return retval; } -static String *getRTypeName(SwigType *t, int *outCount = NULL) { +static String * getRTypeName(SwigType *t, int *outCount = NULL) { String *b = SwigType_base(t); List *els = SwigType_split(t); int count = 0; int i; - - if (Strncmp(b, "struct ", 7) == 0) + + if(Strncmp(b, "struct ", 7) == 0) Replace(b, "struct ", "", DOH_REPLACE_FIRST); - + /* Printf(stdout, " %s,base = %s\n", t, b); - for(i = 0; i < Len(els); i++) + for(i = 0; i < Len(els); i++) Printf(stdout, "%d) %s, ", i, Getitem(els,i)); Printf(stdout, "\n"); */ - - for (i = 0; i < Len(els); i++) { + + for(i = 0; i < Len(els); i++) { String *el = Getitem(els, i); - if (Strcmp(el, "p.") == 0 || Strncmp(el, "a(", 2) == 0) { + if(Strcmp(el, "p.") == 0 || Strncmp(el, "a(", 2) == 0) { count++; Append(b, "Ref"); } } - if (outCount) + if(outCount) *outCount = count; - + String *tmp = NewString(""); char *retName = Char(SwigType_manglestr(t)); Insert(tmp, 0, retName); return tmp; - + /* - if(count) - return(b); - - Delete(b); - return(NewString("")); - */ -} - -static String *getNamespacePrefix(const String *enumRef) { - // for use from enumDeclaration. - // returns the namespace part of a string - // Do we have any "::"? - String *name = NewString(enumRef); - - while (Strstr(name, "::")) { - name = NewStringf("%s", Strchr(name, ':') + 2); - } - String *result = NewStringWithSize(enumRef, Len(enumRef) - Len(name)); - - Delete(name); - return (result); + if(count) + return(b); + + Delete(b); + return(NewString("")); + */ } /********************* @@ -86,16 +71,16 @@ static String *getNamespacePrefix(const String *enumRef) { Now handles arrays, i.e. struct A[2] ****************/ -static String *getRClassName(String *retType, int /*addRef */ = 1, int upRef = 0) { +static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) { String *tmp = NewString(""); SwigType *resolved = SwigType_typedef_resolve_all(retType); char *retName = Char(SwigType_manglestr(resolved)); if (upRef) { Printf(tmp, "_p%s", retName); - } else { + } else{ Insert(tmp, 0, retName); } - + return tmp; /* #if 1 @@ -104,33 +89,33 @@ static String *getRClassName(String *retType, int /*addRef */ = 1, int upRef = if(!l || n == 0) { #ifdef R_SWIG_VERBOSE if (debugMode) - Printf(stdout, "SwigType_split return an empty list for %s\n", - retType); + Printf(stdout, "SwigType_split return an empty list for %s\n", + retType); #endif return(tmp); } - - + + String *el = Getitem(l, n-1); char *ptr = Char(el); if(strncmp(ptr, "struct ", 7) == 0) ptr += 7; - + Printf(tmp, "%s", ptr); - + if(addRef) { for(int i = 0; i < n; i++) { - if(Strcmp(Getitem(l, i), "p.") == 0 || - Strncmp(Getitem(l, i), "a(", 2) == 0) - Printf(tmp, "Ref"); + if(Strcmp(Getitem(l, i), "p.") == 0 || + Strncmp(Getitem(l, i), "a(", 2) == 0) + Printf(tmp, "Ref"); } } - + #else char *retName = Char(SwigType_manglestr(retType)); if(!retName) return(tmp); - + if(addRef) { while(retName && strlen(retName) > 1 && strncmp(retName, "_p", 2) == 0) { retName += 2; @@ -141,7 +126,7 @@ static String *getRClassName(String *retType, int /*addRef */ = 1, int upRef = retName ++; Insert(tmp, 0, retName); #endif - + return tmp; */ } @@ -152,47 +137,50 @@ static String *getRClassName(String *retType, int /*addRef */ = 1, int upRef = Now handles arrays, i.e. struct A[2] ****************/ -static String *getRClassNameCopyStruct(String *retType, int addRef) { +static String * getRClassNameCopyStruct(String *retType, int addRef) { String *tmp = NewString(""); - + #if 1 List *l = SwigType_split(retType); int n = Len(l); - if (!l || n == 0) { + if(!l || n == 0) { #ifdef R_SWIG_VERBOSE Printf(stdout, "SwigType_split return an empty list for %s\n", retType); #endif - return (tmp); + return(tmp); } - - - String *el = Getitem(l, n - 1); + + + String *el = Getitem(l, n-1); char *ptr = Char(el); - if (strncmp(ptr, "struct ", 7) == 0) + if(strncmp(ptr, "struct ", 7) == 0) ptr += 7; - + Printf(tmp, "%s", ptr); - - if (addRef) { - for (int i = 0; i < n; i++) { - if (Strcmp(Getitem(l, i), "p.") == 0 || Strncmp(Getitem(l, i), "a(", 2) == 0) - Printf(tmp, "Ref"); + + if(addRef) { + for(int i = 0; i < n; i++) { + if(Strcmp(Getitem(l, i), "p.") == 0 || + Strncmp(Getitem(l, i), "a(", 2) == 0) + Printf(tmp, "Ref"); } } + #else char *retName = Char(SwigType_manglestr(retType)); - if (!retName) - return (tmp); - - if (addRef) { - while (retName && strlen(retName) > 1 && strncmp(retName, "_p", 2) == 0) { + if(!retName) + return(tmp); + + if(addRef) { + while(retName && strlen(retName) > 1 && + strncmp(retName, "_p", 2) == 0) { retName += 2; Printf(tmp, "Ref"); } } - - if (retName[0] == '_') - retName++; + + if(retName[0] == '_') + retName ++; Insert(tmp, 0, retName); #endif @@ -209,8 +197,11 @@ static String *getRClassNameCopyStruct(String *retType, int addRef) { static void writeListByLine(List *l, File *out, bool quote = 0) { int i, n = Len(l); - for (i = 0; i < n; i++) - Printf(out, "%s%s%s%s%s\n", tab8, quote ? "\"" : "", Getitem(l, i), quote ? "\"" : "", i < n - 1 ? "," : ""); + for(i = 0; i < n; i++) + Printf(out, "%s%s%s%s%s\n", tab8, + quote ? "\"" :"", + Getitem(l, i), + quote ? "\"" :"", i < n-1 ? "," : ""); } @@ -240,13 +231,10 @@ static void showUsage() { } static bool expandTypedef(SwigType *t) { - if (SwigType_isenum(t)) - return false; + if (SwigType_isenum(t)) return false; String *prefix = SwigType_prefix(t); - if (Strncmp(prefix, "f", 1)) - return false; - if (Strncmp(prefix, "p.f", 3)) - return false; + if (Strncmp(prefix, "f", 1)) return false; + if (Strncmp(prefix, "p.f", 3)) return false; return true; } @@ -258,11 +246,11 @@ static bool expandTypedef(SwigType *t) { static int addCopyParameter(SwigType *type) { int ok = 0; ok = Strncmp(type, "struct ", 7) == 0 || Strncmp(type, "p.struct ", 9) == 0; - if (!ok) { + if(!ok) { ok = Strncmp(type, "p.", 2); } - return (ok); + return(ok); } static void replaceRClass(String *tm, SwigType *type) { @@ -272,28 +260,25 @@ static void replaceRClass(String *tm, SwigType *type) { Replaceall(tm, "$R_class", tmp); Replaceall(tm, "$*R_class", tmp_base); Replaceall(tm, "$&R_class", tmp_ref); - Delete(tmp); - Delete(tmp_base); - Delete(tmp_ref); + Delete(tmp); Delete(tmp_base); Delete(tmp_ref); } static double getNumber(String *value) { double d = DEFAULT_NUMBER; - if (Char(value)) { - if (sscanf(Char(value), "%lf", &d) != 1) - return (DEFAULT_NUMBER); + if(Char(value)) { + if(sscanf(Char(value), "%lf", &d) != 1) + return(DEFAULT_NUMBER); } - return (d); + return(d); } - -class R:public Language { +class R : public Language { public: R(); void registerClass(Node *n); void main(int argc, char *argv[]); int top(Node *n); - + void dispatchFunction(Node *n); int functionWrapper(Node *n); int constantWrapper(Node *n); @@ -305,90 +290,99 @@ public: int membervariableHandler(Node *n); int typedefHandler(Node *n); - static List *Swig_overload_rank(Node *n, bool script_lang_wrapping); + static List *Swig_overload_rank(Node *n, + bool script_lang_wrapping); int memberfunctionHandler(Node *n) { if (debugMode) - Printf(stdout, " %s %s\n", Getattr(n, "name"), Getattr(n, "type")); + Printf(stdout, " %s %s\n", + Getattr(n, "name"), + Getattr(n, "type")); member_name = Getattr(n, "sym:name"); processing_class_member_function = 1; - int status = Language::memberfunctionHandler(n); - processing_class_member_function = 0; - return status; + int status = Language::memberfunctionHandler(n); + processing_class_member_function = 0; + return status; } - /* Grab the name of the current class being processed so that we can - deal with members of that class. */ int classHandler(Node *n) { - if (!ClassMemberTable) - ClassMemberTable = NewHash(); + /* Grab the name of the current class being processed so that we can + deal with members of that class. */ + int classHandler(Node *n){ + if(!ClassMemberTable) + ClassMemberTable = NewHash(); + class_name = Getattr(n, "name"); int status = Language::classHandler(n); - + class_name = NULL; return status; } // Not used: String *runtimeCode(); - + protected: int addRegistrationRoutine(String *rname, int nargs); int outputRegistrationRoutines(File *out); - + int outputCommandLineArguments(File *out); - int generateCopyRoutines(Node *n); + int generateCopyRoutines(Node *n); int DumpCode(Node *n); - + int OutputMemberReferenceMethod(String *className, int isSet, List *el, File *out); int OutputArrayMethod(String *className, List *el, File *out); int OutputClassMemberTable(Hash *tb, File *out); int OutputClassMethodsTable(File *out); int OutputClassAccessInfo(Hash *tb, File *out); - + int defineArrayAccessors(SwigType *type); - + void addNamespaceFunction(String *name) { - if (!namespaceFunctions) + if(!namespaceFunctions) namespaceFunctions = NewList(); Append(namespaceFunctions, name); } void addNamespaceMethod(String *name) { - if (!namespaceMethods) + if(!namespaceMethods) namespaceMethods = NewList(); Append(namespaceMethods, name); } - - String *processType(SwigType *t, Node *n, int *nargs = NULL); + + String* processType(SwigType *t, Node *n, int *nargs = NULL); String *createFunctionPointerHandler(SwigType *t, Node *n, int *nargs); int addFunctionPointerProxy(String *name, Node *n, SwigType *t, String *s_paramTypes) { /*XXX Do we need to put the t in there to get the return type later. */ - if (!functionPointerProxyTable) + if(!functionPointerProxyTable) functionPointerProxyTable = NewHash(); - + Setattr(functionPointerProxyTable, name, n); - + Setattr(SClassDefs, name, name); - Printv(s_classes, "setClass('", - name, - "',\n", tab8, - "prototype = list(parameterTypes = c(", s_paramTypes, "),\n", - tab8, tab8, tab8, "returnType = '", SwigType_manglestr(t), "'),\n", tab8, "contains = 'CRoutinePointer')\n\n##\n", NIL); - + Printv(s_classes, "setClass('", + name, + "',\n", tab8, + "prototype = list(parameterTypes = c(", s_paramTypes, "),\n", + tab8, tab8, tab8, + "returnType = '", SwigType_manglestr(t), "'),\n", tab8, + "contains = 'CRoutinePointer')\n\n##\n", NIL); + return SWIG_OK; } - - - void addSMethodInfo(String *name, String *argType, int nargs); - // Simple initialization such as constant strings that can be reused. - void init(); - - - void addAccessor(String *memberName, Wrapper *f, String *name, int isSet = -1); - + + + void addSMethodInfo(String *name, + String *argType, int nargs); + // Simple initialization such as constant strings that can be reused. + void init(); + + + void addAccessor(String *memberName, Wrapper *f, + String *name, int isSet = -1); + static int getFunctionPointerNumArgs(Node *n, SwigType *tt); -protected: +protected: bool copyStruct; bool memoryProfile; bool aggressiveGc; @@ -406,88 +400,95 @@ protected: String *s_init; String *s_init_routine; String *s_namespace; - - // State variables that carry information across calls to functionWrapper() - // from member accessors and class declarations. + + // State variables that carry information across calls to functionWrapper() + // from member accessors and class declarations. String *opaqueClassDeclaration; int processing_variable; int processing_member_access_function; String *member_name; String *class_name; - - + + int processing_class_member_function; List *class_member_functions; List *class_member_set_functions; - + /* */ Hash *ClassMemberTable; Hash *ClassMethodsTable; Hash *SClassDefs; Hash *SMethodInfo; - - // Information about routines that are generated and to be registered with - // R for dynamic lookup. + + // Information about routines that are generated and to be registered with + // R for dynamic lookup. Hash *registrationTable; Hash *functionPointerProxyTable; - + List *namespaceFunctions; List *namespaceMethods; - List *namespaceClasses; // Probably can do this from ClassMemberTable. - - - // Store a copy of the command line. - // Need only keep a string that has it formatted. + List *namespaceClasses; // Probably can do this from ClassMemberTable. + + + // Store a copy of the command line. + // Need only keep a string that has it formatted. char **Argv; - int Argc; + int Argc; bool inCPlusMode; - + // State variables that we remember from the command line settings // potentially that govern the code we generate. String *DllName; String *Rpackage; - bool noInitializationCode; - bool outputNamespaceInfo; - + bool noInitializationCode; + bool outputNamespaceInfo; + String *UnProtectWrapupCode; // Static members static bool debugMode; }; -R::R(): -copyStruct(false), -memoryProfile(false), -aggressiveGc(false), -sfile(0), -f_init(0), -s_classes(0), -f_begin(0), -f_runtime(0), -f_wrapper(0), -s_header(0), -f_wrappers(0), -s_init(0), -s_init_routine(0), -s_namespace(0), -opaqueClassDeclaration(0), -processing_variable(0), -processing_member_access_function(0), -member_name(0), -class_name(0), -processing_class_member_function(0), -class_member_functions(0), -class_member_set_functions(0), -ClassMemberTable(0), -ClassMethodsTable(0), -SClassDefs(0), -SMethodInfo(0), -registrationTable(0), -functionPointerProxyTable(0), -namespaceFunctions(0), -namespaceMethods(0), -namespaceClasses(0), -Argv(0), Argc(0), inCPlusMode(false), DllName(0), Rpackage(0), noInitializationCode(false), outputNamespaceInfo(false), UnProtectWrapupCode(0) { +R::R() : + copyStruct(false), + memoryProfile(false), + aggressiveGc(false), + sfile(0), + f_init(0), + s_classes(0), + f_begin(0), + f_runtime(0), + f_wrapper(0), + s_header(0), + f_wrappers(0), + s_init(0), + s_init_routine(0), + s_namespace(0), + opaqueClassDeclaration(0), + processing_variable(0), + processing_member_access_function(0), + member_name(0), + class_name(0), + processing_class_member_function(0), + class_member_functions(0), + class_member_set_functions(0), + ClassMemberTable(0), + ClassMethodsTable(0), + SClassDefs(0), + SMethodInfo(0), + registrationTable(0), + functionPointerProxyTable(0), + namespaceFunctions(0), + namespaceMethods(0), + namespaceClasses(0), + Argv(0), + Argc(0), + inCPlusMode(false), + DllName(0), + Rpackage(0), + noInitializationCode(false), + outputNamespaceInfo(false), + UnProtectWrapupCode(0) { } bool R::debugMode = false; @@ -507,44 +508,43 @@ int R::getFunctionPointerNumArgs(Node *n, SwigType *tt) { void R::addSMethodInfo(String *name, String *argType, int nargs) { (void) argType; - - if (!SMethodInfo) + + if(!SMethodInfo) SMethodInfo = NewHash(); if (debugMode) Printf(stdout, "[addMethodInfo] %s\n", name); Hash *tb = Getattr(SMethodInfo, name); - if (!tb) { + if(!tb) { tb = NewHash(); Setattr(SMethodInfo, name, tb); } String *str = Getattr(tb, "max"); int max = -1; - if (str) + if(str) max = atoi(Char(str)); - if (max < nargs) { - if (str) - Delete(str); + if(max < nargs) { + if(str) Delete(str); str = NewStringf("%d", max); Setattr(tb, "max", str); } } - + /* Returns the name of the new routine. */ -String *R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { +String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { String *funName = SwigType_manglestr(t); - + /* See if we have already processed this one. */ - if (functionPointerProxyTable && Getattr(functionPointerProxyTable, funName)) + if(functionPointerProxyTable && Getattr(functionPointerProxyTable, funName)) return funName; - + if (debugMode) - Printf(stdout, " Defining %s\n", t); - + Printf(stdout, " Defining %s\n", t); + SwigType *rettype = Copy(Getattr(n, "type")); SwigType *funcparams = SwigType_functionpointer_decompose(rettype); String *rtype = SwigType_str(rettype, 0); @@ -558,13 +558,13 @@ String *R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { Printf(stdout, "Type: %s\n", t); Printf(stdout, "Return type: %s\n", SwigType_base(t)); } - + bool isVoidType = Strcmp(rettype, "void") == 0; if (debugMode) Printf(stdout, "%s is void ? %s (%s)\n", funName, isVoidType ? "yes" : "no", rettype); - + Wrapper *f = NewWrapper(); - + /* Go through argument list, attach lnames for arguments */ int i = 0; Parm *p = parms; @@ -573,14 +573,14 @@ String *R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { String *lname; if (!arg && Cmp(Getattr(p, "type"), "void")) { - lname = NewStringf("s_arg%d", i + 1); + lname = NewStringf("s_arg%d", i+1); Setattr(p, "name", lname); } else lname = arg; Setattr(p, "lname", lname); } - + Swig_typemap_attach_parms("out", parms, f); Swig_typemap_attach_parms("scoerceout", parms, f); Swig_typemap_attach_parms("scheck", parms, f); @@ -595,9 +595,9 @@ String *R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { Wrapper_add_local(f, "r_swig_cb_data", "RCallbackFunctionData *r_swig_cb_data = R_SWIG_getCallbackFunctionData()"); String *lvar = NewString("r_swig_cb_data"); - Wrapper_add_local(f, "r_tmp", "SEXP r_tmp"); // for use in converting arguments to R objects for call. - Wrapper_add_local(f, "r_nprotect", "int r_nprotect = 0"); // for use in converting arguments to R objects for call. - Wrapper_add_local(f, "r_vmax", "char * r_vmax= 0"); // for use in converting arguments to R objects for call. + Wrapper_add_local(f, "r_tmp", "SEXP r_tmp"); // for use in converting arguments to R objects for call. + Wrapper_add_local(f, "r_nprotect", "int r_nprotect = 0"); // for use in converting arguments to R objects for call. + Wrapper_add_local(f, "r_vmax", "char * r_vmax= 0"); // for use in converting arguments to R objects for call. // Add local for error code in return value. This is not in emit_return_variable because that assumes an out typemap // whereas the type makes are reverse @@ -605,125 +605,136 @@ String *R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { p = parms; int nargs = ParmList_len(parms); - if (numArgs) { + if(numArgs) { *numArgs = nargs; if (debugMode) Printf(stdout, "Setting number of parameters to %d\n", *numArgs); - } + } String *setExprElements = NewString(""); - + String *s_paramTypes = NewString(""); - for (i = 0; p; i++) { + for(i = 0; p; i++) { SwigType *tt = Getattr(p, "type"); SwigType *name = Getattr(p, "name"); String *tm = Getattr(p, "tmap:out"); - Printf(f->def, "%s %s", SwigType_str(tt, 0), name); - if (tm) { + Printf(f->def, "%s %s", SwigType_str(tt, 0), name); + if(tm) { Replaceall(tm, "$1", name); if (SwigType_isreference(tt)) { - String *tmp = NewString(""); + String *tmp = NewString(""); Append(tmp, "*"); - Append(tmp, name); - Replaceall(tm, tmp, name); + Append(tmp, name); + Replaceall(tm, tmp, name); } Replaceall(tm, "$result", "r_tmp"); - replaceRClass(tm, Getattr(p, "type")); - Replaceall(tm, "$owner", "R_SWIG_EXTERNAL"); - } - + replaceRClass(tm, Getattr(p,"type")); + Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); + } + Printf(setExprElements, "%s\n", tm); Printf(setExprElements, "SETCAR(r_swig_cb_data->el, %s);\n", "r_tmp"); Printf(setExprElements, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n"); - + Printf(s_paramTypes, "'%s'", SwigType_manglestr(tt)); - - + + p = nextSibling(p); - if (p) { + if(p) { Printf(f->def, ", "); Printf(s_paramTypes, ", "); } } - - Printf(f->def, ") {\n"); - + + Printf(f->def, ") {\n"); + Printf(f->code, "Rf_protect(%s->expr = Rf_allocVector(LANGSXP, %d));\n", lvar, nargs + 1); Printf(f->code, "r_nprotect++;\n"); Printf(f->code, "r_swig_cb_data->el = r_swig_cb_data->expr;\n\n"); - + Printf(f->code, "SETCAR(r_swig_cb_data->el, r_swig_cb_data->fun);\n"); Printf(f->code, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n"); - + Printf(f->code, "%s\n\n", setExprElements); - - Printv(f->code, "r_swig_cb_data->retValue = R_tryEval(", "r_swig_cb_data->expr,", " R_GlobalEnv,", " &r_swig_cb_data->errorOccurred", ");\n", NIL); - + + Printv(f->code, "r_swig_cb_data->retValue = R_tryEval(", + "r_swig_cb_data->expr,", + " R_GlobalEnv,", + " &r_swig_cb_data->errorOccurred", + ");\n", + NIL); + Printv(f->code, "\n", - "if(r_swig_cb_data->errorOccurred) {\n", - "R_SWIG_popCallbackFunctionData(1);\n", "Rf_error(\"error in calling R function as a function pointer (", funName, ")\");\n", "}\n", NIL); - - - - if (!isVoidType) { - /* Need to deal with the return type of the function pointer, not the function pointer itself. + "if(r_swig_cb_data->errorOccurred) {\n", + "R_SWIG_popCallbackFunctionData(1);\n", + "Rf_error(\"error in calling R function as a function pointer (", + funName, + ")\");\n", + "}\n", + NIL); + + + + if(!isVoidType) { + /* Need to deal with the return type of the function pointer, not the function pointer itself. So build a new node that has the relevant pieces. 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? - */ + */ Parm *bbase = NewParmNode(rettype, n); String *returnTM = Swig_typemap_lookup("in", bbase, Swig_cresult_name(), f); - if (returnTM) { + if(returnTM) { String *tm = returnTM; - Replaceall(tm, "$input", "r_swig_cb_data->retValue"); - Replaceall(tm, "$target", Swig_cresult_name()); + Replaceall(tm,"$input", "r_swig_cb_data->retValue"); + Replaceall(tm,"$target", Swig_cresult_name()); replaceRClass(tm, rettype); - Replaceall(tm, "$owner", "R_SWIG_EXTERNAL"); - Replaceall(tm, "$disown", "0"); + Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); + Replaceall(tm,"$disown","0"); Printf(f->code, "%s\n", tm); } Delete(bbase); } - + Printv(f->code, "R_SWIG_popCallbackFunctionData(1);\n", NIL); Printv(f->code, "\n", UnProtectWrapupCode, NIL); - if (SwigType_isreference(rettype)) { - Printv(f->code, "return *", Swig_cresult_name(), ";\n", NIL); - } else if (!isVoidType) - Printv(f->code, "return ", Swig_cresult_name(), ";\n", NIL); - + if (SwigType_isreference(rettype)) { + Printv(f->code, "return *", Swig_cresult_name(), ";\n", NIL); + } else if(!isVoidType) + Printv(f->code, "return ", Swig_cresult_name(), ";\n", NIL); + Printv(f->code, "\n}\n", NIL); Replaceall(f->code, "SWIG_exception_fail", "SWIG_exception_noreturn"); - + /* To coerce correctly in S, we really want to have an extra/intermediate - function that handles the scoerceout. + function that handles the scoerceout. We need to check if any of the argument types have an entry in that map. If none do, the ignore and call the function straight. Otherwise, generate the a marshalling function. Need to be able to find it in S. Or use an entirely generic one that evaluates the expressions. Handle errors in the evaluation of the function by restoring - the stack, if there is one in use for this function (i.e. no + the stack, if there is one in use for this function (i.e. no userData). - */ - + */ + Wrapper_print(f, f_wrapper); - + addFunctionPointerProxy(funName, n, t, s_paramTypes); Delete(s_paramTypes); Delete(rtype); Delete(rettype); Delete(funcparams); DelWrapper(f); - + return funName; } void R::init() { - UnProtectWrapupCode = NewStringf("%s", "vmaxset(r_vmax);\nif(r_nprotect) Rf_unprotect(r_nprotect);\n\n"); - + UnProtectWrapupCode = + NewStringf("%s", "vmaxset(r_vmax);\nif(r_nprotect) Rf_unprotect(r_nprotect);\n\n"); + SClassDefs = NewHash(); - + sfile = NewString(""); f_init = NewString(""); s_header = NewString(""); @@ -750,18 +761,18 @@ int R::cDeclaration(Node *n) { /** Method from Language that is called to start the entire - processing off, i.e. the generation of the code. + processing off, i.e. the generation of the code. It is called after the input has been read and parsed. Here we open the output streams and generate the code. ***/ int R::top(Node *n) { String *module = Getattr(n, "name"); - if (!Rpackage) + if(!Rpackage) Rpackage = Copy(module); - if (!DllName) + if(!DllName) DllName = Copy(module); - if (outputNamespaceInfo) { + if(outputNamespaceInfo) { s_namespace = NewString(""); Swig_register_filebyname("snamespace", s_namespace); Printf(s_namespace, "useDynLib(%s)\n", DllName); @@ -786,7 +797,7 @@ int R::top(Node *n) { Printf(f_runtime, "#define SWIGR\n"); Printf(f_runtime, "\n"); - + Swig_banner_target_lang(s_init, "#"); outputCommandLineArguments(s_init); @@ -801,17 +812,17 @@ int R::top(Node *n) { Printf(f_wrapper, "#endif\n"); String *type_table = NewString(""); - SwigType_emit_type_table(f_runtime, f_wrapper); + SwigType_emit_type_table(f_runtime,f_wrapper); Delete(type_table); - if (ClassMemberTable) { + if(ClassMemberTable) { //XXX OutputClassAccessInfo(ClassMemberTable, sfile); Delete(ClassMemberTable); ClassMemberTable = NULL; } - Printf(f_init, "}\n"); - if (registrationTable) + Printf(f_init,"}\n"); + if(registrationTable) outputRegistrationRoutines(f_init); /* Now arrange to write the 2 files - .S and .c. */ @@ -837,35 +848,35 @@ int R::top(Node *n) { ****************************************************/ int R::DumpCode(Node *n) { String *output_filename = NewString(""); - - + + /* The name of the file in which we will generate the S code. */ Printf(output_filename, "%s%s.R", SWIG_output_directory(), Rpackage); - + #ifdef R_SWIG_VERBOSE Printf(stdout, "Writing S code to %s\n", output_filename); #endif - + File *scode = NewFile(output_filename, "w", SWIG_output_files()); if (!scode) { FileErrorDisplay(output_filename); SWIG_exit(EXIT_FAILURE); } Delete(output_filename); - - + + Printf(scode, "%s\n\n", s_init); Printf(scode, "%s\n\n", s_classes); Printf(scode, "%s\n", sfile); - + Delete(scode); - String *outfile = Getattr(n, "outfile"); - File *runtime = NewFile(outfile, "w", SWIG_output_files()); + String *outfile = Getattr(n,"outfile"); + File *runtime = NewFile(outfile,"w", SWIG_output_files()); if (!runtime) { FileErrorDisplay(outfile); SWIG_exit(EXIT_FAILURE); } - + Printf(runtime, "%s", f_begin); Printf(runtime, "%s\n", f_runtime); Printf(runtime, "%s\n", s_header); @@ -874,7 +885,7 @@ int R::DumpCode(Node *n) { Delete(runtime); - if (outputNamespaceInfo) { + if(outputNamespaceInfo) { output_filename = NewString(""); Printf(output_filename, "%sNAMESPACE", SWIG_output_directory()); File *ns = NewFile(output_filename, "w", SWIG_output_files()); @@ -883,7 +894,7 @@ int R::DumpCode(Node *n) { SWIG_exit(EXIT_FAILURE); } Delete(output_filename); - + Printf(ns, "%s\n", s_namespace); Printf(ns, "\nexport(\n"); @@ -902,7 +913,7 @@ int R::DumpCode(Node *n) { /* - We may need to do more.... so this is left as a + We may need to do more.... so this is left as a stub for the moment. */ int R::OutputClassAccessInfo(Hash *tb, File *out) { @@ -914,28 +925,28 @@ int R::OutputClassAccessInfo(Hash *tb, File *out) { /************************************************************************ Currently this just writes the information collected about the different methods of the C++ classes that have been processed - to the console. + to the console. This will be used later to define S4 generics and methods. **************************************************************************/ int R::OutputClassMethodsTable(File *) { Hash *tb = ClassMethodsTable; - - if (!tb) + + if(!tb) return SWIG_OK; - + List *keys = Keys(tb); String *key; int i, n = Len(keys); if (debugMode) { - for (i = 0; i < n; i++) { + for(i = 0; i < n ; i++ ) { key = Getitem(keys, i); Printf(stdout, "%d) %s\n", i, key); List *els = Getattr(tb, key); int nels = Len(els); Printf(stdout, "\t"); - for (int j = 0; j < nels; j += 2) { - Printf(stdout, "%s%s", Getitem(els, j), j < nels - 1 ? ", " : ""); - Printf(stdout, "%s\n", Getitem(els, j + 1)); + for(int j = 0; j < nels; j+=2) { + Printf(stdout, "%s%s", Getitem(els, j), j < nels - 1 ? ", " : ""); + Printf(stdout, "%s\n", Getitem(els, j+1)); } Printf(stdout, "\n"); } @@ -946,88 +957,89 @@ int R::OutputClassMethodsTable(File *) { /* - Iterate over the _set and <>_get + Iterate over the _set and <>_get elements and generate the $ and $<- functions that provide constrained access to the member fields in these elements. tb - a hash table that is built up in functionWrapper as we process each membervalueHandler. - The entries are indexed by _set and + The entries are indexed by _set and _get. Each entry is a List *. - + out - the stram where the code is to be written. This is the S code stream as we generate only S code here.. */ int R::OutputClassMemberTable(Hash *tb, File *out) { List *keys = Keys(tb), *el; - + String *key; int i, n = Len(keys); /* Loop over all the _set and _get entries in the table. */ - - if (n && outputNamespaceInfo) { + + if(n && outputNamespaceInfo) { Printf(s_namespace, "exportClasses("); } - for (i = 0; i < n; i++) { + for(i = 0; i < n; i++) { key = Getitem(keys, i); el = Getattr(tb, key); - + String *className = Getitem(el, 0); char *ptr = Char(key); ptr = &ptr[Len(key) - 3]; int isSet = strcmp(ptr, "set") == 0; - - // OutputArrayMethod(className, el, out); + + // OutputArrayMethod(className, el, out); OutputMemberReferenceMethod(className, isSet, el, out); - - if (outputNamespaceInfo) - Printf(s_namespace, "\"%s\"%s", className, i < n - 1 ? "," : ""); + + if(outputNamespaceInfo) + Printf(s_namespace, "\"%s\"%s", className, i < n-1 ? "," : ""); } - if (n && outputNamespaceInfo) { + if(n && outputNamespaceInfo) { Printf(s_namespace, ")\n"); } - + return n; } /******************************************************************* - Write the methods for $ or $<- for accessing a member field in an + Write the methods for $ or $<- for accessing a member field in an struct or union (or class). className - the name of the struct or union (e.g. Bar for struct Bar) - isSet - a logical value indicating whether the method is for + isSet - a logical value indicating whether the method is for modifying ($<-) or accessing ($) the member field. el - a list of length 2 * # accessible member elements + 1. - The first element is the name of the class. + The first element is the name of the class. The other pairs are member name and the name of the R function to access it. out - the stream where we write the code. ********************************************************************/ -int R::OutputMemberReferenceMethod(String *className, int isSet, List *el, File *out) { +int R::OutputMemberReferenceMethod(String *className, int isSet, + List *el, File *out) { int numMems = Len(el), j; int varaccessor = 0; - if (numMems == 0) + if (numMems == 0) return SWIG_OK; - + Wrapper *f = NewWrapper(), *attr = NewWrapper(); - + Printf(f->def, "function(x, name%s)", isSet ? ", value" : ""); Printf(attr->def, "function(x, i, j, ...%s)", isSet ? ", value" : ""); - + Printf(f->code, "{\n"); Printf(f->code, "%saccessorFuns = list(", tab8); Node *itemList = NewHash(); bool has_prev = false; - for (j = 0; j < numMems; j += 3) { + for(j = 0; j < numMems; j+=3) { String *item = Getitem(el, j); - if (Getattr(itemList, item)) + if (Getattr(itemList, item)) continue; Setattr(itemList, item, "1"); - + String *dup = Getitem(el, j + 1); char *ptr = Char(dup); ptr = &ptr[Len(dup) - 3]; - + if (!strcmp(ptr, "get")) varaccessor++; @@ -1043,7 +1055,7 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, List *el, File } else { pitem = Copy(item); } - if (has_prev) + if (has_prev) Printf(f->code, ", "); Printf(f->code, "'%s' = %s", pitem, dup); has_prev = true; @@ -1051,102 +1063,114 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, List *el, File } Delete(itemList); Printf(f->code, ");\n"); - + if (!isSet && varaccessor > 0) { Printf(f->code, "%svaccessors = c(", tab8); int vcount = 0; - for (j = 0; j < numMems; j += 3) { + for(j = 0; j < numMems; j+=3) { String *item = Getitem(el, j); String *dup = Getitem(el, j + 1); char *ptr = Char(dup); ptr = &ptr[Len(dup) - 3]; - + if (!strcmp(ptr, "get")) { - vcount++; - Printf(f->code, "'%s'%s", item, vcount < varaccessor ? ", " : ""); + vcount++; + Printf(f->code, "'%s'%s", item, vcount < varaccessor ? ", " : ""); } } Printf(f->code, ");\n"); } - - + + /* Printv(f->code, tab8, - "idx = pmatch(name, names(accessorFuns))\n", - tab8, - "if(is.na(idx)) {\n", - tab8, tab4, - "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", tab8, "if(is.na(idx)) \n", tab8, tab4, NIL); - Printf(f->code, "return(callNextMethod(x, name%s));\n", isSet ? ", value" : ""); + "idx = pmatch(name, names(accessorFuns))\n", + tab8, + "if(is.na(idx)) {\n", + tab8, tab4, + "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", + tab8, + "if(is.na(idx)) \n", + tab8, tab4, NIL); + Printf(f->code, "return(callNextMethod(x, name%s));\n", + isSet ? ", value" : ""); Printv(f->code, tab8, "f = accessorFuns[[idx]];\n", NIL); - if (isSet) { + 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. } else { if (varaccessor) { - Printv(f->code, tab8, "if (is.na(match(name, vaccessors))) function(...){f(x, ...)} else f(x);\n", NIL); + Printv(f->code, tab8, + "if (is.na(match(name, vaccessors))) function(...){f(x, ...)} else f(x);\n", NIL); } else { Printv(f->code, tab8, "function(...){f(x, ...)};\n", NIL); } } Printf(f->code, "}\n"); - - + + Printf(out, "# Start of accessor method for %s\n", className); - Printf(out, "setMethod('$%s', '_p%s', ", isSet ? "<-" : "", getRClassName(className)); + Printf(out, "setMethod('$%s', '_p%s', ", + isSet ? "<-" : "", + getRClassName(className)); Wrapper_print(f, out); Printf(out, ");\n"); - - if (isSet) { - Printf(out, "setMethod('[[<-', c('_p%s', 'character'),", getRClassName(className)); + + if(isSet) { + Printf(out, "setMethod('[[<-', c('_p%s', 'character'),", + getRClassName(className)); Insert(f->code, 2, "name = i;\n"); Printf(attr->code, "%s", f->code); Wrapper_print(attr, out); Printf(out, ");\n"); } - + DelWrapper(attr); DelWrapper(f); - + Printf(out, "# end of accessor method for %s\n", className); - + return SWIG_OK; } /******************************************************************* - Write the methods for [ or [<- for accessing a member field in an + Write the methods for [ or [<- for accessing a member field in an struct or union (or class). className - the name of the struct or union (e.g. Bar for struct Bar) el - a list of length 2 * # accessible member elements + 1. - The first element is the name of the class. + The first element is the name of the class. The other pairs are member name and the name of the R function to access it. out - the stream where we write the code. ********************************************************************/ int R::OutputArrayMethod(String *className, List *el, File *out) { int numMems = Len(el), j; - - if (!el || numMems == 0) - return (0); - + + if(!el || numMems == 0) + return(0); + Printf(out, "# start of array methods for %s\n", className); - for (j = 0; j < numMems; j += 3) { + for(j = 0; j < numMems; j+=3) { String *item = Getitem(el, j); String *dup = Getitem(el, j + 1); if (!Strcmp(item, "__getitem__")) { - Printf(out, "setMethod('[', '_p%s', function(x, i, j, ..., drop =TRUE) ", getRClassName(className)); + Printf(out, + "setMethod('[', '_p%s', function(x, i, j, ..., drop =TRUE) ", + getRClassName(className)); Printf(out, " sapply(i, function (n) %s(x, as.integer(n-1))))\n\n", dup); } if (!Strcmp(item, "__setitem__")) { - Printf(out, "setMethod('[<-', '_p%s', function(x, i, j, ..., value)", getRClassName(className)); + Printf(out, "setMethod('[<-', '_p%s', function(x, i, j, ..., value)", + getRClassName(className)); Printf(out, " sapply(1:length(i), function(n) %s(x, as.integer(i[n]-1), value[n])))\n\n", dup); } - + } - + Printf(out, "# end of array methods for %s\n", className); - + return SWIG_OK; } @@ -1159,129 +1183,51 @@ int R::OutputArrayMethod(String *className, List *el, File *out) { int R::enumDeclaration(Node *n) { String *name = Getattr(n, "name"); String *tdname = Getattr(n, "tdname"); - - if (cplus_mode != PUBLIC) { - return (SWIG_NOWRAP); - } - + /* Using name if tdname is empty. */ - - if (Len(tdname) == 0) + + if(Len(tdname) == 0) tdname = name; - if (!tdname || Strcmp(tdname, "") == 0) { + + if(!tdname || Strcmp(tdname, "") == 0) { Language::enumDeclaration(n); return SWIG_OK; } - + String *mangled_tdname = SwigType_manglestr(tdname); String *scode = NewString(""); - String *possiblescode = NewString(""); - - // Need to create some C code to return the enum values. - // Presumably a C function for each element of the enum.. - // There is probably some sneaky way to use the - // standard methods of variable/constant access, but I can't see - // it yet. - // Need to fetch the namespace part of the enum in tdname, so - // that we can address the correct enum. Perhaps there is already an - // attribute that has this info, but I can't find it. That leaves - // searching for ::. Obviously needs to work if there is no nesting. - // - // One issue is that swig is generating defineEnumeration calls for - // enums in the private part of classes. This usually isn't a - // problem, but the model in which some C code returns the - // underlying value won't compile because it is accessing a private - // type. - // - // It will be best to turn off binding to private parts of - // classes. - - String *cppcode = NewString(""); - // this is the namespace that will get used inside the functions - // returning enumerations. - String *namespaceprefix = getNamespacePrefix(tdname); - Wrapper *eW = NewWrapper(); - Node *kk; - - for (kk = firstChild(n); kk; kk = nextSibling(kk)) { - String *ename = Getattr(kk, "name"); - String *fname = NewString(""); - String *cfunctname = NewStringf("R_swigenum_%s_%s", mangled_tdname, ename); - String *rfunctname = NewStringf("R_swigenum_%s_%s_get", mangled_tdname, ename); - Printf(fname, "%s(void){", cfunctname); - Printf(cppcode, "SWIGEXPORT SEXP \n%s\n", fname); - Printf(cppcode, "int result;\n"); - Printf(cppcode, "SEXP r_ans = R_NilValue;\n"); - Printf(cppcode, "result = (int)%s%s;\n", namespaceprefix, ename); - Printf(cppcode, "r_ans = Rf_ScalarInteger(result);\n"); - Printf(cppcode, "return(r_ans);\n}\n"); - - // Now emit the r binding functions - Printf(possiblescode, "`%s` = function(.copy=FALSE) {\n", rfunctname); - Printf(possiblescode, ".Call(\'%s\', as.logical(.copy), PACKAGE=\'%s\')\n}\n\n", cfunctname, Rpackage); - Printf(possiblescode, "attr(`%s`, \'returnType\')=\'integer\'\n", rfunctname); - Printf(possiblescode, "class(`%s`) = c(\"SWIGfunction\", class(\'%s\'))\n\n", rfunctname, rfunctname); - Delete(ename); - Delete(fname); - Delete(cfunctname); - Delete(rfunctname); - } - - Printv(cppcode, "", NIL); - - Printf(eW->code, "%s", cppcode); - Delete(cppcode); - - Delete(namespaceprefix); - - Printv(scode, "defineEnumeration('", mangled_tdname, "'", ",\n", tab8, tab8, tab4, ".values = c(\n", NIL); - + + Printv(scode, "defineEnumeration('", mangled_tdname, "'", + ",\n", tab8, tab8, tab4, ".values = c(\n", NIL); + Node *c; - int value = -1; // First number is zero - bool needenumfunc = false; // Track whether we need runtime C - // calls to deduce correct enum values + int value = -1; // First number is zero for (c = firstChild(n); c; c = nextSibling(c)) { // const char *tag = Char(nodeType(c)); - // if (Strcmp(tag,"cdecl") == 0) { + // if (Strcmp(tag,"cdecl") == 0) { name = Getattr(c, "name"); - // This needs to match the version earlier - could have stored it. - String *rfunctname = NewStringf("R_swigenum_%s_%s_get()", mangled_tdname, name); String *val = Getattr(c, "enumvalue"); - String *numstring = NewString(""); - - if (val && Char(val)) { - double inval = getNumber(val); - if (inval == DEFAULT_NUMBER) { - // This should indicate there is some fancy text there - // so we want to call the special R functions - needenumfunc = true; - Printf(numstring, "%s", rfunctname); - } else { - value = (int) inval; - Printf(numstring, "%d", value); - - } - } else { + if(val && Char(val)) { + int inval = (int) getNumber(val); + if(inval == DEFAULT_NUMBER) + value++; + else + value = inval; + } else value++; - Printf(numstring, "%d", value); - } - Printf(scode, "%s%s%s'%s' = %s%s\n", tab8, tab8, tab8, name, numstring, nextSibling(c) ? ", " : ""); - Delete(rfunctname); - Delete(numstring); + + Printf(scode, "%s%s%s'%s' = %d%s\n", tab8, tab8, tab8, name, value, + nextSibling(c) ? ", " : ""); + // } } - + Printv(scode, "))", NIL); - - if (needenumfunc) { - Wrapper_print(eW, f_wrapper); - Printf(sfile, "%s\n", possiblescode); - } Printf(sfile, "%s\n", scode); - + Delete(scode); - Delete(possiblescode); Delete(mangled_tdname); + return SWIG_OK; } @@ -1290,28 +1236,30 @@ int R::enumDeclaration(Node *n) { **************************************************************/ int R::variableWrapper(Node *n) { String *name = Getattr(n, "sym:name"); - + processing_variable = 1; Language::variableWrapper(n); // Force the emission of the _set and _get function wrappers. processing_variable = 0; - - + + SwigType *ty = Getattr(n, "type"); int addCopyParam = addCopyParameter(ty); - + //XXX processType(ty, n); - - if (!SwigType_isconst(ty)) { + + if(!SwigType_isconst(ty)) { Wrapper *f = NewWrapper(); - Printf(f->def, "%s = \nfunction(value%s)\n{\n", name, addCopyParam ? ", .copy = FALSE" : ""); - Printv(f->code, "if(missing(value)) {\n", name, "_get(", addCopyParam ? ".copy" : "", ")\n}", NIL); - Printv(f->code, " else {\n", name, "_set(value)\n}\n}", NIL); - + Printf(f->def, "%s = \nfunction(value%s)\n{\n", + name, addCopyParam ? ", .copy = FALSE" : ""); + Printv(f->code, "if(missing(value)) {\n", + name, "_get(", addCopyParam ? ".copy" : "", ")\n}", NIL); + Printv(f->code, " else {\n", + name, "_set(value)\n}\n}", NIL); + Wrapper_print(f, sfile); DelWrapper(f); } else { - Printf(sfile, "## constant in variableWrapper\n"); Printf(sfile, "%s = %s_get\n", name, name); } @@ -1319,27 +1267,27 @@ int R::variableWrapper(Node *n) { } - -void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, int isSet) { - if (isSet < 0) { +void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, + int isSet) { + if(isSet < 0) { int n = Len(name); char *ptr = Char(name); - isSet = Strcmp(NewString(&ptr[n - 3]), "set") == 0; + isSet = Strcmp(NewString(&ptr[n-3]), "set") == 0; } - + List *l = isSet ? class_member_set_functions : class_member_functions; - - if (!l) { + + if(!l) { l = NewList(); - if (isSet) + if(isSet) class_member_set_functions = l; else class_member_functions = l; } - + Append(l, memberName); Append(l, name); - + String *tmp = NewString(""); Wrapper_print(wrapper, tmp); Append(l, tmp); @@ -1351,235 +1299,237 @@ void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, int isSe #define MAX_OVERLOAD 256 struct Overloaded { - Node *n; /* Node */ - int argc; /* Argument count */ - ParmList *parms; /* Parameters used for overload check */ - int error; /* Ambiguity error */ + Node *n; /* Node */ + int argc; /* Argument count */ + ParmList *parms; /* Parameters used for overload check */ + int error; /* Ambiguity error */ }; -List *R::Swig_overload_rank(Node *n, bool script_lang_wrapping) { - Overloaded nodes[MAX_OVERLOAD]; - int nnodes = 0; - Node *o = Getattr(n, "sym:overloaded"); +List * R::Swig_overload_rank(Node *n, + bool script_lang_wrapping) { + Overloaded nodes[MAX_OVERLOAD]; + int nnodes = 0; + Node *o = Getattr(n,"sym:overloaded"); - if (!o) - return 0; + if (!o) return 0; Node *c = o; while (c) { - if (Getattr(c, "error")) { - c = Getattr(c, "sym:nextSibling"); + if (Getattr(c,"error")) { + c = Getattr(c,"sym:nextSibling"); continue; } /* if (SmartPointer && Getattr(c,"cplus:staticbase")) { - c = Getattr(c,"sym:nextSibling"); - continue; - } */ + c = Getattr(c,"sym:nextSibling"); + continue; + } */ /* Make a list of all the declarations (methods) that are overloaded with * this one particular method name */ - if (Getattr(c, "wrap:name")) { + if (Getattr(c,"wrap:name")) { nodes[nnodes].n = c; - nodes[nnodes].parms = Getattr(c, "wrap:parms"); + nodes[nnodes].parms = Getattr(c,"wrap:parms"); nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms); nodes[nnodes].error = 0; nnodes++; } - c = Getattr(c, "sym:nextSibling"); + c = Getattr(c,"sym:nextSibling"); } - + /* Sort the declarations by required argument count */ { - int i, j; + int i,j; for (i = 0; i < nnodes; i++) { - for (j = i + 1; j < nnodes; j++) { - if (nodes[i].argc > nodes[j].argc) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } + for (j = i+1; j < nnodes; j++) { + if (nodes[i].argc > nodes[j].argc) { + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + } } } } /* Sort the declarations by argument types */ { - int i, j; - for (i = 0; i < nnodes - 1; i++) { - if (nodes[i].argc == nodes[i + 1].argc) { - for (j = i + 1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) { - Parm *p1 = nodes[i].parms; - Parm *p2 = nodes[j].parms; - int differ = 0; - int num_checked = 0; - while (p1 && p2 && (num_checked < nodes[i].argc)) { - if (debugMode) { - Printf(stdout, "p1 = '%s', p2 = '%s'\n", Getattr(p1, "type"), Getattr(p2, "type")); - } - if (checkAttribute(p1, "tmap:in:numinputs", "0")) { - p1 = Getattr(p1, "tmap:in:next"); - continue; - } - if (checkAttribute(p2, "tmap:in:numinputs", "0")) { - p2 = Getattr(p2, "tmap:in:next"); - continue; - } - String *t1 = Getattr(p1, "tmap:typecheck:precedence"); - String *t2 = Getattr(p2, "tmap:typecheck:precedence"); - if (debugMode) { - Printf(stdout, "t1 = '%s', t2 = '%s'\n", t1, t2); - } - if ((!t1) && (!nodes[i].error)) { - Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n), - "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap 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 method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n", - Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0)); - nodes[j].error = 1; - } - if (t1 && t2) { - int t1v, t2v; - t1v = atoi(Char(t1)); - t2v = atoi(Char(t2)); - differ = t1v - t2v; - } else if (!t1 && t2) - differ = 1; - else if (t1 && !t2) - differ = -1; - else if (!t1 && !t2) - differ = -1; - num_checked++; - if (differ > 0) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - break; - } else if ((differ == 0) && (Strcmp(t1, "0") == 0)) { - t1 = Getattr(p1, "ltype"); - if (!t1) { - t1 = SwigType_ltype(Getattr(p1, "type")); - if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) { - SwigType_add_pointer(t1); - } - Setattr(p1, "ltype", t1); - } - t2 = Getattr(p2, "ltype"); - if (!t2) { - t2 = SwigType_ltype(Getattr(p2, "type")); - if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) { - SwigType_add_pointer(t2); - } - Setattr(p2, "ltype", t2); - } - - /* Need subtype check here. If t2 is a subtype of t1, then we need to change the + int i,j; + for (i = 0; i < nnodes-1; i++) { + if (nodes[i].argc == nodes[i+1].argc) { + for (j = i+1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) { + Parm *p1 = nodes[i].parms; + Parm *p2 = nodes[j].parms; + int differ = 0; + int num_checked = 0; + while (p1 && p2 && (num_checked < nodes[i].argc)) { + if (debugMode) { + Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type")); + } + if (checkAttribute(p1,"tmap:in:numinputs","0")) { + p1 = Getattr(p1,"tmap:in:next"); + continue; + } + if (checkAttribute(p2,"tmap:in:numinputs","0")) { + p2 = Getattr(p2,"tmap:in:next"); + continue; + } + String *t1 = Getattr(p1,"tmap:typecheck:precedence"); + String *t2 = Getattr(p2,"tmap:typecheck:precedence"); + if (debugMode) { + Printf(stdout,"t1 = '%s', t2 = '%s'\n", t1, t2); + } + if ((!t1) && (!nodes[i].error)) { + Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n), + "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap 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 method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n", + Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0)); + nodes[j].error = 1; + } + if (t1 && t2) { + int t1v, t2v; + t1v = atoi(Char(t1)); + t2v = atoi(Char(t2)); + differ = t1v-t2v; + } + else if (!t1 && t2) differ = 1; + else if (t1 && !t2) differ = -1; + else if (!t1 && !t2) differ = -1; + num_checked++; + if (differ > 0) { + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + break; + } else if ((differ == 0) && (Strcmp(t1,"0") == 0)) { + t1 = Getattr(p1,"ltype"); + if (!t1) { + t1 = SwigType_ltype(Getattr(p1,"type")); + if (Getattr(p1,"tmap:typecheck:SWIGTYPE")) { + SwigType_add_pointer(t1); + } + Setattr(p1,"ltype",t1); + } + t2 = Getattr(p2,"ltype"); + if (!t2) { + t2 = SwigType_ltype(Getattr(p2,"type")); + if (Getattr(p2,"tmap:typecheck:SWIGTYPE")) { + SwigType_add_pointer(t2); + } + Setattr(p2,"ltype",t2); + } + + /* Need subtype check here. If t2 is a subtype of t1, then we need to change the order */ - if (SwigType_issubtype(t2, t1)) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } - - if (Strcmp(t1, t2) != 0) { - differ = 1; - break; - } - } else if (differ) { - break; - } - if (Getattr(p1, "tmap:in:next")) { - p1 = Getattr(p1, "tmap:in:next"); - } else { - p1 = nextSibling(p1); - } - if (Getattr(p2, "tmap:in:next")) { - p2 = Getattr(p2, "tmap:in:next"); - } else { - p2 = nextSibling(p2); - } - } - if (!differ) { - /* See if declarations differ by const only */ - 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); - if (SwigType_isconst(d1)) { - Delete(SwigType_pop(dq1)); - } - if (SwigType_isconst(d2)) { - Delete(SwigType_pop(dq2)); - } - 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; - } - differ = 1; - 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,\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) { - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].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; - } - } - Delete(dq1); - Delete(dq2); - } - } - if (!differ) { - if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s 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; - } - } - } + if (SwigType_issubtype(t2,t1)) { + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + } + + if (Strcmp(t1,t2) != 0) { + differ = 1; + break; + } + } else if (differ) { + break; + } + if (Getattr(p1,"tmap:in:next")) { + p1 = Getattr(p1,"tmap:in:next"); + } else { + p1 = nextSibling(p1); + } + if (Getattr(p2,"tmap:in:next")) { + p2 = Getattr(p2,"tmap:in:next"); + } else { + p2 = nextSibling(p2); + } + } + if (!differ) { + /* See if declarations differ by const only */ + 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); + if (SwigType_isconst(d1)) { + Delete(SwigType_pop(dq1)); + } + if (SwigType_isconst(d2)) { + Delete(SwigType_pop(dq2)); + } + 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; + } + differ = 1; + 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,\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) { + Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].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; + } + } + Delete(dq1); + Delete(dq2); + } + } + if (!differ) { + if (!nodes[j].error) { + if (script_lang_wrapping) { + Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), + "Overloaded method %s 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; + } + } + } } } } @@ -1589,7 +1539,7 @@ List *R::Swig_overload_rank(Node *n, bool script_lang_wrapping) { for (i = 0; i < nnodes; i++) { if (nodes[i].error) Setattr(nodes[i].n, "overload:ignore", "1"); - Append(result, nodes[i].n); + Append(result,nodes[i].n); // Printf(stdout,"[ %d ] %s\n", i, ParmList_errorstr(nodes[i].parms)); // Swig_print_node(nodes[i].n); } @@ -1601,33 +1551,37 @@ void R::dispatchFunction(Node *n) { Wrapper *f = NewWrapper(); String *symname = Getattr(n, "sym:name"); String *nodeType = Getattr(n, "nodeType"); - bool constructor = (!Cmp(nodeType, "constructor")); + bool constructor = (!Cmp(nodeType, "constructor")); String *sfname = NewString(symname); if (constructor) Replace(sfname, "new_", "", DOH_REPLACE_FIRST); - Printf(f->def, "`%s` <- function(...) {", sfname); + Printf(f->def, + "`%s` <- function(...) {", sfname); if (debugMode) { Swig_print_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); + int nfunc = Len(dispatch); + Printv(f->code, + "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; bool first_compare = true; - for (int i = 0; i < nfunc; i++) { - Node *ni = Getitem(dispatch, i); - Parm *pi = Getattr(ni, "wrap:parms"); + for (int i=0; i < nfunc; i++) { + Node *ni = Getitem(dispatch,i); + Parm *pi = Getattr(ni,"wrap:parms"); int num_arguments = emit_num_arguments(pi); - String *overname = Getattr(ni, "sym:overname"); + String *overname = Getattr(ni,"sym:overname"); if (cur_args != num_arguments) { if (cur_args != -1) { - Printv(f->code, "} else ", NIL); + Printv(f->code, "} else ", NIL); } Printf(f->code, "if (argc == %d) {", num_arguments); cur_args = num_arguments; @@ -1637,52 +1591,67 @@ void R::dispatchFunction(Node *n) { int j; if (num_arguments > 0) { if (!first_compare) { - Printv(f->code, " else ", NIL); + Printv(f->code, " else ", NIL); } else { - first_compare = false; + first_compare = false; } Printv(f->code, "if (", NIL); - for (p = pi, j = 0; j < num_arguments; j++) { - if (debugMode) { - Swig_print_node(p); - } - String *tm = Swig_typemap_lookup("rtype", p, "", 0); - if (tm) { - replaceRClass(tm, Getattr(p, "type")); - } - - String *tmcheck = Swig_typemap_lookup("rtypecheck", p, "", 0); - if (tmcheck) { - String *tmp = NewString(""); - Printf(tmp, "argv[[%d]]", j + 1); - Replaceall(tmcheck, "$arg", tmp); - Printf(tmp, "argtype[%d]", j + 1); - Replaceall(tmcheck, "$argtype", tmp); - if (tm) { - Replaceall(tmcheck, "$rtype", tm); - } - if (debugMode) { - Printf(stdout, "%s\n", tmcheck); - } - Printf(f->code, "%s(%s)", j == 0 ? "" : " && ", tmcheck); - p = Getattr(p, "tmap:in:next"); - continue; - } - if (tm) { - if (Strcmp(tm, "numeric") == 0) { - Printf(f->code, "%sis.numeric(argv[[%d]])", j == 0 ? "" : " && ", j + 1); - } else if (Strcmp(tm, "integer") == 0) { - Printf(f->code, "%s(is.integer(argv[[%d]]) || is.numeric(argv[[%d]]))", j == 0 ? "" : " && ", j + 1, j + 1); - } else if (Strcmp(tm, "character") == 0) { - Printf(f->code, "%sis.character(argv[[%d]])", j == 0 ? "" : " && ", j + 1); - } else { - Printf(f->code, "%sextends(argtypes[%d], '%s')", j == 0 ? "" : " && ", j + 1, tm); - } - } - if (!SwigType_ispointer(Getattr(p, "type"))) { - Printf(f->code, " && length(argv[[%d]]) == 1", j + 1); - } - p = Getattr(p, "tmap:in:next"); + for (p =pi, j = 0 ; j < num_arguments ; j++) { + if (debugMode) { + Swig_print_node(p); + } + String *tm = Swig_typemap_lookup("rtype", p, "", 0); + if(tm) { + replaceRClass(tm, Getattr(p, "type")); + } + + String *tmcheck = Swig_typemap_lookup("rtypecheck", p, "", 0); + if (tmcheck) { + String *tmp = NewString(""); + Printf(tmp, "argv[[%d]]", j+1); + Replaceall(tmcheck, "$arg", tmp); + Printf(tmp, "argtype[%d]", j+1); + Replaceall(tmcheck, "$argtype", tmp); + if (tm) { + Replaceall(tmcheck, "$rtype", tm); + } + if (debugMode) { + Printf(stdout, "%s\n", tmcheck); + } + Printf(f->code, "%s(%s)", + j == 0? "" : " && ", + tmcheck); + p = Getattr(p, "tmap:in:next"); + continue; + } + if (tm) { + if (Strcmp(tm,"numeric")==0) { + Printf(f->code, "%sis.numeric(argv[[%d]])", + j == 0 ? "" : " && ", + j+1); + } + else if (Strcmp(tm,"integer")==0) { + Printf(f->code, "%s(is.integer(argv[[%d]]) || is.numeric(argv[[%d]]))", + j == 0 ? "" : " && ", + j+1, j+1); + } + else if (Strcmp(tm,"character")==0) { + Printf(f->code, "%sis.character(argv[[%d]])", + j == 0 ? "" : " && ", + j+1); + } + else { + Printf(f->code, "%sextends(argtypes[%d], '%s')", + j == 0 ? "" : " && ", + j+1, + tm); + } + } + if (!SwigType_ispointer(Getattr(p, "type"))) { + Printf(f->code, " && length(argv[[%d]]) == 1", + j+1); + } + p = Getattr(p, "tmap:in:next"); } Printf(f->code, ") { f <- %s%s; }\n", sfname, overname); } else { @@ -1690,7 +1659,10 @@ void R::dispatchFunction(Node *n) { } } if (cur_args != -1) { - Printf(f->code, "} else {\n" "stop(\"cannot find overloaded function for %s with argtypes (\"," "toString(argtypes),\")\");\n" "}", sfname); + Printf(f->code, "} else {\n" + "stop(\"cannot find overloaded function for %s with argtypes (\"," + "toString(argtypes),\")\");\n" + "}", sfname); } Printv(f->code, ";\nf(...)", NIL); Printv(f->code, ";\n}", NIL); @@ -1705,77 +1677,86 @@ void R::dispatchFunction(Node *n) { int R::functionWrapper(Node *n) { String *fname = Getattr(n, "name"); String *iname = Getattr(n, "sym:name"); - String *type = Getattr(n, "type"); - + String *type = Getattr(n, "type"); + if (debugMode) { - Printf(stdout, " %s %s %s\n", fname, iname, type); + Printf(stdout, + " %s %s %s\n", fname, iname, type); } String *overname = 0; String *nodeType = Getattr(n, "nodeType"); - bool constructor = (!Cmp(nodeType, "constructor")); - bool destructor = (!Cmp(nodeType, "destructor")); - + bool constructor = (!Cmp(nodeType, "constructor")); + bool destructor = (!Cmp(nodeType, "destructor")); + String *sfname = NewString(iname); - + if (constructor) Replace(sfname, "new_", "", DOH_REPLACE_FIRST); - - if (Getattr(n, "sym:overloaded")) { - overname = Getattr(n, "sym:overname"); + + if (Getattr(n,"sym:overloaded")) { + overname = Getattr(n,"sym:overname"); Append(sfname, overname); } - - if (debugMode) - Printf(stdout, " processing parameters\n"); - - + + if (debugMode) + Printf(stdout, + " processing parameters\n"); + + ParmList *l = Getattr(n, "parms"); Parm *p; String *tm; - + p = l; - while (p) { + while(p) { SwigType *resultType = Getattr(p, "type"); - if (expandTypedef(resultType) && SwigType_istypedef(resultType)) { - SwigType *resolved = SwigType_typedef_resolve_all(resultType); + if (expandTypedef(resultType) && + SwigType_istypedef(resultType)) { + SwigType *resolved = + SwigType_typedef_resolve_all(resultType); if (expandTypedef(resolved)) { - Setattr(p, "type", Copy(resolved)); + Setattr(p, "type", Copy(resolved)); } } p = nextSibling(p); - } - - String *unresolved_return_type = Copy(type); - if (expandTypedef(type) && SwigType_istypedef(type)) { - SwigType *resolved = SwigType_typedef_resolve_all(type); + } + + String *unresolved_return_type = + Copy(type); + if (expandTypedef(type) && + SwigType_istypedef(type)) { + SwigType *resolved = + SwigType_typedef_resolve_all(type); if (expandTypedef(resolved)) { type = Copy(resolved); Setattr(n, "type", type); } } - if (debugMode) - Printf(stdout, " unresolved_return_type %s\n", unresolved_return_type); - if (processing_member_access_function) { + if (debugMode) + Printf(stdout, " unresolved_return_type %s\n", + unresolved_return_type); + if(processing_member_access_function) { if (debugMode) - Printf(stdout, " '%s' '%s' '%s' '%s'\n", fname, iname, member_name, class_name); - - if (opaqueClassDeclaration) + Printf(stdout, " '%s' '%s' '%s' '%s'\n", + fname, iname, member_name, class_name); + + if(opaqueClassDeclaration) return SWIG_OK; - - - /* Add the name of this member to a list for this class_name. + + + /* Add the name of this member to a list for this class_name. We will dump all these at the end. */ - + int n = Len(iname); char *ptr = Char(iname); - bool isSet(Strcmp(NewString(&ptr[n - 3]), "set") == 0); - - + bool isSet(Strcmp(NewString(&ptr[n-3]), "set") == 0); + + String *tmp = NewString(""); Printf(tmp, "%s_%s", class_name, isSet ? "set" : "get"); - + List *memList = Getattr(ClassMemberTable, tmp); - if (!memList) { + if(!memList) { memList = NewList(); Append(memList, class_name); Setattr(ClassMemberTable, tmp, memList); @@ -1784,29 +1765,29 @@ int R::functionWrapper(Node *n) { Append(memList, member_name); Append(memList, iname); } - + int i; int nargs; - + String *wname = Swig_name_wrapper(iname); Replace(wname, "_wrap", "R_swig", DOH_REPLACE_FIRST); - if (overname) + if(overname) Append(wname, overname); - Setattr(n, "wrap:name", wname); + Setattr(n,"wrap:name", wname); Wrapper *f = NewWrapper(); Wrapper *sfun = NewWrapper(); - + int isVoidReturnType = (Strcmp(type, "void") == 0); - // Need to use the unresolved return type since - // typedef resolution removes the const which causes a + // Need to use the unresolved return type since + // typedef resolution removes the const which causes a // mismatch with the function action emit_return_variable(n, unresolved_return_type, f); SwigType *rtype = Getattr(n, "type"); int addCopyParam = 0; - if (!isVoidReturnType) + if(!isVoidReturnType) addCopyParam = addCopyParameter(rtype); @@ -1815,14 +1796,15 @@ int R::functionWrapper(Node *n) { // if(addCopyParam) if (debugMode) - Printf(stdout, "Adding a .copy argument to %s for %s = %s\n", iname, type, addCopyParam ? "yes" : "no"); + Printf(stdout, "Adding a .copy argument to %s for %s = %s\n", + iname, type, addCopyParam ? "yes" : "no"); Printv(f->def, "SWIGEXPORT SEXP\n", wname, " ( ", NIL); - Printf(sfun->def, "# Start of %s\n", iname); + Printf(sfun->def, "# Start of %s\n", iname); Printv(sfun->def, "\n`", sfname, "` = function(", NIL); - if (outputNamespaceInfo) //XXX Need to be a little more discriminating + if(outputNamespaceInfo) //XXX Need to be a little more discriminating addNamespaceFunction(iname); Swig_typemap_attach_parms("scoercein", l, f); @@ -1830,8 +1812,8 @@ int R::functionWrapper(Node *n) { Swig_typemap_attach_parms("scheck", l, f); emit_parameter_variables(l, f); - emit_attach_parmmaps(l, f); - Setattr(n, "wrap:parms", l); + emit_attach_parmmaps(l,f); + Setattr(n,"wrap:parms",l); nargs = emit_num_arguments(l); @@ -1847,7 +1829,7 @@ int R::functionWrapper(Node *n) { bool inFirstArg = true; bool inFirstType = true; Parm *curP; - for (p = l, i = 0; i < nargs; i++) { + for (p =l, i = 0 ; i < nargs ; i++) { while (checkAttribute(p, "tmap:in:numinputs", "0")) { p = Getattr(p, "tmap:in:next"); @@ -1858,26 +1840,26 @@ int R::functionWrapper(Node *n) { String *funcptr_name = processType(tt, p, &nargs); // SwigType *tp = Getattr(p, "type"); - String *name = Getattr(p, "name"); - String *lname = Getattr(p, "lname"); + String *name = Getattr(p,"name"); + String *lname = Getattr(p,"lname"); // R keyword renaming if (name) { if (Swig_name_warning(p, 0, name, 0)) { - name = 0; + name = 0; } else { - /* If we have a :: in the parameter name because we are accessing a static member of a class, say, then - we need to remove that prefix. */ - while (Strstr(name, "::")) { - //XXX need to free. - name = NewStringf("%s", Strchr(name, ':') + 2); - if (debugMode) - Printf(stdout, "+++ parameter name with :: in it %s\n", name); - } + /* If we have a :: in the parameter name because we are accessing a static member of a class, say, then + we need to remove that prefix. */ + while (Strstr(name, "::")) { + //XXX need to free. + name = NewStringf("%s", Strchr(name, ':') + 2); + if (debugMode) + Printf(stdout, "+++ parameter name with :: in it %s\n", name); + } } } if (!name || Len(name) == 0) - name = NewStringf("s_arg%d", i + 1); + name = NewStringf("s_arg%d", i+1); name = replaceInitialDash(name); @@ -1885,13 +1867,13 @@ int R::functionWrapper(Node *n) { name = Copy(name); Insert(name, 0, "s_"); } - - if (processing_variable) { + + if(processing_variable) { name = Copy(name); Insert(name, 0, "s_"); } - if (!Strcmp(name, fname)) { + if(!Strcmp(name, fname)) { name = Copy(name); Insert(name, 0, "s_"); } @@ -1899,73 +1881,79 @@ int R::functionWrapper(Node *n) { Printf(sargs, "%s, ", name); String *tm; - if ((tm = Getattr(p, "tmap:scoercein"))) { + if((tm = Getattr(p, "tmap:scoercein"))) { Replaceall(tm, "$input", name); replaceRClass(tm, Getattr(p, "type")); - if (funcptr_name) { - //XXX need to get this to return non-zero - if (nargs == -1) - nargs = getFunctionPointerNumArgs(p, tt); - - String *snargs = NewStringf("%d", nargs); - Printv(sfun->code, "if(is.function(", name, ")) {", "\n", - "assert('...' %in% names(formals(", name, ")) || length(formals(", name, ")) >= ", snargs, ");\n} ", NIL); - Delete(snargs); - - Printv(sfun->code, "else {\n", - "if(is.character(", name, ")) {\n", - name, " = getNativeSymbolInfo(", name, ");", - "\n};\n", - "if(is(", name, ", \"NativeSymbolInfo\")) {\n", - name, " = ", name, "$address", ";\n}\n", "if(is(", name, ", \"ExternalReference\")) {\n", name, " = ", name, "@ref;\n}\n", "}; \n", NIL); + if(funcptr_name) { + //XXX need to get this to return non-zero + if(nargs == -1) + nargs = getFunctionPointerNumArgs(p, tt); + + String *snargs = NewStringf("%d", nargs); + Printv(sfun->code, "if(is.function(", name, ")) {", "\n", + "assert('...' %in% names(formals(", name, + ")) || length(formals(", name, ")) >= ", snargs, ");\n} ", NIL); + Delete(snargs); + + Printv(sfun->code, "else {\n", + "if(is.character(", name, ")) {\n", + name, " = getNativeSymbolInfo(", name, ");", + "\n};\n", + "if(is(", name, ", \"NativeSymbolInfo\")) {\n", + name, " = ", name, "$address", ";\n}\n", + "if(is(", name, ", \"ExternalReference\")) {\n", + name, " = ", name, "@ref;\n}\n", + "}; \n", + NIL); } else { - Printf(sfun->code, "%s\n", tm); + Printf(sfun->code, "%s\n", tm); } } Printv(sfun->def, inFirstArg ? "" : ", ", name, NIL); - if ((tm = Getattr(p, "tmap:scheck"))) { + if ((tm = Getattr(p,"tmap:scheck"))) { - Replaceall(tm, "$target", lname); - Replaceall(tm, "$source", name); - Replaceall(tm, "$input", name); + Replaceall(tm,"$target", lname); + Replaceall(tm,"$source", name); + Replaceall(tm,"$input", name); replaceRClass(tm, Getattr(p, "type")); - Printf(sfun->code, "%s\n", tm); + Printf(sfun->code,"%s\n",tm); } curP = p; - if ((tm = Getattr(p, "tmap:in"))) { + if ((tm = Getattr(p,"tmap:in"))) { - Replaceall(tm, "$target", lname); - Replaceall(tm, "$source", name); - Replaceall(tm, "$input", name); + Replaceall(tm,"$target", lname); + Replaceall(tm,"$source", name); + Replaceall(tm,"$input", name); - if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) { - Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN"); + if (Getattr(p,"wrap:disown") || (Getattr(p,"tmap:in:disown"))) { + Replaceall(tm,"$disown","SWIG_POINTER_DISOWN"); } else { - Replaceall(tm, "$disown", "0"); + Replaceall(tm,"$disown","0"); } - if (funcptr_name) { - /* have us a function pointer */ - Printf(f->code, "if(TYPEOF(%s) != CLOSXP) {\n", name); - Replaceall(tm, "$R_class", ""); + if(funcptr_name) { + /* have us a function pointer */ + Printf(f->code, "if(TYPEOF(%s) != CLOSXP) {\n", name); + Replaceall(tm,"$R_class", ""); } else { - replaceRClass(tm, Getattr(p, "type")); + replaceRClass(tm, Getattr(p, "type")); } - Printf(f->code, "%s\n", tm); - if (funcptr_name) - Printf(f->code, "} else {\n%s = %s;\nR_SWIG_pushCallbackFunctionData(%s, NULL);\n}\n", lname, funcptr_name, name); + Printf(f->code,"%s\n",tm); + if(funcptr_name) + Printf(f->code, "} else {\n%s = %s;\nR_SWIG_pushCallbackFunctionData(%s, NULL);\n}\n", + lname, funcptr_name, name); Printv(f->def, inFirstArg ? "" : ", ", "SEXP ", name, NIL); - if (Len(name) != 0) - inFirstArg = false; - p = Getattr(p, "tmap:in:next"); + if (Len(name) != 0) + inFirstArg = false; + p = Getattr(p,"tmap:in:next"); } else { p = nextSibling(p); @@ -1973,18 +1961,18 @@ int R::functionWrapper(Node *n) { tm = Swig_typemap_lookup("rtype", curP, "", 0); - if (tm) { + if(tm) { replaceRClass(tm, Getattr(curP, "type")); } Printf(s_inputTypes, "%s'%s'", inFirstType ? "" : ", ", tm); Printf(s_inputMap, "%s%s='%s'", inFirstType ? "" : ", ", name, tm); inFirstType = false; - if (funcptr_name) + if(funcptr_name) Delete(funcptr_name); - } /* end of looping over parameters. */ + } /* end of looping over parameters. */ - if (addCopyParam) { + if(addCopyParam) { Printf(sfun->def, "%s.copy = FALSE", nargs > 0 ? ", " : ""); Printf(f->def, "%sSEXP s_swig_copy", nargs > 0 ? ", " : ""); @@ -2009,21 +1997,21 @@ int R::functionWrapper(Node *n) { String *outargs = NewString(""); int numOutArgs = isVoidReturnType ? -1 : 0; - for (p = l, i = 0; p; i++) { - if ((tm = Getattr(p, "tmap:argout"))) { + for(p = l, i = 0; p; i++) { + if((tm = Getattr(p, "tmap:argout"))) { // String *lname = Getattr(p, "lname"); numOutArgs++; String *pos = NewStringf("%d", numOutArgs); - Replaceall(tm, "$source", Getattr(p, "lname")); - Replaceall(tm, "$result", "r_ans"); - Replaceall(tm, "$n", pos); // The position into which to store the answer. - Replaceall(tm, "$arg", Getattr(p, "emit:input")); - Replaceall(tm, "$input", Getattr(p, "emit:input")); - Replaceall(tm, "$owner", "R_SWIG_EXTERNAL"); + Replaceall(tm,"$source", Getattr(p, "lname")); + Replaceall(tm,"$result", "r_ans"); + Replaceall(tm,"$n", pos); // The position into which to store the answer. + Replaceall(tm,"$arg", Getattr(p, "emit:input")); + Replaceall(tm,"$input", Getattr(p, "emit:input")); + Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); Printf(outargs, "%s\n", tm); - p = Getattr(p, "tmap:argout:next"); + p = Getattr(p,"tmap:argout:next"); } else p = nextSibling(p); } @@ -2031,57 +2019,60 @@ int R::functionWrapper(Node *n) { String *actioncode = emit_action(n); /* Deal with the explicit return value. */ - if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) { + if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) { SwigType *retType = Getattr(n, "type"); - //Printf(stdout, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no"); + //Printf(stdout, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no"); /* if(SwigType_isarray(retType)) { - defineArrayAccessors(retType); - } */ + defineArrayAccessors(retType); + } */ - Replaceall(tm, "$1", Swig_cresult_name()); - Replaceall(tm, "$result", "r_ans"); + Replaceall(tm,"$1", Swig_cresult_name()); + Replaceall(tm,"$result", "r_ans"); replaceRClass(tm, retType); - if (GetFlag(n, "feature:new")) { + if (GetFlag(n,"feature:new")) { Replaceall(tm, "$owner", "R_SWIG_OWNER"); } else { - Replaceall(tm, "$owner", "R_SWIG_EXTERNAL"); + Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); } #if 0 - if (addCopyParam) { + if(addCopyParam) { Printf(f->code, "if(LOGICAL(s_swig_copy)[0]) {\n"); Printf(f->code, "/* Deal with returning a reference. */\nr_ans = R_NilValue;\n"); Printf(f->code, "}\n else {\n"); - } + } #endif Printf(f->code, "%s\n", tm); #if 0 - if (addCopyParam) - Printf(f->code, "}\n"); /* end of if(s_swig_copy) ... else { ... } */ + if(addCopyParam) + Printf(f->code, "}\n"); /* end of if(s_swig_copy) ... else { ... } */ #endif } else { - Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), fname); + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, + "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), fname); } - if (Len(outargs)) { + if(Len(outargs)) { Wrapper_add_local(f, "R_OutputValues", "SEXP R_OutputValues"); String *tmp = NewString(""); - if (!isVoidReturnType) + if(!isVoidReturnType) Printf(tmp, "Rf_protect(r_ans);\n"); - Printf(tmp, "Rf_protect(R_OutputValues = Rf_allocVector(VECSXP,%d));\nr_nprotect += %d;\n", numOutArgs + !isVoidReturnType, isVoidReturnType ? 1 : 2); + Printf(tmp, "Rf_protect(R_OutputValues = Rf_allocVector(VECSXP,%d));\nr_nprotect += %d;\n", + numOutArgs + !isVoidReturnType, + isVoidReturnType ? 1 : 2); - if (!isVoidReturnType) + if(!isVoidReturnType) Printf(tmp, "SET_VECTOR_ELT(R_OutputValues, 0, r_ans);\n"); Printf(tmp, "r_ans = R_OutputValues;\n"); Insert(outargs, 0, tmp); - Delete(tmp); + Delete(tmp); @@ -2097,7 +2088,7 @@ int R::functionWrapper(Node *n) { /* Look to see if there is any newfree cleanup code */ if (GetFlag(n, "feature:new")) { if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) { - Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */ + Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */ Printf(f->code, "%s\n", tm); } } @@ -2106,23 +2097,26 @@ int R::functionWrapper(Node *n) { /*If the user gave us something to convert the result in */ if ((tm = Swig_typemap_lookup("scoerceout", n, Swig_cresult_name(), sfun))) { - Replaceall(tm, "$source", "ans"); - Replaceall(tm, "$result", "ans"); + Replaceall(tm,"$source","ans"); + Replaceall(tm,"$result","ans"); replaceRClass(tm, Getattr(n, "type")); Chop(tm); } - Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname, "', ", sargs, "PACKAGE='", Rpackage, "');\n", NIL); - if (Len(tm)) { - Printf(sfun->code, "%s\n\n", tm); - if (constructor) { - String *finalizer = NewString(iname); - Replace(finalizer, "new_", "", DOH_REPLACE_FIRST); - Printf(sfun->code, "reg.finalizer(ans@ref, delete_%s)\n", finalizer); + Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname, + "', ", sargs, "PACKAGE='", Rpackage, "');\n", NIL); + if(Len(tm)) + { + Printf(sfun->code, "%s\n\n", tm); + if (constructor) + { + String *finalizer = NewString(iname); + Replace(finalizer, "new_", "", DOH_REPLACE_FIRST); + Printf(sfun->code, "reg.finalizer(ans@ref, delete_%s)\n", finalizer); + } + Printf(sfun->code, "ans\n"); } - Printf(sfun->code, "ans\n"); - } if (destructor) Printv(f->code, "R_ClearExternalPtr(self);\n", NIL); @@ -2131,23 +2125,27 @@ int R::functionWrapper(Node *n) { Printv(sfun->code, "\n}", NIL); /* Substitute the function name */ - Replaceall(f->code, "$symname", iname); + Replaceall(f->code,"$symname",iname); Wrapper_print(f, f_wrapper); Wrapper_print(sfun, sfile); Printf(sfun->code, "\n# End of %s\n", iname); tm = Swig_typemap_lookup("rtype", n, "", 0); - if (tm) { + if(tm) { SwigType *retType = Getattr(n, "type"); replaceRClass(tm, retType); - } - - Printv(sfile, "attr(`", sfname, "`, 'returnType') = '", isVoidReturnType ? "void" : (tm ? tm : ""), "'\n", NIL); - - if (nargs > 0) - Printv(sfile, "attr(`", sfname, "`, \"inputTypes\") = c(", s_inputTypes, ")\n", NIL); - Printv(sfile, "class(`", sfname, "`) = c(\"SWIGFunction\", class('", sfname, "'))\n\n", NIL); + } + + Printv(sfile, "attr(`", sfname, "`, 'returnType') = '", + isVoidReturnType ? "void" : (tm ? tm : ""), + "'\n", NIL); + + if(nargs > 0) + Printv(sfile, "attr(`", sfname, "`, \"inputTypes\") = c(", + s_inputTypes, ")\n", NIL); + Printv(sfile, "class(`", sfname, "`) = c(\"SWIGFunction\", class('", + sfname, "'))\n\n", NIL); if (memoryProfile) { Printv(sfile, "memory.profile()\n", NIL); @@ -2155,24 +2153,26 @@ int R::functionWrapper(Node *n) { if (aggressiveGc) { Printv(sfile, "gc()\n", NIL); } + // Printv(sfile, "setMethod('", name, "', '", name, "', ", iname, ")\n\n\n"); - /* If we are dealing with a method in an C++ class, then - add the name of the R function and its definition. + /* If we are dealing with a method in an C++ class, then + add the name of the R function and its definition. XXX need to figure out how to store the Wrapper if possible in the hash/list. Would like to be able to do this so that we can potentially insert - */ - if (processing_member_access_function || processing_class_member_function) { + */ + if(processing_member_access_function || processing_class_member_function) { addAccessor(member_name, sfun, iname); } - if (Getattr(n, "sym:overloaded") && !Getattr(n, "sym:nextSibling")) { + if (Getattr(n, "sym:overloaded") && + !Getattr(n, "sym:nextSibling")) { dispatchFunction(n); } - addRegistrationRoutine(wname, addCopyParam ? nargs + 1 : nargs); + addRegistrationRoutine(wname, addCopyParam ? nargs +1 : nargs); DelWrapper(f); DelWrapper(sfun); @@ -2193,20 +2193,21 @@ int R::constantWrapper(Node *n) { } /***************************************************** - Add the specified routine name to the collection of + Add the specified routine name to the collection of generated routines that are called from R functions. - This is used to register the routines with R for + This is used to register the routines with R for resolving symbols. rname - the name of the routine - nargs - the number of arguments it expects. + nargs - the number of arguments it expects. ******************************************************/ int R::addRegistrationRoutine(String *rname, int nargs) { - if (!registrationTable) + if(!registrationTable) registrationTable = NewHash(); - String *el = NewStringf("{\"%s\", (DL_FUNC) &%s, %d}", rname, rname, nargs); - + String *el = + NewStringf("{\"%s\", (DL_FUNC) &%s, %d}", rname, rname, nargs); + Setattr(registrationTable, rname, el); return SWIG_OK; @@ -2219,30 +2220,30 @@ int R::addRegistrationRoutine(String *rname, int nargs) { ******************************************************/ int R::outputRegistrationRoutines(File *out) { int i, n; - if (!registrationTable) - return (0); - if (inCPlusMode) + if(!registrationTable) + return(0); + if(inCPlusMode) Printf(out, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"); Printf(out, "#include \n\n"); - if (inCPlusMode) + if(inCPlusMode) Printf(out, "#ifdef __cplusplus\n}\n#endif\n\n"); Printf(out, "SWIGINTERN R_CallMethodDef CallEntries[] = {\n"); - + List *keys = Keys(registrationTable); n = Len(keys); - for (i = 0; i < n; i++) + for(i = 0; i < n; i++) Printf(out, " %s,\n", Getattr(registrationTable, Getitem(keys, i))); Printf(out, " {NULL, NULL, 0}\n};\n\n"); - if (!noInitializationCode) { + if(!noInitializationCode) { if (inCPlusMode) Printv(out, "extern \"C\" ", NIL); Printf(out, "SWIGEXPORT void R_init_%s(DllInfo *dll) {\n", Rpackage); Printf(out, "%sR_registerRoutines(dll, NULL, CallEntries, NULL, NULL);\n", tab4); - if (Len(s_init_routine)) { + if(Len(s_init_routine)) { Printf(out, "\n%s\n", s_init_routine); } Printf(out, "}\n"); @@ -2256,58 +2257,60 @@ int R::outputRegistrationRoutines(File *out) { /**************************************************************************** Process a struct, union or class declaration in the source code, or an anonymous typedef struct - + *****************************************************************************/ -//XXX What do we need to do here - +//XXX What do we need to do here - // Define an S4 class to refer to this. void R::registerClass(Node *n) { - String *name = Getattr(n, "name"); - String *kind = Getattr(n, "kind"); + String *name = Getattr(n, "name"); + String *kind = Getattr(n, "kind"); if (debugMode) Swig_print_node(n); String *sname = NewStringf("_p%s", SwigType_manglestr(name)); - if (!Getattr(SClassDefs, sname)) { + if(!Getattr(SClassDefs, sname)) { Setattr(SClassDefs, sname, sname); String *base; - if (Strcmp(kind, "class") == 0) { + if(Strcmp(kind, "class") == 0) { base = NewString(""); List *l = Getattr(n, "bases"); - if (Len(l)) { - Printf(base, "c("); - for (int i = 0; i < Len(l); i++) { - registerClass(Getitem(l, i)); - Printf(base, "'_p%s'%s", SwigType_manglestr(Getattr(Getitem(l, i), "name")), i < Len(l) - 1 ? ", " : ""); - } - Printf(base, ")"); + if(Len(l)) { + Printf(base, "c("); + for(int i = 0; i < Len(l); i++) { + registerClass(Getitem(l, i)); + Printf(base, "'_p%s'%s", + SwigType_manglestr(Getattr(Getitem(l, i), "name")), + i < Len(l)-1 ? ", " : ""); + } + Printf(base, ")"); } else { - base = NewString("'C++Reference'"); + base = NewString("'C++Reference'"); } - } else + } else base = NewString("'ExternalReference'"); Printf(s_classes, "setClass('%s', contains = %s)\n", sname, base); Delete(base); } - + } int R::classDeclaration(Node *n) { - String *name = Getattr(n, "name"); - String *kind = Getattr(n, "kind"); + String *name = Getattr(n, "name"); + String *kind = Getattr(n, "kind"); if (debugMode) Swig_print_node(n); registerClass(n); - + /* If we have a typedef union { ... } U, then we never get to see the typedef via a regular call to typedefHandler. Instead, */ - if (Getattr(n, "unnamed") && Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "typedef") == 0 - && Getattr(n, "tdname") && Strcmp(Getattr(n, "tdname"), name) == 0) { + if(Getattr(n, "unnamed") && Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "typedef") == 0 + && Getattr(n, "tdname") && Strcmp(Getattr(n, "tdname"), name) == 0) { if (debugMode) Printf(stdout, "Typedef in the class declaration for %s\n", name); // typedefHandler(n); @@ -2315,7 +2318,7 @@ int R::classDeclaration(Node *n) { bool opaque = GetFlag(n, "feature:opaque") ? true : false; - if (opaque) + if(opaque) opaqueClassDeclaration = name; int status = Language::classDeclaration(n); @@ -2323,72 +2326,76 @@ int R::classDeclaration(Node *n) { opaqueClassDeclaration = NULL; - // OutputArrayMethod(name, class_member_functions, sfile); + // OutputArrayMethod(name, class_member_functions, sfile); if (class_member_functions) OutputMemberReferenceMethod(name, 0, class_member_functions, sfile); if (class_member_set_functions) OutputMemberReferenceMethod(name, 1, class_member_set_functions, sfile); - if (class_member_functions) { + if(class_member_functions) { Delete(class_member_functions); class_member_functions = NULL; } - if (class_member_set_functions) { + if(class_member_set_functions) { Delete(class_member_set_functions); class_member_set_functions = NULL; } if (Getattr(n, "has_destructor")) { - Printf(sfile, "setMethod('delete', '_p%s', function(obj) {delete%s(obj)})\n", getRClassName(Getattr(n, "name")), getRClassName(Getattr(n, "name"))); + Printf(sfile, "setMethod('delete', '_p%s', function(obj) {delete%s(obj)})\n", + getRClassName(Getattr(n, "name")), + getRClassName(Getattr(n, "name"))); } - if (!opaque && !Strcmp(kind, "struct") && copyStruct) { + if(!opaque && !Strcmp(kind, "struct") && copyStruct) { - String *def = NewStringf("setClass(\"%s\",\n%srepresentation(\n", name, tab4); + String *def = + NewStringf("setClass(\"%s\",\n%srepresentation(\n", name, tab4); bool firstItem = true; - for (Node *c = firstChild(n); c;) { + for(Node *c = firstChild(n); c; ) { String *elName; String *tp; elName = Getattr(c, "name"); - + String *elKind = Getattr(c, "kind"); if (!Equal(elKind, "variable")) { - c = nextSibling(c); - continue; + c = nextSibling(c); + continue; } if (!Len(elName)) { - c = nextSibling(c); - continue; + c = nextSibling(c); + continue; } #if 0 tp = getRType(c); #else tp = Swig_typemap_lookup("rtype", c, "", 0); - if (!tp) { - c = nextSibling(c); - continue; + if(!tp) { + c = nextSibling(c); + continue; } if (Strstr(tp, "R_class")) { - c = nextSibling(c); - continue; + c = nextSibling(c); + continue; } - if (Strcmp(tp, "character") && Strstr(Getattr(c, "decl"), "p.")) { - c = nextSibling(c); - continue; + if (Strcmp(tp, "character") && + Strstr(Getattr(c, "decl"), "p.")) { + c = nextSibling(c); + continue; } if (!firstItem) { - Printf(def, ",\n"); - } - // else + Printf(def, ",\n"); + } + // else //XXX How can we tell if this is already done. - // SwigType_push(elType, elDecl); - - + // SwigType_push(elType, elDecl); + + // returns "" tp = processType(elType, c, NULL); - // Printf(stdout, " elType %p\n", elType); - // tp = getRClassNameCopyStruct(Getattr(c, "type"), 1); + // Printf(stdout, " elType %p\n", elType); + // tp = getRClassNameCopyStruct(Getattr(c, "type"), 1); #endif String *elNameT = replaceInitialDash(elName); Printf(def, "%s%s = \"%s\"", tab8, elNameT, tp); @@ -2424,13 +2431,13 @@ int R::classDeclaration(Node *n) { int R::generateCopyRoutines(Node *n) { Wrapper *copyToR = NewWrapper(); Wrapper *copyToC = NewWrapper(); - + String *name = Getattr(n, "name"); String *tdname = Getattr(n, "tdname"); String *kind = Getattr(n, "kind"); String *type; - if (Len(tdname)) { + if(Len(tdname)) { type = Copy(tdname); } else { type = NewStringf("%s %s", kind, name); @@ -2441,12 +2448,14 @@ int R::generateCopyRoutines(Node *n) { if (debugMode) Printf(stdout, "generateCopyRoutines: name = %s, %s\n", name, type); - Printf(copyToR->def, "CopyToR%s = function(value, obj = new(\"%s\"))\n{\n", mangledName, name); - Printf(copyToC->def, "CopyToC%s = function(value, obj)\n{\n", mangledName); + Printf(copyToR->def, "CopyToR%s = function(value, obj = new(\"%s\"))\n{\n", + mangledName, name); + Printf(copyToC->def, "CopyToC%s = function(value, obj)\n{\n", + mangledName); Node *c = firstChild(n); - for (; c; c = nextSibling(c)) { + for(; c; c = nextSibling(c)) { String *elName = Getattr(c, "name"); if (!Len(elName)) { continue; @@ -2457,13 +2466,14 @@ int R::generateCopyRoutines(Node *n) { } String *tp = Swig_typemap_lookup("rtype", c, "", 0); - if (!tp) { + if(!tp) { continue; } if (Strstr(tp, "R_class")) { continue; } - if (Strcmp(tp, "character") && Strstr(Getattr(c, "decl"), "p.")) { + if (Strcmp(tp, "character") && + Strstr(Getattr(c, "decl"), "p.")) { continue; } @@ -2475,25 +2485,26 @@ int R::generateCopyRoutines(Node *n) { Delete(elNameT); } 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); - + String *rclassName = getRClassNameCopyStruct(type, 0); // without the Ref. + Printf(sfile, "# Start definition of copy functions & methods for %s\n", rclassName); + Wrapper_print(copyToR, sfile); Printf(copyToC->code, "obj\n}\n\n"); Wrapper_print(copyToC, sfile); - - - Printf(sfile, "# Start definition of copy methods for %s\n", rclassName); - Printf(sfile, "setMethod('copyToR', '_p_%s', CopyToR%s);\n", rclassName, mangledName); - Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s);\n\n", rclassName, mangledName); - - Printf(sfile, "# End definition of copy methods for %s\n", rclassName); - Printf(sfile, "# End definition of copy functions & methods for %s\n", rclassName); - + + + Printf(sfile, "# Start definition of copy methods for %s\n", rclassName); + Printf(sfile, "setMethod('copyToR', '_p_%s', CopyToR%s);\n", rclassName, + mangledName); + Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s);\n\n", rclassName, + mangledName); + + Printf(sfile, "# End definition of copy methods for %s\n", rclassName); + Printf(sfile, "# End definition of copy functions & methods for %s\n", rclassName); + String *m = NewStringf("%sCopyToR", name); addNamespaceMethod(m); - char *tt = Char(m); - tt[Len(m) - 1] = 'C'; + char *tt = Char(m); tt[Len(m)-1] = 'C'; addNamespaceMethod(m); Delete(m); Delete(rclassName); @@ -2507,9 +2518,9 @@ int R::generateCopyRoutines(Node *n) { /***** - Called when there is a typedef to be invoked. + Called when there is a typedef to be invoked. - XXX Needs to be enhanced or split to handle the case where we have a + XXX Needs to be enhanced or split to handle the case where we have a typedef within a classDeclaration emission because the struct/union/etc. is anonymous. ******/ @@ -2521,13 +2532,14 @@ int R::typedefHandler(Node *n) { processType(tp, n); - if (Strncmp(type, "struct ", 7) == 0) { + if(Strncmp(type, "struct ", 7) == 0) { String *name = Getattr(n, "name"); char *trueName = Char(type); trueName += 7; if (debugMode) Printf(stdout, " Defining S class %s\n", trueName); - Printf(s_classes, "setClass('_p%s', contains = 'ExternalReference')\n", SwigType_manglestr(name)); + Printf(s_classes, "setClass('_p%s', contains = 'ExternalReference')\n", + SwigType_manglestr(name)); } return Language::typedefHandler(n); @@ -2538,20 +2550,21 @@ int R::typedefHandler(Node *n) { /********************* Called when processing a field in a "class", i.e. struct, union or actual class. We set a state variable so that we can correctly - interpret the resulting functionWrapper() call and understand that + interpret the resulting functionWrapper() call and understand that it is for a field element. **********************/ int R::membervariableHandler(Node *n) { SwigType *t = Getattr(n, "type"); processType(t, n, NULL); processing_member_access_function = 1; - member_name = Getattr(n, "sym:name"); + member_name = Getattr(n,"sym:name"); if (debugMode) - Printf(stdout, " name = %s, sym:name = %s\n", Getattr(n, "name"), member_name); + Printf(stdout, " name = %s, sym:name = %s\n", + Getattr(n, "name"), member_name); int status(Language::membervariableHandler(n)); - if (!opaqueClassDeclaration && debugMode) + if(!opaqueClassDeclaration && debugMode) Printf(stdout, " %s %s\n", Getattr(n, "name"), Getattr(n, "type")); processing_member_access_function = 0; @@ -2564,7 +2577,7 @@ int R::membervariableHandler(Node *n) { /* This doesn't seem to get used so leave it out for the moment. */ -String *R::runtimeCode() { +String * R::runtimeCode() { String *s = Swig_include_sys("rrun.swg"); if (!s) { Printf(stdout, "*** Unable to open 'rrun.swg'\n"); @@ -2575,7 +2588,7 @@ String *R::runtimeCode() { /** - Called when SWIG wants to initialize this + Called when SWIG wants to initialize this We initialize anythin we want here. Most importantly, tell SWIG where to find the files (e.g. r.swg) for this module. Use Swig_mark_arg() to tell SWIG that it is understood and not to throw an error. @@ -2597,41 +2610,41 @@ void R::main(int argc, char *argv[]) { this->Argc = argc; this->Argv = argv; - allow_overloading(); // can we support this? + allow_overloading();// can we support this? - for (int i = 0; i < argc; i++) { - if (strcmp(argv[i], "-package") == 0) { + for(int i = 0; i < argc; i++) { + if(strcmp(argv[i], "-package") == 0) { Swig_mark_arg(i); i++; Swig_mark_arg(i); Rpackage = argv[i]; - } else if (strcmp(argv[i], "-dll") == 0) { + } else if(strcmp(argv[i], "-dll") == 0) { Swig_mark_arg(i); i++; Swig_mark_arg(i); DllName = argv[i]; - } else if (strcmp(argv[i], "-help") == 0) { + } else if(strcmp(argv[i], "-help") == 0) { showUsage(); - } else if (strcmp(argv[i], "-namespace") == 0) { + } else if(strcmp(argv[i], "-namespace") == 0) { outputNamespaceInfo = true; Swig_mark_arg(i); - } else if (!strcmp(argv[i], "-no-init-code")) { + } else if(!strcmp(argv[i], "-no-init-code")) { noInitializationCode = true; Swig_mark_arg(i); - } else if (!strcmp(argv[i], "-c++")) { + } else if(!strcmp(argv[i], "-c++")) { inCPlusMode = true; Swig_mark_arg(i); Printf(s_classes, "setClass('C++Reference', contains = 'ExternalReference')\n"); - } else if (!strcmp(argv[i], "-debug")) { + } else if(!strcmp(argv[i], "-debug")) { debugMode = true; Swig_mark_arg(i); - } else if (!strcmp(argv[i], "-cppcast")) { + } else if (!strcmp(argv[i],"-cppcast")) { cppcast = true; Swig_mark_arg(i); - } else if (!strcmp(argv[i], "-nocppcast")) { + } else if (!strcmp(argv[i],"-nocppcast")) { cppcast = false; Swig_mark_arg(i); - } else if (!strcmp(argv[i], "-copystruct")) { + } else if (!strcmp(argv[i],"-copystruct")) { copyStruct = true; Swig_mark_arg(i); } else if (!strcmp(argv[i], "-nocopystruct")) { @@ -2670,12 +2683,13 @@ void R::main(int argc, char *argv[]) { Could make this work for String or File and then just store the resulting string rather than the collection of arguments and argc. */ -int R::outputCommandLineArguments(File *out) { - if (Argc < 1 || !Argv || !Argv[0]) - return (-1); +int R::outputCommandLineArguments(File *out) +{ + if(Argc < 1 || !Argv || !Argv[0]) + return(-1); Printf(out, "\n## Generated via the command line invocation:\n##\t"); - for (int i = 0; i < Argc; i++) { + for(int i = 0; i < Argc ; i++) { Printf(out, " %s", Argv[i]); } Printf(out, "\n\n\n"); @@ -2685,9 +2699,10 @@ int R::outputCommandLineArguments(File *out) { -/* How SWIG instantiates an object from this module. +/* How SWIG instantiates an object from this module. See swigmain.cxx */ -extern "C" Language *swig_r(void) { +extern "C" +Language *swig_r(void) { return new R(); } @@ -2698,50 +2713,55 @@ extern "C" Language *swig_r(void) { /* Needs to be reworked. */ -String *R::processType(SwigType *t, Node *n, int *nargs) { +String * R::processType(SwigType *t, Node *n, int *nargs) { //XXX Need to handle typedefs, e.g. // a type which is a typedef to a function pointer. SwigType *tmp = Getattr(n, "tdname"); if (debugMode) Printf(stdout, "processType %s (tdname = %s)\n", Getattr(n, "name"), tmp); - + SwigType *td = t; - if (expandTypedef(t) && SwigType_istypedef(t)) { - SwigType *resolved = SwigType_typedef_resolve_all(t); + if (expandTypedef(t) && + SwigType_istypedef(t)) { + SwigType *resolved = + SwigType_typedef_resolve_all(t); if (expandTypedef(resolved)) { td = Copy(resolved); } } - if (!td) { + if(!td) { int count = 0; String *b = getRTypeName(t, &count); - if (count && b && !Getattr(SClassDefs, b)) { + if(count && b && !Getattr(SClassDefs, b)) { if (debugMode) - Printf(stdout, " Defining class %s\n", b); + Printf(stdout, " Defining class %s\n", b); - Printf(s_classes, "setClass('%s', contains = 'ExternalReference')\n", b); + Printf(s_classes, "setClass('%s', contains = 'ExternalReference')\n", b); Setattr(SClassDefs, b, b); } - + } - if (td) + if(td) t = td; - if (SwigType_isfunctionpointer(t)) { + if(SwigType_isfunctionpointer(t)) { if (debugMode) - Printf(stdout, " Defining pointer handler %s\n", t); - + Printf(stdout, + " Defining pointer handler %s\n", t); + String *tmp = createFunctionPointerHandler(t, n, nargs); return tmp; } + #if 0 SwigType_isfunction(t) && SwigType_ispointer(t) #endif - return NULL; + + return NULL; } @@ -2753,3 +2773,8 @@ String *R::processType(SwigType *t, Node *n, int *nargs) { /*************************************************************************************/ + + + + + -- cgit v1.2.1 From 9aa0f85cdacff59180cde416d5b10406cff1bda1 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 7 Aug 2015 19:48:06 +0100 Subject: Workaround Appveyor random failures due to nuget install errors Add and use nuget-install.cmd based on https://github.com/appveyor/ci/blob/master/scripts/nuget-restore.cmd --- Tools/nuget-install.cmd | 28 ++++++++++++++++++++++++++++ appveyor.yml | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 Tools/nuget-install.cmd diff --git a/Tools/nuget-install.cmd b/Tools/nuget-install.cmd new file mode 100644 index 000000000..08caea7e0 --- /dev/null +++ b/Tools/nuget-install.cmd @@ -0,0 +1,28 @@ +rem Workaround 'nuget install' not being reliable by retrying a few times + +@echo off +rem initiate the retry number +set errorCode=1 +set retryNumber=0 +set maxRetries=5 + +:RESTORE +nuget install %* + +rem problem? +IF ERRORLEVEL %errorCode% GOTO :RETRY + +rem everything is fine! +GOTO :EXIT + +:RETRY +@echo Oops, nuget restore exited with code %errorCode% - let us try again! +set /a retryNumber=%retryNumber%+1 +IF %reTryNumber% LSS %maxRetries% (GOTO :RESTORE) +IF %retryNumber% EQU %maxRetries% (GOTO :ERR) + +:ERR +@echo Sorry, we tried restoring nuget packages for %maxRetries% times and all attempts were unsuccessful! +EXIT /B 1 + +:EXIT diff --git a/appveyor.yml b/appveyor.yml index dc96d0bca..1e60c37d4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -46,7 +46,7 @@ install: - ps: $env:VSCOMNTOOLS=(Get-Content ("env:VS" + "$env:VSVER" + "0COMNTOOLS")) - echo "Using Visual Studio %VSVER%.0 at %VSCOMNTOOLS%" - call "%VSCOMNTOOLS%\..\..\VC\vcvarsall.bat" %VCVARS_PLATFORM% -- nuget install pcre -Verbosity detailed -Version 8.33.0.1 -OutputDirectory C:\pcre +- Tools\nuget-install.cmd pcre -Verbosity detailed -Version 8.33.0.1 -OutputDirectory C:\pcre - set PCRE_ROOT=C:/pcre/pcre.8.33.0.1/build/native - set PATH=C:\Python%VER%%LANG_PLATFORM%;%PATH% - python -V -- cgit v1.2.1