aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2013-12-14 15:12:07 +0000
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2013-12-14 15:12:07 +0000
commit314fae460b83389b87a83e003bfbc28271c495c1 (patch)
treeaae5d33c0dd3bb4268a2c273716578350f66b36b
parent4cf5de797f15fa0c2a500cea12db7c9223f07fdc (diff)
parent0f4ceaf5923fd9a30eb9201048cd285a9bba8084 (diff)
downloadswig-314fae460b83389b87a83e003bfbc28271c495c1.tar.gz
Merge branch 'nested' - nested structs/classes support
* nested: Deprecation of the 'nestedworkaround' feature Ensure -c++out is not used with -c++ Add missing header to new source file Nested C class setters restored in c++out mode for Octave Classprefix fixed after private nested classes some comments and spaces added Fix template partial specialization detection Minor tweaks in Swig_feature_set Swig_offset_string moved to misc.c nested private classes are discarded while parsing nested relate functions are moved to nested.cxx and renamed accordingly out-of-scope template definitions fixed nested_private test disabled again fixed out-of-scope nested class definitions, added a test enabled nested C structs assignment (still disabled for Octave), added Java runtime test fixed nested_private test case for Java & C# Testcase of private nested class usage causing segfault C nested struct passed by value example Add in Travis testing for nested branch Add C++ nested class example Minor code improvements Cosmetics/code beautification of nested class support Nested classes support
-rw-r--r--.travis.yml1
-rw-r--r--Doc/Manual/SWIGPlus.html140
-rw-r--r--Doc/Manual/Warnings.html1
-rw-r--r--Examples/csharp/check.list1
-rw-r--r--Examples/csharp/nested/Makefile19
-rw-r--r--Examples/csharp/nested/example-cs.csproj94
-rw-r--r--Examples/csharp/nested/example-vc.vcproj158
-rw-r--r--Examples/csharp/nested/example.cxx62
-rw-r--r--Examples/csharp/nested/example.h48
-rw-r--r--Examples/csharp/nested/example.i13
-rw-r--r--Examples/csharp/nested/example.sln30
-rw-r--r--Examples/csharp/nested/runme.cs27
-rw-r--r--Examples/java/check.list1
-rw-r--r--Examples/java/nested/Makefile18
-rw-r--r--Examples/java/nested/example.cxx62
-rw-r--r--Examples/java/nested/example.dsp162
-rw-r--r--Examples/java/nested/example.h48
-rw-r--r--Examples/java/nested/example.i13
-rw-r--r--Examples/java/nested/runme.java32
-rw-r--r--Examples/test-suite/common.mk2
-rw-r--r--Examples/test-suite/derived_nested.i10
-rw-r--r--Examples/test-suite/java/nested_class_runme.java62
-rw-r--r--Examples/test-suite/java/nested_structs_runme.java21
-rw-r--r--Examples/test-suite/java/template_nested_runme.java4
-rw-r--r--Examples/test-suite/namespace_class.i10
-rw-r--r--Examples/test-suite/namespace_union.i2
-rw-r--r--Examples/test-suite/nested_class.i24
-rw-r--r--Examples/test-suite/nested_comment.i2
-rw-r--r--Examples/test-suite/nested_private.i32
-rw-r--r--Examples/test-suite/nested_scope.i14
-rw-r--r--Examples/test-suite/nested_structs.i16
-rw-r--r--Examples/test-suite/nested_workaround.i20
-rw-r--r--Examples/test-suite/octave/nested_structs_runme.m14
-rw-r--r--Examples/test-suite/template_nested.i19
-rw-r--r--Examples/test-suite/template_nested_typemaps.i6
-rw-r--r--Examples/test-suite/union_scope.i1
-rw-r--r--Lib/swig.swg11
-rw-r--r--Lib/typemaps/swigtype.swg6
-rw-r--r--Source/CParse/cparse.h3
-rw-r--r--Source/CParse/cscanner.c21
-rw-r--r--Source/CParse/parser.y1028
-rw-r--r--Source/Include/swigwarn.h3
-rw-r--r--Source/Makefile.am1
-rw-r--r--Source/Modules/allocate.cxx6
-rw-r--r--Source/Modules/contract.cxx6
-rw-r--r--Source/Modules/csharp.cxx232
-rw-r--r--Source/Modules/java.cxx192
-rw-r--r--Source/Modules/lang.cxx56
-rw-r--r--Source/Modules/main.cxx29
-rw-r--r--Source/Modules/nested.cxx444
-rw-r--r--Source/Modules/octave.cxx5
-rw-r--r--Source/Modules/swigmod.h12
-rw-r--r--Source/Modules/typepass.cxx35
-rw-r--r--Source/Swig/cwrap.c22
-rw-r--r--Source/Swig/misc.c49
-rw-r--r--Source/Swig/naming.c76
-rw-r--r--Source/Swig/scanner.c108
-rw-r--r--Source/Swig/swig.h5
-rw-r--r--Source/Swig/swigscan.h1
-rw-r--r--Source/Swig/swigtree.h1
-rw-r--r--Source/Swig/tree.c18
61 files changed, 2435 insertions, 1124 deletions
diff --git a/.travis.yml b/.travis.yml
index 70cbb2f27..7f868ae91 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -57,3 +57,4 @@ script:
branches:
only:
- master
+ - nested
diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html
index 2ed450c01..3c3c7d564 100644
--- a/Doc/Manual/SWIGPlus.html
+++ b/Doc/Manual/SWIGPlus.html
@@ -185,7 +185,6 @@ The following C++ features are not currently supported:</p>
<ul>
<li>Overloaded versions of certain operators (new, delete, etc.)
-<li>Nested classes, see <a href="#SWIGPlus_nested_classes">Nested classes</a> for workarounds.
</ul>
<p>
@@ -4965,143 +4964,56 @@ public:
<H2><a name="SWIGPlus_nested_classes"></a>6.27 Nested classes</H2>
-
-<p>
-There is some support for nested structs and unions when wrapping C code,
-see <a href="SWIG.html#SWIG_nested_structs">Nested structures</a> for further details.
-The added complexity of C++ compared to C means this approach does not work well for
-C++ code (when using the -c++ command line option).
-For C++, a nested class is treated much like an opaque pointer, so anything useful within the nested class, such as its
-methods and variables, are not accessible from the target language.
-True nested class support may be added to SWIG in the future, however,
-until then some of the following workarounds can be applied to improve the situation.
-</p>
-
-<p>
-It might be possible to use partial class information as often you can accept that the nested class is not needed,
-especially if it is not actually used in any methods you need from the target language.
-Imagine you are wrapping the following <tt>Outer</tt> class which contains a nested class <tt>Inner</tt>.
-The easiest thing to do is turn a blind eye to the warning that SWIG generates, or simply suppress it:
-</p>
-
-<div class="code">
-<pre>
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::Inner;
-
-class Outer {
-public:
- class Inner {
- public:
- ...
- };
- Inner getInner();
- void useInner(const Inner&amp; inner);
- ...
-};
-</pre>
-</div>
-
<p>
-Note that if <tt>Inner</tt> can be used as an opaque type, the default wrapping approach suffices.
-For example, if the nested class does not need to be created from the target language, but can be obtained via a method
-call, such as the <tt>getInner()</tt> method above, the returned value can then be passed around, such as passed into the
-<tt>useInner()</tt> method.
+If the target language supports the nested classes concept (like Java), the nested C++ classes
+are wrapped as nested target language proxy classes. (In case of Java - "static" nested classes.)
+Only public nested classes are wrapped. Otherwise there is little difference between nested and
+normal classes.
</p>
-
-<p>
-With some more effort the above situation can be improved somewhat and a nested class can be constructed and used
-from the target language much like any other non-nested class. Assuming we have the <tt>Outer</tt> class in a header file:
-</p>
-
-<div class="code">
-<pre>
-// File outer.h
-class Outer {
-public:
- class Inner {
- public:
- int var;
- Inner(int v = 0) : var(v) {}
- };
- Inner getInner();
- void useInner(const Inner&amp; inner);
-};
-</pre>
-</div>
-
<p>
-The following interface file works around the nested class limitations by redefining the nested class as a global class.
-A typedef for the compiler and the <tt>nestedworkaround</tt>
-<a href="Customization.html#Customization_feature_flags">feature flag</a> is also required in
-order for the generated wrappers to compile. This flag simply removes all the type information from SWIG, so SWIG treats
-the nested class as if it had not been parsed at all.
+If the target language doesn't support nested classes directly, or the support is not implemented in the
+language module (like for python currently), then the visible nested classes are moved to the same name
+space as the containing class (nesting hierarchy is "flattened"). The same behaviour may be turned on for
+C# and Java by the %feature ("flatnested"); If there is a class with the same name in the outer namespace
+the inner class (or the global one) may be renamed or ignored:
</p>
<div class="code">
<pre>
-// File : example.i
-%module example
-
-// Redefine nested class in global scope in order for SWIG to generate
-// a proxy class. Only SWIG parses this definition.
-class Inner {
+%rename (Bar_Foo) Bar::Foo;
+class Foo {};
+class Bar {
public:
- int var;
- Inner(int v = 0) : var(v) {}
+ class Foo {};
};
-
-%nestedworkaround Outer::Inner;
-
-%{
-#include "outer.h"
-%}
-%include "outer.h"
-
-// We've fooled SWIG into thinking that Inner is a global class, so now we need
-// to trick the C++ compiler into understanding this apparent global type.
-%{
-typedef Outer::Inner Inner;
-%}
</pre>
</div>
-<p>
-The downside to this approach is a more complex interface file and having to maintain two definitions of <tt>Inner</tt>,
-the real one and the one in the interface file that SWIG parses.
-However, the upside is that all the methods/variables in the nested class are available from the target language
-as a proxy class is generated instead of treating the nested class as an opaque type.
-The proxy class can be constructed from the target language and passed into any methods accepting the nested class.
-Also note that the original header file is parsed unmodified.
-</p>
<p>
-Finally, conditional compilation can be used as a workaround to comment out nested class definitions in the actual headers,
-assuming you are able to modify them.
+<b>Compatibility Note:</b>
+Prior to SWIG-3.0.0, there was limited nested class support. Nested classes were treated as opaque pointers.
+However, there was a workaround for nested class support in these older versions requiring the user to replicate
+the nested class in the global scope, adding in a typedef for the nested class in the global scope and
+using the "nestedworkaround" feature on the nested class. This resulted in approximately the
+same behaviour as the "flatnested" feature. With proper nested class support now available in SWIG-3.0.0, this
+feature has been deprecated and no longer works requiring code changes. If you see the following warning:
</p>
-<div class="code">
+<div class="shell">
<pre>
-// File outer.h
-class Outer {
-public:
-#ifndef SWIG
- class Inner {
- public:
- ...
- };
-#endif
- ...
-};
+example.i:8: Warning 126: The nestedworkaround feature is deprecated
</pre>
</div>
<p>
-This workaround used to be common when SWIG could not deal with nested classes particulary well.
-This should just be a last resort for unusual corner cases now as SWIG can parse nested classes and even handle nested template classes fairly well.
+consider using the "flatnested" feature discussed above which generates a non-nested proxy class, like the
+"nestedworkaround" feature did. Alternatively, use the default nested class code generation, which may generate an
+equivalent to a nested proxy class in the target language, depending on the target language support.
</p>
<p>
-<b>Compatibility Note:</b> SWIG-1.3.40 and earlier versions did not have the <tt>nestedworkaround</tt> feature
+SWIG-1.3.40 and earlier versions did not have the <tt>nestedworkaround</tt> feature
and the generated code resulting from parsing nested classes did not always compile.
Nested class warnings could also not be suppressed using %warnfilter.
</p>
diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html
index e0debe41c..b4d27872c 100644
--- a/Doc/Manual/Warnings.html
+++ b/Doc/Manual/Warnings.html
@@ -382,6 +382,7 @@ example.i(4) : Syntax error in input.
<li>119. Deprecated <tt>%typemap(ignore)</tt>.
<li>120. Deprecated command line option (-runtime, -noruntime).
<li>121. Deprecated <tt>%name</tt> directive.
+<li>126. The 'nestedworkaround' feature is deprecated.
</ul>
<H3><a name="Warnings_nn11"></a>14.9.2 Preprocessor (200-299)</H3>
diff --git a/Examples/csharp/check.list b/Examples/csharp/check.list
index 5454d8531..a530a4b42 100644
--- a/Examples/csharp/check.list
+++ b/Examples/csharp/check.list
@@ -5,6 +5,7 @@ class
enum
extend
funcptr
+nested
reference
simple
template
diff --git a/Examples/csharp/nested/Makefile b/Examples/csharp/nested/Makefile
new file mode 100644
index 000000000..bc3ce8ce8
--- /dev/null
+++ b/Examples/csharp/nested/Makefile
@@ -0,0 +1,19 @@
+TOP = ../..
+SWIG = $(TOP)/../preinst-swig
+CXXSRCS = example.cxx
+TARGET = example
+INTERFACE = example.i
+SWIGOPT =
+CSHARPSRCS = *.cs
+CSHARPFLAGS= -nologo -out:runme.exe
+
+check: build
+ $(MAKE) -f $(TOP)/Makefile csharp_run
+
+build:
+ $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
+ SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' csharp_cpp
+ $(MAKE) -f $(TOP)/Makefile CSHARPSRCS='$(CSHARPSRCS)' CSHARPFLAGS='$(CSHARPFLAGS)' csharp_compile
+
+clean:
+ $(MAKE) -f $(TOP)/Makefile csharp_clean
diff --git a/Examples/csharp/nested/example-cs.csproj b/Examples/csharp/nested/example-cs.csproj
new file mode 100644
index 000000000..8004780fb
--- /dev/null
+++ b/Examples/csharp/nested/example-cs.csproj
@@ -0,0 +1,94 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "runme"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Exe"
+ PreBuildEvent = ""
+ PostBuildEvent = ""
+ RootNamespace = "runme"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "false"
+ OutputPath = ".\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = ".\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References/>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "example.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "examplePINVOKE.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "MotorCar.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "runme.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/Examples/csharp/nested/example-vc.vcproj b/Examples/csharp/nested/example-vc.vcproj
new file mode 100644
index 000000000..5788bc9c7
--- /dev/null
+++ b/Examples/csharp/nested/example-vc.vcproj
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="example"
+ ProjectGUID="{C2302635-D489-4678-96B4-70F5309DCBE6}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="2"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;EXAMPLEVC_EXPORTS"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="example.dll"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/example.pdb"
+ SubSystem="2"
+ ImportLibrary="$(OutDir)/example.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="2"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;EXAMPLEVC_EXPORTS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="example.dll"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(OutDir)/example.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="example.cxx">
+ </File>
+ <File
+ RelativePath="example_wrap.cxx">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="example.h">
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\example.i">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="echo Invoking SWIG...
+echo on
+..\..\..\swig.exe -c++ -csharp &quot;$(InputPath)&quot;
+@echo off"
+ Outputs="$(InputName)_wrap.cxx"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="echo Invoking SWIG...
+echo on
+..\..\..\swig.exe -c++ -csharp &quot;$(InputPath)&quot;
+@echo off"
+ Outputs="$(InputName)_wrap.cxx"/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Examples/csharp/nested/example.cxx b/Examples/csharp/nested/example.cxx
new file mode 100644
index 000000000..03bb74d9e
--- /dev/null
+++ b/Examples/csharp/nested/example.cxx
@@ -0,0 +1,62 @@
+#include "example.h"
+
+int MotorCar::DesignOpinion::AceDesignCount = 0;
+int MotorCar::DesignOpinion::TotalDesignCount = 0;
+
+int MotorCar::DesignOpinion::PercentScore() {
+ return AceDesignCount*100/TotalDesignCount;
+}
+
+MotorCar::Wheels::Wheels(Shape shape, size_t count) : shape(shape), count(count) {}
+
+MotorCar::WindScreen::WindScreen(bool opaque) : opaque(opaque) {}
+
+MotorCar::MotorCar(const std::string &name, const Wheels &wheels, const WindScreen &windscreen) : name(name), wheels(wheels), windscreen(windscreen) {}
+
+MotorCar MotorCar::DesignFromComponents(const std::string &name, const Wheels &wheels, const WindScreen &windscreen) {
+ MotorCar car = MotorCar(name, wheels, windscreen);
+ DesignOpinion::TotalDesignCount++;
+ if (car.wheels.Opinion().itrocks && car.windscreen.Opinion().itrocks)
+ DesignOpinion::AceDesignCount++;
+ return car;
+}
+
+MotorCar::DesignOpinion MotorCar::Wheels::Opinion() {
+ DesignOpinion opinion;
+ opinion.itrocks = true;
+ if (shape == Square) {
+ opinion.itrocks = false;
+ opinion.reason = "you'll have a few issues with wheel rotation";
+ }
+ if (count <= 2) {
+ opinion.reason += opinion.itrocks ? "" : " and ";
+ opinion.itrocks = false;
+ opinion.reason += "a few more wheels are needed for stability";
+ }
+ if (opinion.itrocks)
+ opinion.reason = "your choice of wheels was top notch";
+
+ return opinion;
+}
+
+MotorCar::DesignOpinion MotorCar::WindScreen::Opinion() {
+ DesignOpinion opinion;
+ opinion.itrocks = !opaque;
+ opinion.reason = opinion.itrocks ? "the driver will have a commanding view out the window" : "you can't see out the windscreen";
+ return opinion;
+}
+
+std::string MotorCar::WillItWork() {
+ DesignOpinion wh = wheels.Opinion();
+ DesignOpinion ws = windscreen.Opinion();
+ std::string willit;
+ if (wh.itrocks && ws.itrocks) {
+ willit = "Great car design because " + wh.reason + " and " + ws.reason;
+ } else {
+ willit = "You need a rethink because ";
+ willit += wh.itrocks ? "" : wh.reason;
+ willit += (!wh.itrocks && !ws.itrocks) ? " and " : "";
+ willit += ws.itrocks ? "" : ws.reason;
+ }
+ return willit;
+}
diff --git a/Examples/csharp/nested/example.h b/Examples/csharp/nested/example.h
new file mode 100644
index 000000000..4fb107cb5
--- /dev/null
+++ b/Examples/csharp/nested/example.h
@@ -0,0 +1,48 @@
+#include <string>
+
+/** Design a motor car from various components */
+struct MotorCar {
+
+ /** Information about an opinion of the design of a car component */
+ struct DesignOpinion {
+ bool itrocks;
+ std::string reason;
+ static int AceDesignCount;
+ static int TotalDesignCount;
+ static int PercentScore();
+ };
+
+ /** Wheels component */
+ struct Wheels {
+ enum Shape { Round, Square };
+ Wheels(Shape shape, size_t count);
+ DesignOpinion Opinion();
+ private:
+ Shape shape;
+ size_t count;
+ };
+
+ /** Windscreen component */
+ struct WindScreen {
+ WindScreen(bool opaque);
+ DesignOpinion Opinion();
+ private:
+ bool opaque;
+ };
+
+ /** Factory method for creating a car */
+ static MotorCar DesignFromComponents(const std::string &name, const Wheels &wheels, const WindScreen &windscreen);
+
+ std::string Name() {
+ return name;
+ }
+
+ /** Get an overall opinion on the car design */
+ std::string WillItWork();
+
+private:
+ MotorCar(const std::string &name, const Wheels &wheels, const WindScreen &windscreen);
+ std::string name;
+ Wheels wheels;
+ WindScreen windscreen;
+};
diff --git a/Examples/csharp/nested/example.i b/Examples/csharp/nested/example.i
new file mode 100644
index 000000000..c07c1521a
--- /dev/null
+++ b/Examples/csharp/nested/example.i
@@ -0,0 +1,13 @@
+%module example
+
+// This example shows how wrappers for numerous aspects of C++ nested classes work:
+// Nested static and instance variables and methods and nested enums
+
+%include <std_string.i>
+
+%{
+#include "example.h"
+%}
+
+%include "example.h"
+
diff --git a/Examples/csharp/nested/example.sln b/Examples/csharp/nested/example.sln
new file mode 100644
index 000000000..88995ffd3
--- /dev/null
+++ b/Examples/csharp/nested/example.sln
@@ -0,0 +1,30 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-cs", "example-cs.csproj", "{C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}"
+ ProjectSection(ProjectDependencies) = postProject
+ {C2302635-D489-4678-96B4-70F5309DCBE6} = {C2302635-D489-4678-96B4-70F5309DCBE6}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example-vc", "example-vc.vcproj", "{C2302635-D489-4678-96B4-70F5309DCBE6}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}.Debug.ActiveCfg = Debug|.NET
+ {C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}.Debug.Build.0 = Debug|.NET
+ {C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}.Release.ActiveCfg = Release|.NET
+ {C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}.Release.Build.0 = Release|.NET
+ {C2302635-D489-4678-96B4-70F5309DCBE6}.Debug.ActiveCfg = Debug|Win32
+ {C2302635-D489-4678-96B4-70F5309DCBE6}.Debug.Build.0 = Debug|Win32
+ {C2302635-D489-4678-96B4-70F5309DCBE6}.Release.ActiveCfg = Release|Win32
+ {C2302635-D489-4678-96B4-70F5309DCBE6}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Examples/csharp/nested/runme.cs b/Examples/csharp/nested/runme.cs
new file mode 100644
index 000000000..facaefdb7
--- /dev/null
+++ b/Examples/csharp/nested/runme.cs
@@ -0,0 +1,27 @@
+// This example illustrates how C++ classes can be used from C# using SWIG.
+// The C# class gets mapped onto the C++ class and behaves as if it is a C# class.
+
+using System;
+
+public class runme
+{
+ static void Main()
+ {
+ MotorCar car1 = MotorCar.DesignFromComponents("Bumpy", new MotorCar.Wheels(MotorCar.Wheels.Shape.Square, 4), new MotorCar.WindScreen(false));
+ MotorCar car2 = MotorCar.DesignFromComponents("Wobbly", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 2), new MotorCar.WindScreen(false));
+ MotorCar car3 = MotorCar.DesignFromComponents("Batty", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 4), new MotorCar.WindScreen(true));
+ MotorCar car4 = MotorCar.DesignFromComponents("Spiffing", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 4), new MotorCar.WindScreen(false));
+
+ Console.WriteLine("Expert opinion on " + car1.Name() + " : \n " + car1.WillItWork());
+ Console.WriteLine("Expert opinion on " + car2.Name() + " : \n " + car2.WillItWork());
+ Console.WriteLine("Expert opinion on " + car3.Name() + " : \n " + car3.WillItWork());
+ Console.WriteLine("Expert opinion on " + car4.Name() + " : \n " + car4.WillItWork());
+
+ int count = MotorCar.DesignOpinion.AceDesignCount;
+ int total = MotorCar.DesignOpinion.TotalDesignCount;
+ int percent = MotorCar.DesignOpinion.PercentScore();
+ Console.WriteLine("Overall opinion rating on car design is " + count + "/" + total + " = " + percent + "%");
+
+ Console.WriteLine("Single square wheel thoughts: " + new MotorCar.Wheels(MotorCar.Wheels.Shape.Square, 1).Opinion().reason);
+ }
+}
diff --git a/Examples/java/check.list b/Examples/java/check.list
index 9728342f2..825d04a6d 100644
--- a/Examples/java/check.list
+++ b/Examples/java/check.list
@@ -7,6 +7,7 @@ extend
funcptr
multimap
native
+nested
pointer
reference
simple
diff --git a/Examples/java/nested/Makefile b/Examples/java/nested/Makefile
new file mode 100644
index 000000000..8f274e7cb
--- /dev/null
+++ b/Examples/java/nested/Makefile
@@ -0,0 +1,18 @@
+TOP = ../..
+SWIG = $(TOP)/../preinst-swig
+CXXSRCS = example.cxx
+TARGET = example
+INTERFACE = example.i
+SWIGOPT =
+JAVASRCS = *.java
+
+check: build
+ $(MAKE) -f $(TOP)/Makefile java_run
+
+build:
+ $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
+ SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' java_cpp
+ $(MAKE) -f $(TOP)/Makefile JAVASRCS='$(JAVASRCS)' JAVAFLAGS='$(JAVAFLAGS)' java_compile
+
+clean:
+ $(MAKE) -f $(TOP)/Makefile java_clean
diff --git a/Examples/java/nested/example.cxx b/Examples/java/nested/example.cxx
new file mode 100644
index 000000000..03bb74d9e
--- /dev/null
+++ b/Examples/java/nested/example.cxx
@@ -0,0 +1,62 @@
+#include "example.h"
+
+int MotorCar::DesignOpinion::AceDesignCount = 0;
+int MotorCar::DesignOpinion::TotalDesignCount = 0;
+
+int MotorCar::DesignOpinion::PercentScore() {
+ return AceDesignCount*100/TotalDesignCount;
+}
+
+MotorCar::Wheels::Wheels(Shape shape, size_t count) : shape(shape), count(count) {}
+
+MotorCar::WindScreen::WindScreen(bool opaque) : opaque(opaque) {}
+
+MotorCar::MotorCar(const std::string &name, const Wheels &wheels, const WindScreen &windscreen) : name(name), wheels(wheels), windscreen(windscreen) {}
+
+MotorCar MotorCar::DesignFromComponents(const std::string &name, const Wheels &wheels, const WindScreen &windscreen) {
+ MotorCar car = MotorCar(name, wheels, windscreen);
+ DesignOpinion::TotalDesignCount++;
+ if (car.wheels.Opinion().itrocks && car.windscreen.Opinion().itrocks)
+ DesignOpinion::AceDesignCount++;
+ return car;
+}
+
+MotorCar::DesignOpinion MotorCar::Wheels::Opinion() {
+ DesignOpinion opinion;
+ opinion.itrocks = true;
+ if (shape == Square) {
+ opinion.itrocks = false;
+ opinion.reason = "you'll have a few issues with wheel rotation";
+ }
+ if (count <= 2) {
+ opinion.reason += opinion.itrocks ? "" : " and ";
+ opinion.itrocks = false;
+ opinion.reason += "a few more wheels are needed for stability";
+ }
+ if (opinion.itrocks)
+ opinion.reason = "your choice of wheels was top notch";
+
+ return opinion;
+}
+
+MotorCar::DesignOpinion MotorCar::WindScreen::Opinion() {
+ DesignOpinion opinion;
+ opinion.itrocks = !opaque;
+ opinion.reason = opinion.itrocks ? "the driver will have a commanding view out the window" : "you can't see out the windscreen";
+ return opinion;
+}
+
+std::string MotorCar::WillItWork() {
+ DesignOpinion wh = wheels.Opinion();
+ DesignOpinion ws = windscreen.Opinion();
+ std::string willit;
+ if (wh.itrocks && ws.itrocks) {
+ willit = "Great car design because " + wh.reason + " and " + ws.reason;
+ } else {
+ willit = "You need a rethink because ";
+ willit += wh.itrocks ? "" : wh.reason;
+ willit += (!wh.itrocks && !ws.itrocks) ? " and " : "";
+ willit += ws.itrocks ? "" : ws.reason;
+ }
+ return willit;
+}
diff --git a/Examples/java/nested/example.dsp b/Examples/java/nested/example.dsp
new file mode 100644
index 000000000..f52544b95
--- /dev/null
+++ b/Examples/java/nested/example.dsp
@@ -0,0 +1,162 @@
+# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=example - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "example.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "example - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "example - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "example - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "$(JAVA_INCLUDE)" /I "$(JAVA_INCLUDE)\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Java compile post-build step
+PostBuild_Cmds=echo on "%JAVA_BIN%\javac" *.java
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "example - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "$(JAVA_INCLUDE)" /I "$(JAVA_INCLUDE)\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /machine:I386 /out:"example.dll"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Java compile post-build step
+PostBuild_Cmds=echo on "%JAVA_BIN%\javac" *.java
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "example - Win32 Debug"
+# Name "example - Win32 Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\example.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=.\example_wrap.cxx
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\example.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=.\example.i
+
+!IF "$(CFG)" == "example - Win32 Debug"
+
+# Begin Custom Build
+InputPath=.\example.i
+InputName=example
+
+"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo JAVA_INCLUDE: %JAVA_INCLUDE%
+ echo JAVA_BIN: %JAVA_BIN%
+ echo on
+ ..\..\..\swig.exe -c++ -java "$(InputPath)"
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "example - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\example.i
+InputName=example
+
+"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo JAVA_INCLUDE: %JAVA_INCLUDE%
+ echo JAVA_BIN: %JAVA_BIN%
+ echo on
+ ..\..\..\swig.exe -c++ -java "$(InputPath)"
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/java/nested/example.h b/Examples/java/nested/example.h
new file mode 100644
index 000000000..4fb107cb5
--- /dev/null
+++ b/Examples/java/nested/example.h
@@ -0,0 +1,48 @@
+#include <string>
+
+/** Design a motor car from various components */
+struct MotorCar {
+
+ /** Information about an opinion of the design of a car component */
+ struct DesignOpinion {
+ bool itrocks;
+ std::string reason;
+ static int AceDesignCount;
+ static int TotalDesignCount;
+ static int PercentScore();
+ };
+
+ /** Wheels component */
+ struct Wheels {
+ enum Shape { Round, Square };
+ Wheels(Shape shape, size_t count);
+ DesignOpinion Opinion();
+ private:
+ Shape shape;
+ size_t count;
+ };
+
+ /** Windscreen component */
+ struct WindScreen {
+ WindScreen(bool opaque);
+ DesignOpinion Opinion();
+ private:
+ bool opaque;
+ };
+
+ /** Factory method for creating a car */
+ static MotorCar DesignFromComponents(const std::string &name, const Wheels &wheels, const WindScreen &windscreen);
+
+ std::string Name() {
+ return name;
+ }
+
+ /** Get an overall opinion on the car design */
+ std::string WillItWork();
+
+private:
+ MotorCar(const std::string &name, const Wheels &wheels, const WindScreen &windscreen);
+ std::string name;
+ Wheels wheels;
+ WindScreen windscreen;
+};
diff --git a/Examples/java/nested/example.i b/Examples/java/nested/example.i
new file mode 100644
index 000000000..c07c1521a
--- /dev/null
+++ b/Examples/java/nested/example.i
@@ -0,0 +1,13 @@
+%module example
+
+// This example shows how wrappers for numerous aspects of C++ nested classes work:
+// Nested static and instance variables and methods and nested enums
+
+%include <std_string.i>
+
+%{
+#include "example.h"
+%}
+
+%include "example.h"
+
diff --git a/Examples/java/nested/runme.java b/Examples/java/nested/runme.java
new file mode 100644
index 000000000..855dbea91
--- /dev/null
+++ b/Examples/java/nested/runme.java
@@ -0,0 +1,32 @@
+// This example illustrates wrapping of nested C++ classes
+
+public class runme {
+ static {
+ try {
+ System.loadLibrary("example");
+ } catch (UnsatisfiedLinkError e) {
+ System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
+ System.exit(1);
+ }
+ }
+
+ public static void main(String argv[])
+ {
+ MotorCar car1 = MotorCar.DesignFromComponents("Bumpy", new MotorCar.Wheels(MotorCar.Wheels.Shape.Square, 4), new MotorCar.WindScreen(false));
+ MotorCar car2 = MotorCar.DesignFromComponents("Wobbly", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 2), new MotorCar.WindScreen(false));
+ MotorCar car3 = MotorCar.DesignFromComponents("Batty", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 4), new MotorCar.WindScreen(true));
+ MotorCar car4 = MotorCar.DesignFromComponents("Spiffing", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 4), new MotorCar.WindScreen(false));
+
+ System.out.println("Expert opinion on " + car1.Name() + " : \n " + car1.WillItWork());
+ System.out.println("Expert opinion on " + car2.Name() + " : \n " + car2.WillItWork());
+ System.out.println("Expert opinion on " + car3.Name() + " : \n " + car3.WillItWork());
+ System.out.println("Expert opinion on " + car4.Name() + " : \n " + car4.WillItWork());
+
+ int count = MotorCar.DesignOpinion.getAceDesignCount();
+ int total = MotorCar.DesignOpinion.getTotalDesignCount();
+ int percent = MotorCar.DesignOpinion.PercentScore();
+ System.out.println("Overall opinion rating on car design is " + count + "/" + total + " = " + percent + "%");
+
+ System.out.println("Single square wheel thoughts: " + new MotorCar.Wheels(MotorCar.Wheels.Shape.Square, 1).Opinion().getReason());
+ }
+}
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index c65fd7901..7972b28d8 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -84,6 +84,7 @@ CPP_TEST_BROKEN += \
extend_variable \
li_std_vector_ptr \
li_boost_shared_ptr_template \
+ nested_private \
overload_complicated \
template_default_pointer \
template_expr \
@@ -279,6 +280,7 @@ CPP_TEST_CASES += \
naturalvar_more \
nested_class \
nested_comment \
+ nested_scope \
nested_workaround \
newobject1 \
null_pointer \
diff --git a/Examples/test-suite/derived_nested.i b/Examples/test-suite/derived_nested.i
index 29114d5a0..e374cf70f 100644
--- a/Examples/test-suite/derived_nested.i
+++ b/Examples/test-suite/derived_nested.i
@@ -3,14 +3,12 @@ This was reported in bug #909389 */
%module derived_nested
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) BB::CC;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) BB::DD;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) BB::EE;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) BB::FF;
-
%inline %{
-class A { int x; };
+class A {
+public:
+ int x;
+};
class B {
class C { int y; }; //generates a warning
class D : public A { int z; }; //ok
diff --git a/Examples/test-suite/java/nested_class_runme.java b/Examples/test-suite/java/nested_class_runme.java
index f1c67a0af..f75613e65 100644
--- a/Examples/test-suite/java/nested_class_runme.java
+++ b/Examples/test-suite/java/nested_class_runme.java
@@ -14,59 +14,59 @@ public class nested_class_runme {
public static void main(String argv[]) {
Outer outer = new Outer();
- SWIGTYPE_p_Outer__InnerStruct1 is1 = outer.makeInnerStruct1();
- SWIGTYPE_p_Outer__InnerClass1 ic1 = outer.makeInnerClass1();
- SWIGTYPE_p_Outer__InnerUnion1 iu1 = outer.makeInnerUnion1();
+ Outer.InnerStruct1 is1 = outer.makeInnerStruct1();
+ Outer.InnerClass1 ic1 = outer.makeInnerClass1();
+ Outer.InnerUnion1 iu1 = outer.makeInnerUnion1();
- SWIGTYPE_p_Outer__InnerStruct2 is2 = outer.makeInnerStruct2();
- SWIGTYPE_p_Outer__InnerClass2 ic2 = outer.makeInnerClass2();
- SWIGTYPE_p_Outer__InnerUnion2 iu2 = outer.makeInnerUnion2();
+ Outer.InnerStruct2 is2 = outer.makeInnerStruct2();
+ Outer.InnerClass2 ic2 = outer.makeInnerClass2();
+ Outer.InnerUnion2 iu2 = outer.makeInnerUnion2();
- SWIGTYPE_p_Outer__InnerClass4Typedef ic4 = outer.makeInnerClass4Typedef();
- SWIGTYPE_p_Outer__InnerStruct4Typedef is4 = outer.makeInnerStruct4Typedef();
- SWIGTYPE_p_Outer__InnerUnion4Typedef iu4 = outer.makeInnerUnion4Typedef();
+ Outer.InnerClass4Typedef ic4 = outer.makeInnerClass4Typedef();
+ Outer.InnerStruct4Typedef is4 = outer.makeInnerStruct4Typedef();
+ Outer.InnerUnion4Typedef iu4 = outer.makeInnerUnion4Typedef();
- SWIGTYPE_p_Outer__InnerClass5 ic5 = outer.makeInnerClass5();
- SWIGTYPE_p_Outer__InnerStruct5 is5 = outer.makeInnerStruct5();
- SWIGTYPE_p_Outer__InnerUnion5 iu5 = outer.makeInnerUnion5();
+ Outer.InnerClass5Typedef ic5 = outer.makeInnerClass5();
+ Outer.InnerStruct5Typedef is5 = outer.makeInnerStruct5();
+ Outer.InnerUnion5Typedef iu5 = outer.makeInnerUnion5();
ic5 = outer.makeInnerClass5Typedef();
is5 = outer.makeInnerStruct5Typedef();
iu5 = outer.makeInnerUnion5Typedef();
{
- SWIGTYPE_p_Outer__InnerMultiple im1 = outer.getMultipleInstance1();
- SWIGTYPE_p_Outer__InnerMultiple im2 = outer.getMultipleInstance2();
- SWIGTYPE_p_Outer__InnerMultiple im3 = outer.getMultipleInstance3();
- SWIGTYPE_p_Outer__InnerMultiple im4 = outer.getMultipleInstance4();
+ Outer.InnerMultiple im1 = outer.getMultipleInstance1();
+ Outer.InnerMultiple im2 = outer.getMultipleInstance2();
+ Outer.InnerMultiple im3 = outer.getMultipleInstance3();
+ Outer.InnerMultiple im4 = outer.getMultipleInstance4();
}
{
- SWIGTYPE_p_Outer__InnerMultipleDerived im1 = outer.getMultipleDerivedInstance1();
- SWIGTYPE_p_Outer__InnerMultipleDerived im2 = outer.getMultipleDerivedInstance2();
- SWIGTYPE_p_Outer__InnerMultipleDerived im3 = outer.getMultipleDerivedInstance3();
- SWIGTYPE_p_Outer__InnerMultipleDerived im4 = outer.getMultipleDerivedInstance4();
+ Outer.InnerMultipleDerived im1 = outer.getMultipleDerivedInstance1();
+ Outer.InnerMultipleDerived im2 = outer.getMultipleDerivedInstance2();
+ Outer.InnerMultipleDerived im3 = outer.getMultipleDerivedInstance3();
+ Outer.InnerMultipleDerived im4 = outer.getMultipleDerivedInstance4();
}
{
- SWIGTYPE_p_Outer__InnerMultipleDerived im1 = outer.getMultipleDerivedInstance1();
- SWIGTYPE_p_Outer__InnerMultipleDerived im2 = outer.getMultipleDerivedInstance2();
- SWIGTYPE_p_Outer__InnerMultipleDerived im3 = outer.getMultipleDerivedInstance3();
- SWIGTYPE_p_Outer__InnerMultipleDerived im4 = outer.getMultipleDerivedInstance4();
+ Outer.InnerMultipleDerived im1 = outer.getMultipleDerivedInstance1();
+ Outer.InnerMultipleDerived im2 = outer.getMultipleDerivedInstance2();
+ Outer.InnerMultipleDerived im3 = outer.getMultipleDerivedInstance3();
+ Outer.InnerMultipleDerived im4 = outer.getMultipleDerivedInstance4();
}
{
- SWIGTYPE_p_Outer__InnerMultipleAnonTypedef1 mat1 = outer.makeInnerMultipleAnonTypedef1();
- SWIGTYPE_p_Outer__InnerMultipleAnonTypedef2 mat2 = outer.makeInnerMultipleAnonTypedef2();
- SWIGTYPE_p_Outer__InnerMultipleAnonTypedef3 mat3 = outer.makeInnerMultipleAnonTypedef3();
+ Outer.InnerMultipleAnonTypedef1 mat1 = outer.makeInnerMultipleAnonTypedef1();
+ Outer.InnerMultipleAnonTypedef1 mat2 = outer.makeInnerMultipleAnonTypedef2();
+ SWIGTYPE_p_p_Outer__InnerMultipleAnonTypedef1 mat3 = outer.makeInnerMultipleAnonTypedef3();
- SWIGTYPE_p_Outer__InnerMultipleNamedTypedef mnt = outer.makeInnerMultipleNamedTypedef();
- SWIGTYPE_p_Outer__InnerMultipleNamedTypedef mnt1 = outer.makeInnerMultipleNamedTypedef1();
- SWIGTYPE_p_Outer__InnerMultipleNamedTypedef mnt2 = outer.makeInnerMultipleNamedTypedef2();
+ Outer.InnerMultipleNamedTypedef1 mnt = outer.makeInnerMultipleNamedTypedef();
+ Outer.InnerMultipleNamedTypedef1 mnt1 = outer.makeInnerMultipleNamedTypedef1();
+ Outer.InnerMultipleNamedTypedef1 mnt2 = outer.makeInnerMultipleNamedTypedef2();
SWIGTYPE_p_p_Outer__InnerMultipleNamedTypedef mnt3 = outer.makeInnerMultipleNamedTypedef3();
}
{
- SWIGTYPE_p_Outer__InnerSameName isn = outer.makeInnerSameName();
+ Outer.InnerSameName isn = outer.makeInnerSameName();
}
}
}
diff --git a/Examples/test-suite/java/nested_structs_runme.java b/Examples/test-suite/java/nested_structs_runme.java
index 6e103cd12..43c5e2897 100644
--- a/Examples/test-suite/java/nested_structs_runme.java
+++ b/Examples/test-suite/java/nested_structs_runme.java
@@ -17,21 +17,28 @@ public class nested_structs_runme {
nested_structs.setValues(outer, 10);
Outer_inner1 inner1 = outer.getInner1();
- Outer_inner2 inner2 = outer.getInner2();
- Outer_inner3 inner3 = outer.getInner3();
- Outer_inner4 inner4 = outer.getInner4();
+ Outer_inner1 inner2 = outer.getInner2();
+ Outer_inner1 inner3 = outer.getInner3();
+ Outer_inner1 inner4 = outer.getInner4();
if (inner1.getVal() != 10) throw new RuntimeException("failed inner1");
if (inner2.getVal() != 20) throw new RuntimeException("failed inner2");
if (inner3.getVal() != 20) throw new RuntimeException("failed inner3");
if (inner4.getVal() != 40) throw new RuntimeException("failed inner4");
- Outer_inside1 inside1 = outer.getInside1();
- Outer_inside2 inside2 = outer.getInside2();
- Outer_inside3 inside3 = outer.getInside3();
- Outer_inside4 inside4 = outer.getInside4();
+ Named inside1 = outer.getInside1();
+ Named inside2 = outer.getInside2();
+ Named inside3 = outer.getInside3();
+ Named inside4 = outer.getInside4();
if (inside1.getVal() != 100) throw new RuntimeException("failed inside1");
if (inside2.getVal() != 200) throw new RuntimeException("failed inside2");
if (inside3.getVal() != 200) throw new RuntimeException("failed inside3");
if (inside4.getVal() != 400) throw new RuntimeException("failed inside4");
+
+ outer.getInner1().setVal(11);
+ if (inner1.getVal() != 11) throw new RuntimeException("failed inner1 assignment");
+ Named named = new Named();
+ named.setVal(22);
+ outer.setInside2(named);
+ if (outer.getInside2().getVal() != 22) throw new RuntimeException("failed inside2 assignment");
}
}
diff --git a/Examples/test-suite/java/template_nested_runme.java b/Examples/test-suite/java/template_nested_runme.java
index 407821674..422e7ea9e 100644
--- a/Examples/test-suite/java/template_nested_runme.java
+++ b/Examples/test-suite/java/template_nested_runme.java
@@ -25,6 +25,10 @@ public class template_nested_runme {
T_NestedOuterTemplateDouble tn = new T_NestedOuterTemplateDouble();
if (tn.hohum(-12.3) != -12.3)
throw new RuntimeException("it failed");
+ OuterClass.T_OuterClassInner1Int inner1 = new OuterClass().useInner1(new OuterClass.T_OuterClassInner1Int());
+ OuterClass.T_OuterClassInner2NormalClass inner2 = new OuterClass.T_OuterClassInner2NormalClass();
+ inner2.setEmbeddedVar(2);
+ OuterClass.T_OuterClassInner2NormalClass inner22 = new OuterClass().useInner2Again(inner2);
}
}
diff --git a/Examples/test-suite/namespace_class.i b/Examples/test-suite/namespace_class.i
index aea5362d1..113bbeb35 100644
--- a/Examples/test-suite/namespace_class.i
+++ b/Examples/test-suite/namespace_class.i
@@ -1,6 +1,5 @@
%module namespace_class
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Ala::Ola;
#ifdef SWIGD
%warnfilter(SWIGWARN_IGNORE_OPERATOR_LT);
@@ -216,9 +215,6 @@ namespace a
%}
-// %copyctor doesn't work with nested class workaround
-%nocopyctor;
-
%inline %{
class Ala {
public :
@@ -236,12 +232,6 @@ namespace a
};
%}
-%rename(Ala__Ola) Ala::Ola;
-class Ala::Ola {
-public:
- Ola() {}
- void eek() {}
-};
%template(hi) Ala::hi<int>;
diff --git a/Examples/test-suite/namespace_union.i b/Examples/test-suite/namespace_union.i
index 85885f399..84e38b4d5 100644
--- a/Examples/test-suite/namespace_union.i
+++ b/Examples/test-suite/namespace_union.i
@@ -1,7 +1,5 @@
%module namespace_union
-#pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS
-
%inline %{
namespace SpatialIndex
{
diff --git a/Examples/test-suite/nested_class.i b/Examples/test-suite/nested_class.i
index d67440ac9..0d418192d 100644
--- a/Examples/test-suite/nested_class.i
+++ b/Examples/test-suite/nested_class.i
@@ -1,25 +1,5 @@
%module nested_class
-#pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct1;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass1;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion1;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass2;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct2;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion2;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass4Typedef;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct4Typedef;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion4Typedef;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass5;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct5;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion5;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultiple;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultipleDerived;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultipleAnonTypedef1;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultipleNamedTypedef;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerSameName;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer2::IgnoreMe;
-
%inline %{
struct Outer {
typedef int Integer;
@@ -39,7 +19,7 @@ struct Outer {
};
///////////////////////////////////////////
-#ifdef SWIG
+#if defined(__GNUC__) || defined(_MSC_VER) || defined(SWIG)
/* some compilers do not accept these */
class {
public:
@@ -154,7 +134,7 @@ struct Outer {
Integer xx;
} MultipleInstanceAnonDerived1, MultipleInstanceAnonDerived2, *MultipleInstanceAnonDerived3, MultipleInstanceAnonDerived4[2];
-#ifdef SWIG
+#if defined(__GNUC__) || defined(_MSC_VER) || defined(SWIG)
/* some compilers do not accept these */
struct : public InnerMultiple {
Integer xx;
diff --git a/Examples/test-suite/nested_comment.i b/Examples/test-suite/nested_comment.i
index 99d0ffb43..df160b157 100644
--- a/Examples/test-suite/nested_comment.i
+++ b/Examples/test-suite/nested_comment.i
@@ -1,7 +1,5 @@
%module nested_comment
-#pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS
-
// this example shows a problem with 'dump_nested' (parser.y).
// bug #949654
diff --git a/Examples/test-suite/nested_private.i b/Examples/test-suite/nested_private.i
new file mode 100644
index 000000000..a573fdd5a
--- /dev/null
+++ b/Examples/test-suite/nested_private.i
@@ -0,0 +1,32 @@
+%module nested_private
+
+// segfault due to private nested class usage
+
+%inline %{
+#include <string>
+class MotorCar {
+
+ struct DesignOpinion {
+ std::string reason;
+ };
+
+public:
+ struct WindScreen {
+ WindScreen(bool opaque) : opaque(opaque) {}
+ DesignOpinion Opinion();
+ private:
+ bool opaque;
+ };
+
+ std::string WindScreenOpinion() {
+ return MotorCar::WindScreen(true).Opinion().reason;
+ }
+};
+
+MotorCar::DesignOpinion MotorCar::WindScreen::Opinion() {
+ DesignOpinion opinion;
+ opinion.reason = !opaque ? "great design" : "you can't see out the windscreen";
+ return opinion;
+}
+
+%}
diff --git a/Examples/test-suite/nested_scope.i b/Examples/test-suite/nested_scope.i
new file mode 100644
index 000000000..358dbbb61
--- /dev/null
+++ b/Examples/test-suite/nested_scope.i
@@ -0,0 +1,14 @@
+%module nested_scope
+
+%inline %{
+namespace ns {
+ struct Global {
+ struct Outer {
+ struct Nested;
+ };
+ struct Outer::Nested {
+ int data;
+ } instance;
+ };
+}
+%} \ No newline at end of file
diff --git a/Examples/test-suite/nested_structs.i b/Examples/test-suite/nested_structs.i
index c15623085..44ff994ba 100644
--- a/Examples/test-suite/nested_structs.i
+++ b/Examples/test-suite/nested_structs.i
@@ -25,5 +25,21 @@ void setValues(struct Outer *outer, int val) {
outer->inside4[0].val = val * 4;
outer->inside5 = &outer->inside3;
}
+
+int getInside1Val(struct Outer *n) { return n->inside1.val; }
+%}
+
+/*
+Below was causing problems in Octave as wrappers were compiled as C++.
+Solution requires regenerating the inner struct into
+the global C++ namespace (which is where it is intended to be in C).
+*/
+%inline %{
+int nestedByVal(struct Named s);
+int nestedByPtr(struct Named *s);
+%}
+%{
+int nestedByVal(struct Named s) { return s.val; }
+int nestedByPtr(struct Named *s) { return s->val; }
%}
diff --git a/Examples/test-suite/nested_workaround.i b/Examples/test-suite/nested_workaround.i
index 9727dacee..bb69a5bbd 100644
--- a/Examples/test-suite/nested_workaround.i
+++ b/Examples/test-suite/nested_workaround.i
@@ -1,14 +1,6 @@
%module nested_workaround
-// Similar to "Nested classes" documentation example.
-
-class Inner {
- int val;
- public:
- Inner(int v = 0) : val(v) {}
- void setValue(int v) { val = v; }
- int getValue() const { return val; }
-};
-%nestedworkaround Outer::Inner;
+// "flatnested" emulates deprecated feature "nested_workaround" for the languages not supporting nested classes
+%feature ("flatnested");
%inline %{
class Outer {
@@ -28,11 +20,3 @@ public:
}
};
%}
-
-// We've fooled SWIG into thinking that Inner is a global class, so now we need
-// to trick the C++ compiler into understanding this apparent global type.
-%{
-typedef Outer::Inner Inner;
-%}
-
-
diff --git a/Examples/test-suite/octave/nested_structs_runme.m b/Examples/test-suite/octave/nested_structs_runme.m
new file mode 100644
index 000000000..a04aaa672
--- /dev/null
+++ b/Examples/test-suite/octave/nested_structs_runme.m
@@ -0,0 +1,14 @@
+nested_structs
+
+named = nested_structs.Named();
+named.val = 999;
+assert(nested_structs.nestedByVal(named), 999);
+assert(nested_structs.nestedByPtr(named), 999);
+
+outer = nested_structs.Outer();
+outer.inside1.val = 456;
+assert(nested_structs.getInside1Val(outer), 456);
+
+outer.inside1 = named;
+assert(nested_structs.getInside1Val(outer), 999);
+
diff --git a/Examples/test-suite/template_nested.i b/Examples/test-suite/template_nested.i
index 1bb1c686a..bbca9502c 100644
--- a/Examples/test-suite/template_nested.i
+++ b/Examples/test-suite/template_nested.i
@@ -2,13 +2,6 @@
// Test nested templates - that is template classes and template methods within a class.
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterClass::Inner1;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterClass::Inner2;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterTemplate::NestedInnerTemplate1;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterTemplate::NestedInnerTemplate2;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterTemplate::NestedInnerTemplate3;
-%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) ns::OuterTemplate::NestedStruct;
-
namespace ns {
template <class T> struct ForwardTemplate;
}
@@ -33,7 +26,13 @@ namespace ns {
template <class T> struct NormalTemplate {
void tmethod(T t) {}
};
+}
+%}
+%template(T_NormalTemplateNormalClass) ns::NormalTemplate<ns::NormalClass>;
+%template(T_NormalTemplateInt) ns::NormalTemplate<int>;
+%inline %{
+namespace ns {
class OuterClass {
public:
template <class T> struct Inner1 {
@@ -70,6 +69,7 @@ namespace ns {
};
};
Inner2<int> useInner2(const Inner2<int>& inner) { return inner; }
+ Inner2<NormalClass> useInner2Again(const Inner2<NormalClass>& inner) { return inner; }
int iii;
};
struct ABC {
@@ -108,9 +108,10 @@ namespace ns {
%}
-%template(T_NormalTemplateNormalClass) ns::NormalTemplate<ns::NormalClass>;
%template(T_OuterTMethodNormalClass) ns::OuterClass::InnerTMethod<ns::NormalClass>;
%template(T_TemplateFuncs1Int) ns::TemplateFuncs::templateMethod1<int>;
%template(T_TemplateFuncs2Double) ns::TemplateFuncs::templateMethod2<double>;
%template(T_NestedOuterTemplateDouble) ns::OuterTemplate<double>;
-
+%template(T_OuterClassInner1Int) ns::OuterClass::Inner1<int>;
+%template(T_OuterClassInner2NormalClass) ns::OuterClass::Inner2<ns::NormalClass>;
+%template(T_OuterClassInner2Int) ns::OuterClass::Inner2<int>;
diff --git a/Examples/test-suite/template_nested_typemaps.i b/Examples/test-suite/template_nested_typemaps.i
index 54f5bc503..b40e7e291 100644
--- a/Examples/test-suite/template_nested_typemaps.i
+++ b/Examples/test-suite/template_nested_typemaps.i
@@ -4,18 +4,22 @@
// Testing that the typemaps invoked within a class via %template are picked up by appropriate methods
+%inline %{
template <typename T> struct Typemap {
+#ifdef SWIG
%typemap(in) T {
$1 = -99;
}
+#endif
};
template <> struct Typemap<short> { // Note explicit specialization
+#ifdef SWIG
%typemap(in) short {
$1 = -77;
}
+#endif
};
-%inline %{
int globalInt1(int s) { return s; }
short globalShort1(short s) { return s; }
diff --git a/Examples/test-suite/union_scope.i b/Examples/test-suite/union_scope.i
index b7307cb29..67093eff6 100644
--- a/Examples/test-suite/union_scope.i
+++ b/Examples/test-suite/union_scope.i
@@ -2,7 +2,6 @@
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) nRState; // Ruby, wrong class name
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) nRState_rstate; // Ruby, wrong class name
-#pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS
%inline %{
class nRState {
diff --git a/Lib/swig.swg b/Lib/swig.swg
index 241d93f3f..edadf036d 100644
--- a/Lib/swig.swg
+++ b/Lib/swig.swg
@@ -9,7 +9,7 @@
* User Directives
* ----------------------------------------------------------------------------- */
-/* Deprecated SWIG directives */
+/* Deprecated SWIG-1.1 directives */
#define %disabledoc %warn "104:%disabledoc is deprecated"
#define %enabledoc %warn "105:%enabledoc is deprecated"
@@ -136,11 +136,16 @@
#define %nocallback %feature("callback","0")
#define %clearcallback %feature("callback","")
-/* the %nestedworkaround directive */
+/* the %nestedworkaround directive (deprecated) */
#define %nestedworkaround %feature("nestedworkaround")
#define %nonestedworkaround %feature("nestedworkaround","0")
#define %clearnestedworkaround %feature("nestedworkaround","")
+/* the %flatnested directive */
+#define %flatnested %feature("flatnested")
+#define %noflatnested %feature("flatnested","0")
+#define %clearflatnested %feature("flatnested","")
+
/* the %fastdispatch directive */
#define %fastdispatch %feature("fastdispatch")
#define %nofastdispatch %feature("fastdispatch","0")
@@ -302,7 +307,7 @@ static int NAME(TYPE x) {
%define %$ismemberset "match$memberset"="1" %enddef
%define %$classname %$ismember,"match$parentNode$name" %enddef
-
+%define %$isnested "match$nested"="1" %enddef
/* -----------------------------------------------------------------------------
* Include all the warnings labels and macros
* ----------------------------------------------------------------------------- */
diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg
index 5e92790d8..6c0affbe2 100644
--- a/Lib/typemaps/swigtype.swg
+++ b/Lib/typemaps/swigtype.swg
@@ -159,7 +159,7 @@
%typemap(memberin) SWIGTYPE [ANY] {
if ($input) {
size_t ii = 0;
- for (; ii < (size_t)$1_dim0; ++ii) $1[ii] = $input[ii];
+ for (; ii < (size_t)$1_dim0; ++ii) *($1_ltype)&$1[ii] = ($*1_ltype)$input[ii];
} else {
%variable_nullref("$type","$name");
}
@@ -168,7 +168,7 @@
%typemap(globalin) SWIGTYPE [ANY] {
if ($input) {
size_t ii = 0;
- for (; ii < (size_t)$1_dim0; ++ii) $1[ii] = $input[ii];
+ for (; ii < (size_t)$1_dim0; ++ii) *($1_ltype)&$1[ii] = ($*1_ltype)$input[ii];
} else {
%variable_nullref("$type","$name");
}
@@ -181,7 +181,7 @@
%variable_fail(res, "$type", "$name");
} else if (inp) {
size_t ii = 0;
- for (; ii < (size_t)$1_dim0; ++ii) $1[ii] = inp[ii];
+ for (; ii < (size_t)$1_dim0; ++ii) *($1_ltype)&$1[ii] = ($*1_ltype)inp[ii];
} else {
%variable_nullref("$type", "$name");
}
diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h
index 922bbfcdc..6d7342a45 100644
--- a/Source/CParse/cparse.h
+++ b/Source/CParse/cparse.h
@@ -25,12 +25,15 @@ extern "C" {
extern String *cparse_file;
extern int cparse_line;
extern int cparse_cplusplus;
+ extern int cparse_cplusplusout;
extern int cparse_start_line;
extern void Swig_cparse_cplusplus(int);
+ extern void Swig_cparse_cplusplusout(int);
extern void scanner_file(File *);
extern void scanner_next_token(int);
extern void skip_balanced(int startchar, int endchar);
+ extern String *get_raw_text_balanced(int startchar, int endchar);
extern void skip_decl(void);
extern void scanner_check_typedef(void);
extern void scanner_ignore_typedef(void);
diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c
index c04ce4688..2dfc2c479 100644
--- a/Source/CParse/cscanner.c
+++ b/Source/CParse/cscanner.c
@@ -37,6 +37,9 @@ int cparse_start_line = 0;
/* C++ mode */
int cparse_cplusplus = 0;
+/* Generate C++ compatible code when wrapping C code */
+int cparse_cplusplusout = 0;
+
/* Private vars */
static int scan_init = 0;
static int num_brace = 0;
@@ -52,6 +55,14 @@ void Swig_cparse_cplusplus(int v) {
cparse_cplusplus = v;
}
+/* -----------------------------------------------------------------------------
+ * Swig_cparse_cplusplusout()
+ * ----------------------------------------------------------------------------- */
+
+void Swig_cparse_cplusplusout(int v) {
+ cparse_cplusplusout = v;
+}
+
/* ----------------------------------------------------------------------------
* scanner_init()
*
@@ -118,6 +129,16 @@ void skip_balanced(int startchar, int endchar) {
return;
}
+/* -----------------------------------------------------------------------------
+ * get_raw_text_balanced()
+ *
+ * Returns raw text between 2 braces
+ * ----------------------------------------------------------------------------- */
+
+String *get_raw_text_balanced(int startchar, int endchar) {
+ return Scanner_get_raw_text_balanced(scan, startchar, endchar);
+}
+
/* ----------------------------------------------------------------------------
* void skip_decl(void)
*
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index 3384dcc5b..203284402 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -51,7 +51,7 @@ static Node *module_node = 0;
static String *Classprefix = 0;
static String *Namespaceprefix = 0;
static int inclass = 0;
-static int nested_template = 0; /* template class/function definition within a class */
+static Node *currentOuterClass = 0; /* for nested classes */
static char *last_cpptype = 0;
static int inherit_list = 0;
static Parm *template_parameters = 0;
@@ -60,10 +60,6 @@ static int compact_default_args = 0;
static int template_reduce = 0;
static int cparse_externc = 0;
-static int max_class_levels = 0;
-static int class_level = 0;
-static Node **class_decl = NULL;
-
/* -----------------------------------------------------------------------------
* Assist Functions
* ----------------------------------------------------------------------------- */
@@ -165,7 +161,6 @@ static Node *copy_node(Node *n) {
static char *typemap_lang = 0; /* Current language setting */
static int cplus_mode = 0;
-static String *class_rename = 0;
/* C++ modes */
@@ -237,6 +232,25 @@ static String *feature_identifier_fix(String *s) {
}
}
+static void set_access_mode(Node *n) {
+ if (cplus_mode == CPLUS_PUBLIC)
+ Setattr(n, "access", "public");
+ else if (cplus_mode == CPLUS_PROTECTED)
+ Setattr(n, "access", "protected");
+ else
+ Setattr(n, "access", "private");
+}
+
+static void restore_access_mode(Node *n) {
+ String *mode = Getattr(n, "access");
+ if (Strcmp(mode, "private") == 0)
+ cplus_mode = CPLUS_PRIVATE;
+ else if (Strcmp(mode, "protected") == 0)
+ cplus_mode = CPLUS_PROTECTED;
+ else
+ cplus_mode = CPLUS_PUBLIC;
+}
+
/* Generate the symbol table name for an object */
/* This is a bit of a mess. Need to clean up */
static String *add_oldname = 0;
@@ -283,13 +297,6 @@ static void add_symbols(Node *n) {
String *decl;
String *wrn = 0;
- if (nested_template) {
- if (!(n && Equal(nodeType(n), "template"))) {
- return;
- }
- /* continue if template function, but not template class, declared within a class */
- }
-
if (inclass && n) {
cparse_normalize_void(n);
}
@@ -301,9 +308,6 @@ static void add_symbols(Node *n) {
int isfriend = inclass && is_friend(n);
int iscdecl = Cmp(nodeType(n),"cdecl") == 0;
int only_csymbol = 0;
- if (extendmode) {
- Setattr(n,"isextension","1");
- }
if (inclass) {
String *name = Getattr(n, "name");
@@ -349,9 +353,6 @@ static void add_symbols(Node *n) {
Delete(prefix);
}
- /*
- if (!Getattr(n,"parentNode") && class_level) set_parentNode(n,class_decl[class_level - 1]);
- */
Setattr(n,"ismember","1");
}
}
@@ -793,53 +794,31 @@ static String *make_class_name(String *name) {
return nname;
}
-static List *make_inherit_list(String *clsname, List *names) {
- int i, ilen;
- String *derived;
- List *bases = NewList();
-
- if (Namespaceprefix) derived = NewStringf("%s::%s", Namespaceprefix,clsname);
- else derived = NewString(clsname);
-
- ilen = Len(names);
- for (i = 0; i < ilen; i++) {
- Node *s;
- String *base;
- String *n = Getitem(names,i);
- /* Try to figure out where this symbol is */
- s = Swig_symbol_clookup(n,0);
- if (s) {
- while (s && (Strcmp(nodeType(s),"class") != 0)) {
- /* Not a class. Could be a typedef though. */
- String *storage = Getattr(s,"storage");
- if (storage && (Strcmp(storage,"typedef") == 0)) {
- String *nn = Getattr(s,"type");
- s = Swig_symbol_clookup(nn,Getattr(s,"sym:symtab"));
- } else {
- break;
- }
- }
- if (s && ((Strcmp(nodeType(s),"class") == 0) || (Strcmp(nodeType(s),"template") == 0))) {
- String *q = Swig_symbol_qualified(s);
- Append(bases,s);
- if (q) {
- base = NewStringf("%s::%s", q, Getattr(s,"name"));
- Delete(q);
- } else {
- base = NewString(Getattr(s,"name"));
- }
- } else {
- base = NewString(n);
- }
- } else {
- base = NewString(n);
- }
- if (base) {
- Swig_name_inherit(base,derived);
- Delete(base);
+/* Use typedef name as class name */
+
+static void add_typedef_name(Node *n, Node *decl, String *oldName, Symtab *cscope, String *scpname) {
+ String *class_rename = 0;
+ SwigType *decltype = Getattr(decl, "decl");
+ if (!decltype || !Len(decltype)) {
+ String *cname;
+ String *tdscopename;
+ String *class_scope = Swig_symbol_qualifiedscopename(cscope);
+ String *name = Getattr(decl, "name");
+ cname = Copy(name);
+ Setattr(n, "tdname", cname);
+ tdscopename = class_scope ? NewStringf("%s::%s", class_scope, name) : Copy(name);
+ class_rename = Getattr(n, "class_rename");
+ if (class_rename && (Strcmp(class_rename, oldName) == 0))
+ Setattr(n, "class_rename", NewString(name));
+ if (!classes_typedefs) classes_typedefs = NewHash();
+ if (!Equal(scpname, tdscopename) && !Getattr(classes_typedefs, tdscopename)) {
+ Setattr(classes_typedefs, tdscopename, n);
}
+ Setattr(n, "decl", decltype);
+ Delete(class_scope);
+ Delete(cname);
+ Delete(tdscopename);
}
- return bases;
}
/* If the class name is qualified. We need to create or lookup namespace entries */
@@ -1059,352 +1038,33 @@ static String *resolve_create_node_scope(String *cname) {
return cname;
}
-
-
-/* Structures for handling code fragments built for nested classes */
-
-typedef struct Nested {
- String *code; /* Associated code fragment */
- int line; /* line number where it starts */
- const char *name; /* Name associated with this nested class */
- const char *kind; /* Kind of class */
- int unnamed; /* unnamed class */
- SwigType *type; /* Datatype associated with the name */
- struct Nested *next; /* Next code fragment in list */
-} Nested;
-
-/* Some internal variables for saving nested class information */
-
-static Nested *nested_list = 0;
-
-/* Add a function to the nested list */
-
-static void add_nested(Nested *n) {
- if (!nested_list) {
- nested_list = n;
- } else {
- Nested *n1 = nested_list;
- while (n1->next)
- n1 = n1->next;
- n1->next = n;
- }
-}
-
-/* -----------------------------------------------------------------------------
- * nested_new_struct()
- *
- * Nested struct handling for C code only creates a global struct from the nested struct.
- *
- * Nested structure. This is a sick "hack". If we encounter
- * a nested structure, we're going to grab the text of its definition and
- * feed it back into the scanner. In the meantime, we need to grab
- * variable declaration information and generate the associated wrapper
- * code later. Yikes!
- *
- * This really only works in a limited sense. Since we use the
- * code attached to the nested class to generate both C code
- * it can't have any SWIG directives in it. It also needs to be parsable
- * by SWIG or this whole thing is going to puke.
- * ----------------------------------------------------------------------------- */
-
-static void nested_new_struct(const char *kind, String *struct_code, Node *cpp_opt_declarators) {
- String *name;
- String *decl;
-
- /* Create a new global struct declaration which is just a copy of the nested struct */
- Nested *nested = (Nested *) malloc(sizeof(Nested));
- Nested *n = nested;
-
- name = Getattr(cpp_opt_declarators, "name");
- decl = Getattr(cpp_opt_declarators, "decl");
-
- n->code = NewStringEmpty();
- Printv(n->code, "typedef ", kind, " ", struct_code, " $classname_", name, ";\n", NIL);
- n->name = Swig_copy_string(Char(name));
- n->line = cparse_start_line;
- n->type = NewStringEmpty();
- n->kind = kind;
- n->unnamed = 0;
- SwigType_push(n->type, decl);
- n->next = 0;
-
- /* Repeat for any multiple instances of the nested struct */
- {
- Node *p = cpp_opt_declarators;
- p = nextSibling(p);
- while (p) {
- Nested *nn = (Nested *) malloc(sizeof(Nested));
-
- name = Getattr(p, "name");
- decl = Getattr(p, "decl");
-
- nn->code = NewStringEmpty();
- Printv(nn->code, "typedef ", kind, " ", struct_code, " $classname_", name, ";\n", NIL);
- nn->name = Swig_copy_string(Char(name));
- nn->line = cparse_start_line;
- nn->type = NewStringEmpty();
- nn->kind = kind;
- nn->unnamed = 0;
- SwigType_push(nn->type, decl);
- nn->next = 0;
- n->next = nn;
- n = nn;
- p = nextSibling(p);
- }
- }
-
- add_nested(nested);
-}
-
-/* -----------------------------------------------------------------------------
- * nested_forward_declaration()
- *
- * Nested struct handling for C++ code only.
- *
- * Treat the nested class/struct/union as a forward declaration until a proper
- * nested class solution is implemented.
- * ----------------------------------------------------------------------------- */
-
-static Node *nested_forward_declaration(const char *storage, const char *kind, String *sname, String *name, Node *cpp_opt_declarators) {
- Node *nn = 0;
- int warned = 0;
-
- if (sname) {
- /* Add forward declaration of the nested type */
- Node *n = new_node("classforward");
- Setattr(n, "kind", kind);
- Setattr(n, "name", sname);
- Setattr(n, "storage", storage);
- Setattr(n, "sym:weak", "1");
- add_symbols(n);
- nn = n;
- }
-
- /* Add any variable instances. Also add in any further typedefs of the nested type.
- Note that anonymous typedefs (eg typedef struct {...} a, b;) are treated as class forward declarations */
- if (cpp_opt_declarators) {
- int storage_typedef = (storage && (strcmp(storage, "typedef") == 0));
- int variable_of_anonymous_type = !sname && !storage_typedef;
- if (!variable_of_anonymous_type) {
- int anonymous_typedef = !sname && (storage && (strcmp(storage, "typedef") == 0));
- Node *n = cpp_opt_declarators;
- SwigType *type = name;
- while (n) {
- Setattr(n, "type", type);
- Setattr(n, "storage", storage);
- if (anonymous_typedef) {
- Setattr(n, "nodeType", "classforward");
- Setattr(n, "sym:weak", "1");
- }
- n = nextSibling(n);
- }
- add_symbols(cpp_opt_declarators);
-
- if (nn) {
- set_nextSibling(nn, cpp_opt_declarators);
- } else {
- nn = cpp_opt_declarators;
+/* look for simple typedef name in typedef list */
+static String *try_to_find_a_name_for_unnamed_structure(const char *storage, Node *decls) {
+ String *name = 0;
+ Node *n = decls;
+ if (storage && (strcmp(storage, "typedef") == 0)) {
+ for (; n; n = nextSibling(n)) {
+ if (!Len(Getattr(n, "decl"))) {
+ name = Copy(Getattr(n, "name"));
+ break;
}
}
}
-
- if (nn && Equal(nodeType(nn), "classforward")) {
- Node *n = nn;
- if (GetFlag(n, "feature:nestedworkaround")) {
- Swig_symbol_remove(n);
- nn = 0;
- warned = 1;
- } else {
- SWIG_WARN_NODE_BEGIN(n);
- Swig_warning(WARN_PARSE_NAMED_NESTED_CLASS, cparse_file, cparse_line,"Nested %s not currently supported (%s ignored)\n", kind, sname ? sname : name);
- SWIG_WARN_NODE_END(n);
- warned = 1;
- }
- }
-
- if (!warned)
- Swig_warning(WARN_PARSE_UNNAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", kind);
-
- return nn;
+ return name;
}
-/* Strips C-style and C++-style comments from string in-place. */
-static void strip_comments(char *string) {
- int state = 0; /*
- * 0 - not in comment
- * 1 - in c-style comment
- * 2 - in c++-style comment
- * 3 - in string
- * 4 - after reading / not in comments
- * 5 - after reading * in c-style comments
- * 6 - after reading \ in strings
- */
- char * c = string;
- while (*c) {
- switch (state) {
- case 0:
- if (*c == '\"')
- state = 3;
- else if (*c == '/')
- state = 4;
- break;
- case 1:
- if (*c == '*')
- state = 5;
- *c = ' ';
- break;
- case 2:
- if (*c == '\n')
- state = 0;
- else
- *c = ' ';
- break;
- case 3:
- if (*c == '\"')
- state = 0;
- else if (*c == '\\')
- state = 6;
- break;
- case 4:
- if (*c == '/') {
- *(c-1) = ' ';
- *c = ' ';
- state = 2;
- } else if (*c == '*') {
- *(c-1) = ' ';
- *c = ' ';
- state = 1;
- } else
- state = 0;
- break;
- case 5:
- if (*c == '/')
- state = 0;
- else
- state = 1;
- *c = ' ';
- break;
- case 6:
- state = 3;
- break;
- }
- ++c;
+/* traverse copied tree segment, and update outer class links*/
+static void update_nested_classes(Node *n)
+{
+ Node *c = firstChild(n);
+ while (c) {
+ if (Getattr(c, "nested:outer"))
+ Setattr(c, "nested:outer", n);
+ update_nested_classes(c);
+ c = nextSibling(c);
}
}
-/* Dump all of the nested class declarations to the inline processor
- * However. We need to do a few name replacements and other munging
- * first. This function must be called before closing a class! */
-
-static Node *dump_nested(const char *parent) {
- Nested *n,*n1;
- Node *ret = 0;
- Node *last = 0;
- n = nested_list;
- if (!parent) {
- nested_list = 0;
- return 0;
- }
- while (n) {
- Node *retx;
- SwigType *nt;
- /* Token replace the name of the parent class */
- Replace(n->code, "$classname", parent, DOH_REPLACE_ANY);
-
- /* Fix up the name of the datatype (for building typedefs and other stuff) */
- Append(n->type,parent);
- Append(n->type,"_");
- Append(n->type,n->name);
-
- /* Add the appropriate declaration to the C++ processor */
- retx = new_node("cdecl");
- Setattr(retx,"name",n->name);
- nt = Copy(n->type);
- Setattr(retx,"type",nt);
- Delete(nt);
- Setattr(retx,"nested",parent);
- if (n->unnamed) {
- Setattr(retx,"unnamed","1");
- }
-
- add_symbols(retx);
- if (ret) {
- set_nextSibling(last, retx);
- Delete(retx);
- } else {
- ret = retx;
- }
- last = retx;
-
- /* Strip comments - further code may break in presence of comments. */
- strip_comments(Char(n->code));
-
- /* Make all SWIG created typedef structs/unions/classes unnamed else
- redefinition errors occur - nasty hack alert.*/
-
- {
- const char* types_array[3] = {"struct", "union", "class"};
- int i;
- for (i=0; i<3; i++) {
- char* code_ptr = Char(n->code);
- while (code_ptr) {
- /* Replace struct name (as in 'struct name {...}' ) with whitespace
- name will be between struct and opening brace */
-
- code_ptr = strstr(code_ptr, types_array[i]);
- if (code_ptr) {
- char *open_bracket_pos;
- code_ptr += strlen(types_array[i]);
- open_bracket_pos = strchr(code_ptr, '{');
- if (open_bracket_pos) {
- /* Make sure we don't have something like struct A a; */
- char* semi_colon_pos = strchr(code_ptr, ';');
- if (!(semi_colon_pos && (semi_colon_pos < open_bracket_pos)))
- while (code_ptr < open_bracket_pos)
- *code_ptr++ = ' ';
- }
- }
- }
- }
- }
-
- {
- /* Remove SWIG directive %constant which may be left in the SWIG created typedefs */
- char* code_ptr = Char(n->code);
- while (code_ptr) {
- code_ptr = strstr(code_ptr, "%constant");
- if (code_ptr) {
- char* directive_end_pos = strchr(code_ptr, ';');
- if (directive_end_pos) {
- while (code_ptr <= directive_end_pos)
- *code_ptr++ = ' ';
- }
- }
- }
- }
- {
- Node *newnode = new_node("insert");
- String *code = NewStringEmpty();
- Wrapper_pretty_print(n->code, code);
- Setattr(newnode,"code", code);
- Delete(code);
- set_nextSibling(last, newnode);
- Delete(newnode);
- last = newnode;
- }
-
- /* Dump the code to the scanner */
- start_inline(Char(Getattr(last, "code")),n->line);
-
- n1 = n->next;
- Delete(n->code);
- free(n);
- n = n1;
- }
- nested_list = 0;
- return ret;
-}
-
Node *Swig_cparse(File *f) {
scanner_file(f);
top = 0;
@@ -1420,6 +1080,10 @@ static void single_new_feature(const char *featurename, String *val, Hash *featu
/* Printf(stdout, "single_new_feature: [%s] [%s] [%s] [%s] [%s] [%s]\n", featurename, val, declaratorid, t, ParmList_str_defaultargs(declaratorparms), qualifier); */
+ /* Warn about deprecated features */
+ if (strcmp(featurename, "nestedworkaround") == 0)
+ Swig_warning(WARN_DEPRECATED_NESTED_WORKAROUND, cparse_file, cparse_line, "The 'nestedworkaround' feature is deprecated.\n");
+
fname = NewStringf("feature:%s",featurename);
if (declaratorid) {
fixname = feature_identifier_fix(declaratorid);
@@ -1768,7 +1432,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) {
%type <node> cpp_declaration cpp_class_decl cpp_forward_class_decl cpp_template_decl cpp_alternate_rettype;
%type <node> cpp_members cpp_member;
%type <node> cpp_constructor_decl cpp_destructor_decl cpp_protection_decl cpp_conversion_operator cpp_static_assert;
-%type <node> cpp_swig_directive cpp_temp_possible cpp_nested cpp_opt_declarators ;
+%type <node> cpp_swig_directive cpp_temp_possible cpp_opt_declarators ;
%type <node> cpp_using_decl cpp_namespace_decl cpp_catch_decl cpp_lambda_decl;
%type <node> kwargs options;
@@ -1930,6 +1594,7 @@ swig_directive : extend_directive { $$ = $1; }
extend_directive : EXTEND options idcolon LBRACE {
Node *cls;
String *clsname;
+ extendmode = 1;
cplus_mode = CPLUS_PUBLIC;
if (!classes) classes = NewHash();
if (!classes_typedefs) classes_typedefs = NewHash();
@@ -1955,7 +1620,6 @@ extend_directive : EXTEND options idcolon LBRACE {
Note that %extend before the class typedef never worked, only %extend after the class typdef. */
prev_symtab = Swig_symbol_setscope(Getattr(cls, "symtab"));
current_class = cls;
- extendmode = 1;
SWIG_WARN_NODE_BEGIN(cls);
Swig_warning(WARN_PARSE_EXTEND_NAME, cparse_file, cparse_line, "Deprecated %%extend name used - the %s name '%s' should be used instead of the typedef name '%s'.\n", Getattr(cls, "kind"), SwigType_namestr(Getattr(cls, "name")), $3);
SWIG_WARN_NODE_END(cls);
@@ -1964,7 +1628,6 @@ extend_directive : EXTEND options idcolon LBRACE {
/* Previous class definition. Use its symbol table */
prev_symtab = Swig_symbol_setscope(Getattr(cls,"symtab"));
current_class = cls;
- extendmode = 1;
}
Classprefix = NewString($3);
Namespaceprefix= Swig_symbol_qualifiedscopename(0);
@@ -2999,6 +2662,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
}
templnode = copy_node(nn);
+ update_nested_classes(templnode);
/* We need to set the node name based on name used to instantiate */
Setattr(templnode,"name",tname);
Delete(tname);
@@ -3007,7 +2671,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
} else {
Setattr(templnode,"sym:typename","1");
}
- if ($3 && !inclass) {
+ if ($3) {
/*
Comment this out for 1.3.28. We need to
re-enable it later but first we need to
@@ -3026,16 +2690,15 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
Setattr(templnode,"sym:name",nname);
Delete(nname);
Setattr(templnode,"feature:onlychildren", "typemap,typemapitem,typemapcopy,typedef,types,fragment");
-
- if ($3) {
- Swig_warning(WARN_PARSE_NESTED_TEMPLATE, cparse_file, cparse_line, "Named nested template instantiations not supported. Processing as if no name was given to %%template().\n");
- }
}
Delattr(templnode,"templatetype");
Setattr(templnode,"template",nn);
Setfile(templnode,cparse_file);
Setline(templnode,cparse_line);
Delete(temparms);
+ if (currentOuterClass) {
+ SetFlag(templnode, "nested");
+ }
add_symbols_copy(templnode);
@@ -3051,7 +2714,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
csyms = Swig_symbol_current();
Swig_symbol_setscope(Getattr(templnode,"symtab"));
if (baselist) {
- List *bases = make_inherit_list(Getattr(templnode,"name"),baselist);
+ List *bases = Swig_make_inherit_list(Getattr(templnode,"name"),baselist, Namespaceprefix);
if (bases) {
Iterator s;
for (s = First(bases); s.item; s = Next(s)) {
@@ -3703,10 +3366,10 @@ cpp_declaration : cpp_class_decl { $$ = $1; }
/* A simple class/struct/union definition */
cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
- if (nested_template == 0) {
String *prefix;
List *bases = 0;
Node *scope = 0;
+ String *code;
$<node>$ = new_node("class");
Setline($<node>$,cparse_start_line);
Setattr($<node>$,"kind",$2);
@@ -3718,41 +3381,30 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
Setattr($<node>$,"allows_typedef","1");
/* preserve the current scope */
- prev_symtab = Swig_symbol_current();
+ Setattr($<node>$,"prev_symtab",Swig_symbol_current());
/* If the class name is qualified. We need to create or lookup namespace/scope entries */
scope = resolve_create_node_scope($3);
+ /* save nscope_inner to the class - it may be overwritten in nested classes*/
+ Setattr($<node>$, "nested:innerscope", nscope_inner);
+ Setattr($<node>$, "nested:nscope", nscope);
Setfile(scope,cparse_file);
Setline(scope,cparse_line);
$3 = scope;
-
- /* support for old nested classes "pseudo" support, such as:
-
- %rename(Ala__Ola) Ala::Ola;
- class Ala::Ola {
- public:
- Ola() {}
- };
-
- this should disappear when a proper implementation is added.
- */
- if (nscope_inner && Strcmp(nodeType(nscope_inner),"namespace") != 0) {
- if (Namespaceprefix) {
- String *name = NewStringf("%s::%s", Namespaceprefix, $3);
- $3 = name;
- Namespaceprefix = 0;
- nscope_inner = 0;
- }
- }
Setattr($<node>$,"name",$3);
- Delete(class_rename);
- class_rename = make_name($<node>$,$3,0);
+ if (currentOuterClass) {
+ SetFlag($<node>$, "nested");
+ Setattr($<node>$, "nested:outer", currentOuterClass);
+ set_access_mode($<node>$);
+ }
+ /* save yyrename to the class attribute, to be used later in add_symbols()*/
+ Setattr($<node>$, "class_rename", make_name($<node>$, $3, 0));
+ Setattr($<node>$, "Classprefix", $3);
Classprefix = NewString($3);
/* Deal with inheritance */
- if ($4) {
- bases = make_inherit_list($3,Getattr($4,"public"));
- }
+ if ($4)
+ bases = Swig_make_inherit_list($3,Getattr($4,"public"),Namespaceprefix);
prefix = SwigType_istemplate_templateprefix($3);
if (prefix) {
String *fbase, *tbase;
@@ -3774,18 +3426,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
}
Swig_symbol_newscope();
Swig_symbol_setscopename($3);
- if (bases) {
- Iterator s;
- for (s = First(bases); s.item; s = Next(s)) {
- Symtab *st = Getattr(s.item,"symtab");
- if (st) {
- Setfile(st,Getfile(s.item));
- Setline(st,Getline(s.item));
- Swig_symbol_inherit(st);
- }
- }
- Delete(bases);
- }
+ Swig_inherit_base_symbols(bases);
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
cparse_start_line = cparse_line;
@@ -3804,31 +3445,34 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
Delete(tpname);
}
}
- if (class_level >= max_class_levels) {
- if (!max_class_levels) {
- max_class_levels = 16;
- } else {
- max_class_levels *= 2;
- }
- class_decl = (Node**) realloc(class_decl, sizeof(Node*) * max_class_levels);
- if (!class_decl) {
- Swig_error(cparse_file, cparse_line, "realloc() failed\n");
- }
- }
- class_decl[class_level++] = $<node>$;
Delete(prefix);
inclass = 1;
- }
+ currentOuterClass = $<node>$;
+ if (cparse_cplusplusout) {
+ /* save the structure declaration to declare it in global scope for C++ to see */
+ code = get_raw_text_balanced('{', '}');
+ Setattr($<node>$, "code", code);
+ Delete(code);
+ }
} cpp_members RBRACE cpp_opt_declarators {
- (void) $<node>6;
- if (nested_template == 0) {
Node *p;
SwigType *ty;
- Symtab *cscope = prev_symtab;
+ Symtab *cscope;
Node *am = 0;
String *scpname = 0;
- $$ = class_decl[--class_level];
- inclass = 0;
+ (void) $<node>6;
+ $$ = currentOuterClass;
+ currentOuterClass = Getattr($$, "nested:outer");
+ nscope_inner = Getattr($<node>$, "nested:innerscope");
+ nscope = Getattr($<node>$, "nested:nscope");
+ Delattr($<node>$, "nested:innerscope");
+ Delattr($<node>$, "nested:nscope");
+ if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0) /* actual parent class for this class */
+ Setattr($$, "nested:outer", nscope_inner);
+ if (!currentOuterClass)
+ inclass = 0;
+ cscope = Getattr($$, "prev_symtab");
+ Delattr($$, "prev_symtab");
/* Check for pure-abstract class */
Setattr($$,"abstracts", pure_abstracts($7));
@@ -3837,131 +3481,144 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
if (extendhash) {
String *clsname = Swig_symbol_qualifiedscopename(0);
- am = Getattr(extendhash,clsname);
+ am = Getattr(extendhash, clsname);
if (am) {
- merge_extensions($$,am);
- Delattr(extendhash,clsname);
+ merge_extensions($$, am);
+ Delattr(extendhash, clsname);
}
Delete(clsname);
}
if (!classes) classes = NewHash();
scpname = Swig_symbol_qualifiedscopename(0);
- Setattr(classes,scpname,$$);
+ Setattr(classes, scpname, $$);
- appendChild($$,$7);
+ appendChild($$, $7);
- if (am) append_previous_extension($$,am);
+ if (am)
+ append_previous_extension($$, am);
p = $9;
- if (p) {
- set_nextSibling($$,p);
+ if (p && !nscope_inner) {
+ if (!cparse_cplusplus && currentOuterClass)
+ appendChild(currentOuterClass, p);
+ else
+ appendSibling($$, p);
}
- if (cparse_cplusplus && !cparse_externc) {
+ if (nscope_inner) {
+ ty = NewString(scpname); /* if the class is declared out of scope, let the declarator use fully qualified type*/
+ } else if (cparse_cplusplus && !cparse_externc) {
ty = NewString($3);
} else {
- ty = NewStringf("%s %s", $2,$3);
+ ty = NewStringf("%s %s", $2, $3);
}
while (p) {
- Setattr(p,"storage",$1);
- Setattr(p,"type",ty);
- p = nextSibling(p);
- }
- /* Class typedefs */
- {
- String *name = $3;
- if ($9) {
- SwigType *decltype = Getattr($9,"decl");
- if (Cmp($1,"typedef") == 0) {
- if (!decltype || !Len(decltype)) {
- String *cname;
- String *tdscopename;
- String *class_scope = Swig_symbol_qualifiedscopename(cscope);
- name = Getattr($9,"name");
- cname = Copy(name);
- Setattr($$,"tdname",cname);
- tdscopename = class_scope ? NewStringf("%s::%s", class_scope, name) : Copy(name);
-
- /* Use typedef name as class name */
- if (class_rename && (Strcmp(class_rename,$3) == 0)) {
- Delete(class_rename);
- class_rename = NewString(name);
- }
- if (!classes_typedefs) classes_typedefs = NewHash();
- if (!Equal(scpname, tdscopename) && !Getattr(classes_typedefs, tdscopename)) {
- Setattr(classes_typedefs, tdscopename, $$);
- }
- Setattr($$,"decl",decltype);
- Delete(class_scope);
- Delete(cname);
- Delete(tdscopename);
- }
- }
+ Setattr(p, "storage", $1);
+ Setattr(p, "type" ,ty);
+ if (!cparse_cplusplus && currentOuterClass && (!Getattr(currentOuterClass, "name"))) {
+ SetFlag(p, "hasconsttype");
+ SetFlag(p, "feature:immutable");
}
- appendChild($$,dump_nested(Char(name)));
+ p = nextSibling(p);
}
+ if ($9 && Cmp($1,"typedef") == 0)
+ add_typedef_name($$, $9, $3, cscope, scpname);
Delete(scpname);
if (cplus_mode != CPLUS_PUBLIC) {
/* we 'open' the class at the end, to allow %template
to add new members */
Node *pa = new_node("access");
- Setattr(pa,"kind","public");
+ Setattr(pa, "kind", "public");
cplus_mode = CPLUS_PUBLIC;
- appendChild($$,pa);
+ appendChild($$, pa);
Delete(pa);
}
-
- Setattr($$,"symtab",Swig_symbol_popscope());
-
- Classprefix = 0;
- if (nscope_inner) {
+ if (currentOuterClass)
+ restore_access_mode($$);
+ Setattr($$, "symtab", Swig_symbol_popscope());
+ Classprefix = Getattr($<node>$, "Classprefix");
+ Delattr($<node>$, "Classprefix");
+ if (cplus_mode == CPLUS_PRIVATE) {
+ $$ = 0; /* skip private nested classes */
+ } else if (nscope_inner) {
/* this is tricky */
/* we add the declaration in the original namespace */
- appendChild(nscope_inner,$$);
- Swig_symbol_setscope(Getattr(nscope_inner,"symtab"));
+ appendChild(nscope_inner, $$);
+ Swig_symbol_setscope(Getattr(nscope_inner, "symtab"));
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ yyrename = Copy(Getattr($<node>$, "class_rename"));
add_symbols($$);
- if (nscope) $$ = nscope;
+ Delattr($$, "class_rename");
/* but the variable definition in the current scope */
Swig_symbol_setscope(cscope);
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
add_symbols($9);
+ if (nscope) {
+ $$ = nscope; /* here we return recreated namespace tower instead of the class itself */
+ if ($9)
+ appendSibling($$, $9);
+ }
+ else if (!SwigType_istemplate(ty) && template_parameters == 0) /* for tempalte we need the class itself */
+ $$ = $9;
} else {
Delete(yyrename);
- yyrename = Copy(class_rename);
+ yyrename = 0;
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
-
- add_symbols($$);
- add_symbols($9);
+ if (!cparse_cplusplus && currentOuterClass) { /* nested C structs go into global scope*/
+ Node *outer = currentOuterClass;
+ while (Getattr(outer, "nested:outer"))
+ outer = Getattr(outer, "nested:outer");
+ appendSibling(outer, $$);
+ add_symbols($9);
+ set_scope_to_global();
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ yyrename = Copy(Getattr($<node>$, "class_rename"));
+ add_symbols($$);
+ if (!cparse_cplusplusout)
+ Delattr($$, "nested:outer");
+ Delattr($$, "class_rename");
+ $$ = 0;
+ } else {
+ yyrename = Copy(Getattr($<node>$, "class_rename"));
+ add_symbols($$);
+ add_symbols($9);
+ Delattr($$, "class_rename");
+ }
}
+ Delete(ty);
Swig_symbol_setscope(cscope);
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
- } else {
- $$ = new_node("class");
- Setattr($$,"kind",$2);
- Setattr($$,"name",NewString($3));
- SetFlag($$,"nestedtemplateclass");
- }
}
/* An unnamed struct, possibly with a typedef */
- | storage_class cpptype LBRACE {
+ | storage_class cpptype inherit LBRACE {
String *unnamed;
+ String *code;
unnamed = make_unnamed();
$<node>$ = new_node("class");
Setline($<node>$,cparse_start_line);
Setattr($<node>$,"kind",$2);
+ if ($3) {
+ Setattr($<node>$,"baselist", Getattr($3,"public"));
+ Setattr($<node>$,"protectedbaselist", Getattr($3,"protected"));
+ Setattr($<node>$,"privatebaselist", Getattr($3,"private"));
+ }
Setattr($<node>$,"storage",$1);
Setattr($<node>$,"unnamed",unnamed);
Setattr($<node>$,"allows_typedef","1");
- Delete(class_rename);
- class_rename = make_name($<node>$,0,0);
+ if (currentOuterClass) {
+ SetFlag($<node>$, "nested");
+ Setattr($<node>$, "nested:outer", currentOuterClass);
+ set_access_mode($<node>$);
+ }
+ Setattr($<node>$, "class_rename", make_name($<node>$,0,0));
if (strcmp($2,"class") == 0) {
cplus_mode = CPLUS_PRIVATE;
} else {
@@ -3969,108 +3626,111 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
}
Swig_symbol_newscope();
cparse_start_line = cparse_line;
- if (class_level >= max_class_levels) {
- if (!max_class_levels) {
- max_class_levels = 16;
- } else {
- max_class_levels *= 2;
- }
- class_decl = (Node**) realloc(class_decl, sizeof(Node*) * max_class_levels);
- if (!class_decl) {
- Swig_error(cparse_file, cparse_line, "realloc() failed\n");
- }
- }
- class_decl[class_level++] = $<node>$;
+ currentOuterClass = $<node>$;
inclass = 1;
Classprefix = NewStringEmpty();
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
- } cpp_members RBRACE declarator initializer c_decl_tail {
+ /* save the structure declaration to make a typedef for it later*/
+ code = get_raw_text_balanced('{', '}');
+ Setattr($<node>$, "code", code);
+ Delete(code);
+ } cpp_members RBRACE cpp_opt_declarators {
String *unnamed;
+ List *bases = 0;
+ String *name = 0;
Node *n;
- (void) $<node>4;
Classprefix = 0;
- $$ = class_decl[--class_level];
- inclass = 0;
+ $$ = currentOuterClass;
+ currentOuterClass = Getattr($$, "nested:outer");
+ if (!currentOuterClass)
+ inclass = 0;
+ else
+ restore_access_mode($$);
unnamed = Getattr($$,"unnamed");
-
- /* Check for pure-abstract class */
- Setattr($$,"abstracts", pure_abstracts($5));
-
- n = new_node("cdecl");
- Setattr(n,"name",$7.id);
- Setattr(n,"unnamed",unnamed);
- Setattr(n,"type",unnamed);
- Setattr(n,"decl",$7.type);
- Setattr(n,"parms",$7.parms);
- Setattr(n,"storage",$1);
- if ($9) {
- Node *p = $9;
- set_nextSibling(n,p);
- while (p) {
- String *type = Copy(unnamed);
- Setattr(p,"name",$7.id);
- Setattr(p,"unnamed",unnamed);
- Setattr(p,"type",type);
- Delete(type);
- Setattr(p,"storage",$1);
- p = nextSibling(p);
- }
- }
- set_nextSibling($$,n);
- Delete(n);
- {
+ /* Check for pure-abstract class */
+ Setattr($$,"abstracts", pure_abstracts($6));
+ n = $8;
+ if (n) {
+ appendSibling($$,n);
/* If a proper typedef name was given, we'll use it to set the scope name */
- String *name = 0;
- if ($1 && (strcmp($1,"typedef") == 0)) {
- if (!Len($7.type)) {
- String *scpname = 0;
- name = $7.id;
- Setattr($$,"tdname",name);
- Setattr($$,"name",name);
- Swig_symbol_setscopename(name);
+ name = try_to_find_a_name_for_unnamed_structure($1, n);
+ if (name) {
+ String *scpname = 0;
+ SwigType *ty;
+ Setattr($$,"tdname",name);
+ Setattr($$,"name",name);
+ Swig_symbol_setscopename(name);
+ if ($3)
+ bases = Swig_make_inherit_list(name,Getattr($3,"public"),Namespaceprefix);
+ Swig_inherit_base_symbols(bases);
/* If a proper name was given, we use that as the typedef, not unnamed */
- Clear(unnamed);
- Append(unnamed, name);
-
+ Clear(unnamed);
+ Append(unnamed, name);
+ if (cparse_cplusplus && !cparse_externc) {
+ ty = NewString(name);
+ } else {
+ ty = NewStringf("%s %s", $2,name);
+ }
+ while (n) {
+ Setattr(n,"storage",$1);
+ Setattr(n, "type", ty);
+ if (!cparse_cplusplus && currentOuterClass && (!Getattr(currentOuterClass, "name"))) {
+ SetFlag(n,"hasconsttype");
+ SetFlag(n,"feature:immutable");
+ }
n = nextSibling(n);
- set_nextSibling($$,n);
-
+ }
+ n = $8;
/* Check for previous extensions */
- if (extendhash) {
- String *clsname = Swig_symbol_qualifiedscopename(0);
- Node *am = Getattr(extendhash,clsname);
- if (am) {
+ if (extendhash) {
+ String *clsname = Swig_symbol_qualifiedscopename(0);
+ Node *am = Getattr(extendhash,clsname);
+ if (am) {
/* Merge the extension into the symbol table */
- merge_extensions($$,am);
- append_previous_extension($$,am);
- Delattr(extendhash,clsname);
- }
- Delete(clsname);
+ merge_extensions($$,am);
+ append_previous_extension($$,am);
+ Delattr(extendhash,clsname);
}
- if (!classes) classes = NewHash();
- scpname = Swig_symbol_qualifiedscopename(0);
- Setattr(classes,scpname,$$);
- Delete(scpname);
- } else {
- Swig_symbol_setscopename("<unnamed>");
+ Delete(clsname);
+ }
+ if (!classes) classes = NewHash();
+ scpname = Swig_symbol_qualifiedscopename(0);
+ Setattr(classes,scpname,$$);
+ Delete(scpname);
+ } else { /* no suitable name was found for a struct */
+ Setattr($$, "nested:unnamed", Getattr(n, "name")); /* save the name of the first declarator for later use in name generation*/
+ while (n) { /* attach unnamed struct to the declarators, so that they would receive proper type later*/
+ Setattr(n, "nested:unnamedtype", $$);
+ Setattr(n, "storage", $1);
+ n = nextSibling(n);
}
+ n = $8;
+ Swig_symbol_setscopename("<unnamed>");
}
- appendChild($$,$5);
- appendChild($$,dump_nested(Char(name)));
- }
- /* Pop the scope */
- Setattr($$,"symtab",Swig_symbol_popscope());
- if (class_rename) {
- Delete(yyrename);
- yyrename = NewString(class_rename);
+ appendChild($$,$6);
+ /* Pop the scope */
+ Setattr($$,"symtab",Swig_symbol_popscope());
+ if (name) {
+ Delete(yyrename);
+ yyrename = Copy(Getattr($<node>$, "class_rename"));
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ add_symbols($$);
+ add_symbols(n);
+ Delattr($$, "class_rename");
+ }else if (cparse_cplusplus)
+ $$ = 0; /* ignore unnamed structs for C++ */
+ Delete(unnamed);
+ } else { /* unnamed struct w/o declarator*/
+ Swig_symbol_popscope();
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ add_symbols($6);
+ Delete($$);
+ $$ = $6; /* pass member list to outer class/namespace (instead of self)*/
}
- Delete(Namespaceprefix);
- Namespaceprefix = Swig_symbol_qualifiedscopename(0);
- add_symbols($$);
- add_symbols(n);
- Delete(unnamed);
}
;
@@ -4106,41 +3766,10 @@ cpp_forward_class_decl : storage_class cpptype idcolon SEMI {
------------------------------------------------------------ */
cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
+ if (currentOuterClass)
+ Setattr(currentOuterClass, "template_parameters", template_parameters);
template_parameters = $3;
- if (inclass)
- nested_template++;
-
} cpp_temp_possible {
-
- /* Don't ignore templated functions declared within a class, unless the templated function is within a nested class */
- if (nested_template <= 1) {
- int is_nested_template_class = $6 && GetFlag($6, "nestedtemplateclass");
- if (is_nested_template_class) {
- $$ = 0;
- /* Nested template classes would probably better be ignored like ordinary nested classes using cpp_nested, but that introduces shift/reduce conflicts */
- if (cplus_mode == CPLUS_PUBLIC) {
- /* Treat the nested class/struct/union as a forward declaration until a proper nested class solution is implemented */
- String *kind = Getattr($6, "kind");
- String *name = Getattr($6, "name");
- $$ = new_node("template");
- Setattr($$,"kind",kind);
- Setattr($$,"name",name);
- Setattr($$,"sym:weak", "1");
- Setattr($$,"templatetype","classforward");
- Setattr($$,"templateparms", $3);
- add_symbols($$);
-
- if (GetFlag($$, "feature:nestedworkaround")) {
- Swig_symbol_remove($$);
- $$ = 0;
- } else {
- SWIG_WARN_NODE_BEGIN($$);
- Swig_warning(WARN_PARSE_NAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested template %s not currently supported (%s ignored).\n", kind, name);
- SWIG_WARN_NODE_END($$);
- }
- }
- Delete($6);
- } else {
String *tname = 0;
int error = 0;
@@ -4386,13 +4015,10 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
if (error) $$ = 0;
- }
- } else {
- $$ = 0;
- }
- template_parameters = 0;
- if (inclass)
- nested_template--;
+ if (currentOuterClass)
+ template_parameters = Getattr(currentOuterClass, "template_parameters");
+ else
+ template_parameters = 0;
}
/* Explicit template instantiation */
@@ -4621,6 +4247,8 @@ cpp_members : cpp_member cpp_members {
p = nextSibling(p);
}
set_nextSibling(pp,$2);
+ if ($2)
+ set_previousSibling($2, pp);
} else {
$$ = $2;
}
@@ -4656,7 +4284,7 @@ cpp_members : cpp_member cpp_members {
cpp_member : c_declaration { $$ = $1; }
| cpp_constructor_decl {
$$ = $1;
- if (extendmode) {
+ if (extendmode && current_class) {
String *symname;
symname= make_name($$,Getattr($$,"name"), Getattr($$,"decl"));
if (Strcmp(symname,Getattr($$,"name")) == 0) {
@@ -4677,7 +4305,7 @@ cpp_member : c_declaration { $$ = $1; }
| cpp_swig_directive { $$ = $1; }
| cpp_conversion_operator { $$ = $1; }
| cpp_forward_class_decl { $$ = $1; }
- | cpp_nested { $$ = $1; }
+ | cpp_class_decl { $$ = $1; }
| storage_class idcolon SEMI { $$ = 0; }
| cpp_using_decl { $$ = $1; }
| cpp_template_decl { $$ = $1; }
@@ -4697,7 +4325,7 @@ cpp_member : c_declaration { $$ = $1; }
*/
cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
- if (Classprefix) {
+ if (inclass || extendmode) {
SwigType *decl = NewStringEmpty();
$$ = new_node("constructor");
Setattr($$,"storage",$1);
@@ -4905,82 +4533,6 @@ cpp_protection_decl : PUBLIC COLON {
cplus_mode = CPLUS_PROTECTED;
}
;
-
-
-/* ------------------------------------------------------------
- Named nested structs:
- struct sname { };
- struct sname { } id;
- struct sname : bases { };
- struct sname : bases { } id;
- typedef sname struct { } td;
- typedef sname struct : bases { } td;
-
- Adding inheritance, ie replacing 'ID' with 'idcolon inherit'
- added one shift/reduce
- ------------------------------------------------------------ */
-
-cpp_nested : storage_class cpptype idcolon inherit LBRACE {
- cparse_start_line = cparse_line;
- skip_balanced('{','}');
- $<str>$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */
- } cpp_opt_declarators {
- $$ = 0;
- if (cplus_mode == CPLUS_PUBLIC) {
- if (cparse_cplusplus) {
- String *name = Copy($3);
- $$ = nested_forward_declaration($1, $2, $3, name, $7);
- } else if ($7) {
- nested_new_struct($2, $<str>6, $7);
- }
- }
- Delete($<str>6);
- }
-
-/* ------------------------------------------------------------
- Unnamed/anonymous nested structs:
- struct { };
- struct { } id;
- struct : bases { };
- struct : bases { } id;
- typedef struct { } td;
- typedef struct : bases { } td;
- ------------------------------------------------------------ */
-
- | storage_class cpptype inherit LBRACE {
- cparse_start_line = cparse_line;
- skip_balanced('{','}');
- $<str>$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */
- } cpp_opt_declarators {
- $$ = 0;
- if (cplus_mode == CPLUS_PUBLIC) {
- if (cparse_cplusplus) {
- String *name = $6 ? Copy(Getattr($6, "name")) : 0;
- $$ = nested_forward_declaration($1, $2, 0, name, $6);
- } else {
- if ($6) {
- nested_new_struct($2, $<str>5, $6);
- } else {
- Swig_warning(WARN_PARSE_UNNAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2);
- }
- }
- }
- Delete($<str>5);
- }
-
-
-/* This unfortunately introduces 4 shift/reduce conflicts, so instead the somewhat hacky nested_template is used for ignore nested template classes. */
-/*
- | TEMPLATE LESSTHAN template_parms GREATERTHAN cpptype idcolon LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}');
- } SEMI {
- $$ = 0;
- if (cplus_mode == CPLUS_PUBLIC) {
- Swig_warning(WARN_PARSE_NAMED_NESTED_CLASS, cparse_file, cparse_line,"Nested %s not currently supported (%s ignored)\n", $5, $6);
- }
- }
-*/
- ;
-
/* These directives can be included inside a class definition */
cpp_swig_directive: pragma_directive { $$ = $1; }
diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h
index 65ff70dd9..ea1cf7fe4 100644
--- a/Source/Include/swigwarn.h
+++ b/Source/Include/swigwarn.h
@@ -52,6 +52,7 @@
#define WARN_DEPRECATED_NODEFAULT 123
#define WARN_DEPRECATED_TYPEMAP_LANG 124
#define WARN_DEPRECATED_INPUT_FILE 125
+#define WARN_DEPRECATED_NESTED_WORKAROUND 126
/* -- Preprocessor -- */
@@ -75,7 +76,6 @@
#define WARN_PARSE_PRIVATE_INHERIT 309
#define WARN_PARSE_TEMPLATE_REPEAT 310
#define WARN_PARSE_TEMPLATE_PARTIAL 311
-#define WARN_PARSE_UNNAMED_NESTED_CLASS 312
#define WARN_PARSE_UNDEFINED_EXTERN 313
#define WARN_PARSE_KEYWORD 314
#define WARN_PARSE_USING_UNDEF 315
@@ -88,7 +88,6 @@
#define WARN_PARSE_REDUNDANT 322
#define WARN_PARSE_REC_INHERITANCE 323
#define WARN_PARSE_NESTED_TEMPLATE 324
-#define WARN_PARSE_NAMED_NESTED_CLASS 325
#define WARN_PARSE_EXTEND_NAME 326
#define WARN_CPP11_LAMBDA 340
diff --git a/Source/Makefile.am b/Source/Makefile.am
index 0c28a95b6..49d571236 100644
--- a/Source/Makefile.am
+++ b/Source/Makefile.am
@@ -54,6 +54,7 @@ eswig_SOURCES = CParse/cscanner.c \
Modules/modula3.cxx \
Modules/module.cxx \
Modules/mzscheme.cxx \
+ Modules/nested.cxx \
Modules/ocaml.cxx \
Modules/octave.cxx \
Modules/overload.cxx \
diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx
index b7daae59c..7f1d13678 100644
--- a/Source/Modules/allocate.cxx
+++ b/Source/Modules/allocate.cxx
@@ -559,6 +559,8 @@ Allocate():
virtual int classDeclaration(Node *n) {
Symtab *symtab = Swig_symbol_current();
Swig_symbol_setscope(Getattr(n, "symtab"));
+ Node *oldInclass = inclass;
+ AccessMode oldAcessMode = cplus_mode;
if (!CPlusPlus) {
/* Always have default constructors/destructors in C */
@@ -580,7 +582,6 @@ Allocate():
}
}
}
-
inclass = n;
String *kind = Getattr(n, "kind");
if (Strcmp(kind, "class") == 0) {
@@ -728,7 +729,8 @@ Allocate():
/* Only care about default behavior. Remove temporary values */
Setattr(n, "allocate:visit", "1");
- inclass = 0;
+ inclass = oldInclass;
+ cplus_mode = oldAcessMode;
Swig_symbol_setscope(symtab);
return SWIG_OK;
}
diff --git a/Source/Modules/contract.cxx b/Source/Modules/contract.cxx
index ffd799cfd..7e0eaf9e0 100644
--- a/Source/Modules/contract.cxx
+++ b/Source/Modules/contract.cxx
@@ -342,11 +342,13 @@ int Contracts::namespaceDeclaration(Node *n) {
int Contracts::classDeclaration(Node *n) {
int ret = SWIG_OK;
+ int oldInClass = InClass;
+ Node *oldClass = CurrentClass;
InClass = 1;
CurrentClass = n;
emit_children(n);
- InClass = 0;
- CurrentClass = 0;
+ InClass = oldInClass;
+ CurrentClass = oldClass;
return ret;
}
diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx
index 6b9219750..9197b4b17 100644
--- a/Source/Modules/csharp.cxx
+++ b/Source/Modules/csharp.cxx
@@ -53,7 +53,6 @@ class CSHARP:public Language {
String *proxy_class_code;
String *module_class_code;
String *proxy_class_name; // proxy class name
- String *full_proxy_class_name;// fully qualified proxy class name when using nspace feature, otherwise same as proxy_class_name
String *full_imclass_name; // fully qualified intermediary class name when using nspace feature, otherwise same as imclass_name
String *variable_name; //Name of a variable being wrapped
String *proxy_class_constants_code;
@@ -87,6 +86,7 @@ class CSHARP:public Language {
int n_directors;
int first_class_dmethod;
int curr_class_dmethod;
+ int nesting_depth;
enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
@@ -125,7 +125,6 @@ public:
proxy_class_code(NULL),
module_class_code(NULL),
proxy_class_name(NULL),
- full_proxy_class_name(NULL),
full_imclass_name(NULL),
variable_name(NULL),
proxy_class_constants_code(NULL),
@@ -156,7 +155,8 @@ public:
n_dmethods(0),
n_directors(0),
first_class_dmethod(0),
- curr_class_dmethod(0) {
+ curr_class_dmethod(0),
+ nesting_depth(0){
/* for now, multiple inheritance in directors is disabled, this
should be easy to implement though */
director_multiple_inheritance = 0;
@@ -179,7 +179,13 @@ public:
proxyname = Getattr(n, "proxyname");
if (!proxyname) {
String *nspace = Getattr(n, "sym:nspace");
- String *symname = Getattr(n, "sym:name");
+ String *symname = Copy(Getattr(n, "sym:name"));
+ if (symname && !GetFlag(n, "feature:flatnested")) {
+ for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) {
+ Push(symname, ".");
+ Push(symname, Getattr(outer_class, "sym:name"));
+ }
+ }
if (nspace) {
if (namespce)
proxyname = NewStringf("%s.%s.%s", namespce, nspace, symname);
@@ -190,12 +196,33 @@ public:
}
Setattr(n, "proxyname", proxyname);
Delete(proxyname);
+ Delete(symname);
}
}
}
return proxyname;
}
+ /* -----------------------------------------------------------------------------
+ * directorClassName()
+ * ----------------------------------------------------------------------------- */
+
+ String *directorClassName(Node *n) {
+ String *dirclassname;
+ const char *attrib = "director:classname";
+
+ if (!(dirclassname = Getattr(n, attrib))) {
+ String *classname = getClassPrefix();
+
+ dirclassname = NewStringf("SwigDirector_%s", classname);
+ Setattr(n, attrib, dirclassname);
+ }
+ else
+ dirclassname = Copy(dirclassname);
+
+ return dirclassname;
+ }
+
/* ------------------------------------------------------------
* main()
* ------------------------------------------------------------ */
@@ -1025,7 +1052,7 @@ public:
*/
if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
// Capitalize the first letter in the variable in the getter/setter function name
- bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, proxy_class_name, variable_name))) != 0;
+ bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) != 0;
String *getter_setter_name = NewString("");
if (!getter_flag)
@@ -1589,6 +1616,7 @@ public:
String *c_baseclassname = NULL;
SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
bool feature_director = Swig_directorclass(n) ? true : false;
+ bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
// Inheritance from pure C# classes
Node *attributes = NewHash();
@@ -1648,7 +1676,8 @@ public:
// Pure C# interfaces
const String *pure_interfaces = typemapLookup(n, derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE);
// Start writing the proxy class
- Printv(proxy_class_def, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
+ if (!has_outerclass)
+ Printv(proxy_class_def, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
"\n", NIL);
// Class attributes
@@ -1719,7 +1748,7 @@ public:
Printf(proxy_class_code, " if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s))\n", method, methid);
Printf(proxy_class_code, " swigDelegate%s = new SwigDelegate%s_%s(SwigDirector%s);\n", methid, proxy_class_name, methid, overname);
}
- String *director_connect_method_name = Swig_name_member(getNSpace(), proxy_class_name, "director_connect");
+ String *director_connect_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect");
Printf(proxy_class_code, " %s.%s(swigCPtr", imclass_name, director_connect_method_name);
for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
UpcallData *udata = Getitem(dmethods_seq, i);
@@ -1795,7 +1824,7 @@ public:
// Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
if (derived) {
String *smartptr = Getattr(n, "feature:smartptr");
- String *upcast_method = Swig_name_member(getNSpace(), proxy_class_name, smartptr != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
+ String *upcast_method = Swig_name_member(getNSpace(), getClassPrefix(), smartptr != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
String *wname = Swig_name_wrapper(upcast_method);
Printv(imclass_cppcasts_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
@@ -1846,11 +1875,35 @@ public:
String *nspace = getNSpace();
File *f_proxy = NULL;
+ // save class local variables
+ String *old_proxy_class_name = proxy_class_name;
+ String *old_full_imclass_name = full_imclass_name;
+ String *old_destructor_call = destructor_call;
+ String *old_proxy_class_constants_code = proxy_class_constants_code;
+ String *old_proxy_class_def = proxy_class_def;
+ String *old_proxy_class_code = proxy_class_code;
+
if (proxy_flag) {
proxy_class_name = NewString(Getattr(n, "sym:name"));
+ if (Node *outer = Getattr(n, "nested:outer")) {
+ String *outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
+ for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
+ Push(outerClassesPrefix, "::");
+ Push(outerClassesPrefix, Getattr(outer, "sym:name"));
+ }
+ String *fnspace = nspace ? NewStringf("%s::%s", nspace, outerClassesPrefix) : outerClassesPrefix;
+ if (!addSymbol(proxy_class_name, n, fnspace))
+ return SWIG_ERROR;
+ if (nspace)
+ Delete(fnspace);
+ Delete(outerClassesPrefix);
+ }
+ else {
+ if (!addSymbol(proxy_class_name, n, nspace))
+ return SWIG_ERROR;
+ }
if (!nspace) {
- full_proxy_class_name = NewStringf("%s", proxy_class_name);
full_imclass_name = NewStringf("%s", imclass_name);
if (Cmp(proxy_class_name, imclass_name) == 0) {
Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
@@ -1863,36 +1916,34 @@ public:
}
} else {
if (namespce) {
- full_proxy_class_name = NewStringf("%s.%s.%s", namespce, nspace, proxy_class_name);
full_imclass_name = NewStringf("%s.%s", namespce, imclass_name);
} else {
- full_proxy_class_name = NewStringf("%s.%s", nspace, proxy_class_name);
full_imclass_name = NewStringf("%s", imclass_name);
}
}
- if (!addSymbol(proxy_class_name, n, nspace))
- return SWIG_ERROR;
-
- String *output_directory = outputDirectory(nspace);
- String *filen = NewStringf("%s%s.cs", output_directory, proxy_class_name);
- f_proxy = NewFile(filen, "w", SWIG_output_files());
- if (!f_proxy) {
- FileErrorDisplay(filen);
- SWIG_exit(EXIT_FAILURE);
- }
- Append(filenames_list, Copy(filen));
- Delete(filen);
- filen = NULL;
-
- // Start writing out the proxy class file
- emitBanner(f_proxy);
-
- addOpenNamespace(nspace, f_proxy);
+ // inner class doesn't need this prologue
+ if (!Getattr(n, "nested:outer")) {
+ String *output_directory = outputDirectory(nspace);
+ String *filen = NewStringf("%s%s.cs", output_directory, proxy_class_name);
+ f_proxy = NewFile(filen, "w", SWIG_output_files());
+ if (!f_proxy) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
- Clear(proxy_class_def);
- Clear(proxy_class_code);
+ // Start writing out the proxy class file
+ emitBanner(f_proxy);
+ addOpenNamespace(nspace, f_proxy);
+ }
+ else
+ ++nesting_depth;
+ proxy_class_def = NewString("");
+ proxy_class_code = NewString("");
destructor_call = NewString("");
proxy_class_constants_code = NewString("");
}
@@ -1903,7 +1954,7 @@ public:
emitProxyClassDefAndCPPCasts(n);
- String *csclazzname = Swig_name_member(getNSpace(), proxy_class_name, ""); // mangled full proxy class name
+ String *csclazzname = Swig_name_member(getNSpace(), getClassPrefix(), ""); // mangled full proxy class name
Replaceall(proxy_class_def, "$csclassname", proxy_class_name);
Replaceall(proxy_class_code, "$csclassname", proxy_class_name);
@@ -1924,17 +1975,36 @@ public:
Replaceall(proxy_class_def, "$dllimport", dllimport);
Replaceall(proxy_class_code, "$dllimport", dllimport);
Replaceall(proxy_class_constants_code, "$dllimport", dllimport);
-
- Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
+ bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
+ if (!has_outerclass)
+ Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
+ else {
+ Swig_offset_string(proxy_class_def, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_def);
+ Swig_offset_string(proxy_class_code, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_code);
+ }
// Write out all the constants
- if (Len(proxy_class_constants_code) != 0)
- Printv(f_proxy, proxy_class_constants_code, NIL);
-
- Printf(f_proxy, "}\n");
- addCloseNamespace(nspace, f_proxy);
- Delete(f_proxy);
- f_proxy = NULL;
+ if (Len(proxy_class_constants_code) != 0) {
+ if (!has_outerclass)
+ Printv(f_proxy, proxy_class_constants_code, NIL);
+ else {
+ Swig_offset_string(proxy_class_constants_code, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_constants_code);
+ }
+ }
+ if (!has_outerclass) {
+ Printf(f_proxy, "}\n");
+ addCloseNamespace(nspace, f_proxy);
+ Delete(f_proxy);
+ f_proxy = NULL;
+ } else {
+ for (int i = 0; i < nesting_depth; ++i)
+ Append(old_proxy_class_code, " ");
+ Append(old_proxy_class_code, "}\n\n");
+ --nesting_depth;
+ }
/* Output the downcast method, if necessary. Note: There's no other really
good place to put this code, since Abstract Base Classes (ABCs) can and should have
@@ -1971,17 +2041,18 @@ public:
Delete(csclazzname);
Delete(proxy_class_name);
- proxy_class_name = NULL;
- Delete(full_proxy_class_name);
- full_proxy_class_name = NULL;
+ proxy_class_name = old_proxy_class_name;
Delete(full_imclass_name);
- full_imclass_name = NULL;
+ full_imclass_name = old_full_imclass_name;
Delete(destructor_call);
- destructor_call = NULL;
+ destructor_call = old_destructor_call;
Delete(proxy_class_constants_code);
- proxy_class_constants_code = NULL;
+ proxy_class_constants_code = old_proxy_class_constants_code;
+ Delete(proxy_class_def);
+ proxy_class_def = old_proxy_class_def;
+ Delete(proxy_class_code);
+ proxy_class_code = old_proxy_class_code;
}
-
return SWIG_OK;
}
@@ -1994,7 +2065,7 @@ public:
if (proxy_flag) {
String *overloaded_name = getOverloadedName(n);
- String *intermediary_function_name = Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
+ String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
Setattr(n, "imfuncname", intermediary_function_name);
proxyClassFunctionHandler(n);
@@ -2014,7 +2085,7 @@ public:
if (proxy_flag) {
String *overloaded_name = getOverloadedName(n);
- String *intermediary_function_name = Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
+ String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
Setattr(n, "imfuncname", intermediary_function_name);
proxyClassFunctionHandler(n);
@@ -2094,7 +2165,7 @@ public:
if (wrapping_member_flag && !enum_constant_flag) {
// Properties
- setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, proxy_class_name, variable_name))) == 0);
+ setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) == 0);
if (setter_flag)
Swig_typemap_attach_parms("csvarin", l, NULL);
}
@@ -2264,7 +2335,7 @@ public:
Node *explicit_n = Getattr(n, "explicitcallnode");
if (explicit_n) {
String *ex_overloaded_name = getOverloadedName(explicit_n);
- String *ex_intermediary_function_name = Swig_name_member(getNSpace(), proxy_class_name, ex_overloaded_name);
+ String *ex_intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), ex_overloaded_name);
String *ex_imcall = Copy(imcall);
Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
@@ -3376,14 +3447,21 @@ public:
// Output the director connect method:
String *norm_name = SwigType_namestr(Getattr(n, "name"));
- String *swig_director_connect = Swig_name_member(getNSpace(), proxy_class_name, "director_connect");
+ String *dirclassname = directorClassName(n);
+ String *swig_director_connect = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect");
String *wname = Swig_name_wrapper(swig_director_connect);
String *sym_name = Getattr(n, "sym:name");
String *qualified_classname = Copy(sym_name);
String *nspace = getNSpace();
String *dirClassName = directorClassName(n);
String *smartptr = Getattr(n, "feature:smartptr");
+ if (!GetFlag(n, "feature:flatnested")) {
+ for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) {
+ Push(qualified_classname, ".");
+ Push(qualified_classname, Getattr(outer_class, "sym:name"));
+ }
+ }
if (nspace)
Insert(qualified_classname, 0, NewStringf("%s.", nspace));
@@ -3415,7 +3493,7 @@ public:
Printf(code_wrap->def, ", ");
if (i != first_class_dmethod)
Printf(code_wrap->code, ", ");
- Printf(code_wrap->def, "%s::SWIG_Callback%s_t callback%s", dirClassName, methid, methid);
+ Printf(code_wrap->def, "%s::SWIG_Callback%s_t callback%s", dirclassname, methid, methid);
Printf(code_wrap->code, "callback%s", methid);
Printf(imclass_class_code, ", %s.SwigDelegate%s_%s delegate%s", qualified_classname, sym_name, methid, methid);
}
@@ -3432,7 +3510,7 @@ public:
Delete(wname);
Delete(swig_director_connect);
Delete(qualified_classname);
- Delete(dirClassName);
+ Delete(dirclassname);
}
/* ---------------------------------------------------------------
@@ -3485,7 +3563,7 @@ public:
// we're consistent with the sym:overload name in functionWrapper. (?? when
// does the overloaded method name get set?)
- imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(getNSpace(), classname, overloaded_name));
+ imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name));
qualified_return = SwigType_rcaststr(returntype, "c_result");
@@ -3931,6 +4009,7 @@ public:
Delete(proxy_method_types);
Delete(callback_def);
Delete(callback_code);
+ Delete(dirclassname);
DelWrapper(w);
return status;
@@ -3970,13 +4049,11 @@ public:
String *basetype = Getattr(parent, "classtype");
String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 0);
String *call = Swig_csuperclass_call(0, basetype, superparms);
- String *classtype = SwigType_namestr(Getattr(n, "name"));
Printf(f_directors, "%s::%s : %s, %s {\n", dirclassname, target, call, Getattr(parent, "director:ctor"));
Printf(f_directors, " swig_init_callbacks();\n");
Printf(f_directors, "}\n\n");
- Delete(classtype);
Delete(target);
Delete(call);
}
@@ -4047,6 +4124,29 @@ public:
return Language::classDirectorInit(n);
}
+ int classDeclaration(Node *n) {
+ String *old_director_callback_typedefs = director_callback_typedefs;
+ String *old_director_callbacks = director_callbacks;
+ String *old_director_delegate_callback = director_delegate_callback;
+ String *old_director_delegate_definitions = director_delegate_definitions;
+ String *old_director_delegate_instances = director_delegate_instances;
+ String *old_director_method_types = director_method_types;
+ String *old_director_connect_parms = director_connect_parms;
+
+ int ret = Language::classDeclaration(n);
+
+ // these variables are deleted in emitProxyClassDefAndCPPCasts, hence no Delete here
+ director_callback_typedefs = old_director_callback_typedefs;
+ director_callbacks = old_director_callbacks;
+ director_delegate_callback = old_director_delegate_callback;
+ director_delegate_definitions = old_director_delegate_definitions;
+ director_delegate_instances = old_director_delegate_instances;
+ director_method_types = old_director_method_types;
+ director_connect_parms = old_director_connect_parms;
+
+ return ret;
+ }
+
/* ----------------------------------------------------------------------
* classDirectorDestructor()
* ---------------------------------------------------------------------- */
@@ -4079,7 +4179,7 @@ public:
int classDirectorEnd(Node *n) {
int i;
- String *director_classname = directorClassName(n);
+ String *dirclassname = directorClassName(n);
Wrapper *w = NewWrapper();
@@ -4089,7 +4189,7 @@ public:
Printf(f_directors_h, " void swig_connect_director(");
- Printf(w->def, "void %s::swig_connect_director(", director_classname);
+ Printf(w->def, "void %s::swig_connect_director(", dirclassname);
for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
UpcallData *udata = Getitem(dmethods_seq, i);
@@ -4116,7 +4216,7 @@ public:
Printf(f_directors_h, "};\n\n");
Printf(w->code, "}\n\n");
- Printf(w->code, "void %s::swig_init_callbacks() {\n", director_classname);
+ Printf(w->code, "void %s::swig_init_callbacks() {\n", dirclassname);
for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
UpcallData *udata = Getitem(dmethods_seq, i);
String *overname = Getattr(udata, "overname");
@@ -4127,6 +4227,7 @@ public:
Wrapper_print(w, f_directors);
DelWrapper(w);
+ Delete(dirclassname);
return Language::classDirectorEnd(n);
}
@@ -4159,8 +4260,8 @@ public:
String *base = Getattr(n, "classtype");
String *class_ctor = NewString("Swig::Director()");
- String *directorname = directorClassName(n);
- String *declaration = Swig_class_declaration(n, directorname);
+ String *dirclassname = directorClassName(n);
+ String *declaration = Swig_class_declaration(n, dirclassname);
Printf(declaration, " : public %s, public Swig::Director", base);
@@ -4168,9 +4269,12 @@ public:
Setattr(n, "director:decl", declaration);
Setattr(n, "director:ctor", class_ctor);
- Delete(directorname);
+ Delete(dirclassname);
}
+ bool nestedClassesSupported() const {
+ return true;
+ }
}; /* class CSHARP */
/* -----------------------------------------------------------------------------
diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx
index 6576ad544..fdc678dbf 100644
--- a/Source/Modules/java.cxx
+++ b/Source/Modules/java.cxx
@@ -86,6 +86,7 @@ class JAVA:public Language {
int n_directors;
int first_class_dmethod;
int curr_class_dmethod;
+ int nesting_depth;
enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
@@ -154,7 +155,8 @@ public:
n_dmethods(0),
n_directors(0),
first_class_dmethod(0),
- curr_class_dmethod(0) {
+ curr_class_dmethod(0),
+ nesting_depth(0){
/* for now, multiple inheritance in directors is disabled, this
should be easy to implement though */
director_multiple_inheritance = 0;
@@ -204,7 +206,13 @@ public:
proxyname = Getattr(n, "proxyname");
if (!proxyname || jnidescriptor) {
String *nspace = Getattr(n, "sym:nspace");
- String *symname = Getattr(n, "sym:name");
+ String *symname = Copy(Getattr(n, "sym:name"));
+ if (symname && !GetFlag(n, "feature:flatnested")) {
+ for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) {
+ Push(symname, ".");
+ Push(symname, Getattr(outer_class, "sym:name"));
+ }
+ }
if (nspace) {
if (package && !jnidescriptor)
proxyname = NewStringf("%s.%s.%s", package, nspace, symname);
@@ -217,6 +225,7 @@ public:
Setattr(n, "proxyname", proxyname); // Cache it
Delete(proxyname);
}
+ Delete(symname);
}
}
}
@@ -1134,7 +1143,7 @@ public:
*/
if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
// Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
- bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, proxy_class_name, variable_name))) != 0;
+ bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) != 0;
String *getter_setter_name = NewString("");
if (!getter_flag)
@@ -1713,6 +1722,7 @@ public:
String *c_baseclassname = NULL;
SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
bool feature_director = Swig_directorclass(n) ? true : false;
+ bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
// Inheritance from pure Java classes
Node *attributes = NewHash();
@@ -1773,8 +1783,11 @@ public:
const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
// Start writing the proxy class
- Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements
- "\n", typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
+ if (!has_outerclass) // Import statements
+ Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE),"\n", NIL);
+ else
+ Printv(proxy_class_def, "static ", NIL); // C++ nested classes correspond to static java classes
+ Printv(proxy_class_def, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
" $javaclassname", // Class name and bases
(*Char(wanted_base)) ? " extends " : "", wanted_base, *Char(pure_interfaces) ? // Pure Java interfaces
" implements " : "", pure_interfaces, " {", derived ? typemapLookup(n, "javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) : // main body of class
@@ -1825,7 +1838,7 @@ public:
/* Also insert the swigTakeOwnership and swigReleaseOwnership methods */
if (feature_director) {
String *destruct_jnicall, *release_jnicall, *take_jnicall;
- String *changeown_method_name = Swig_name_member(getNSpace(), proxy_class_name, "change_ownership");
+ String *changeown_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "change_ownership");
destruct_jnicall = NewStringf("%s()", destruct_methodname);
release_jnicall = NewStringf("%s.%s(this, swigCPtr, false)", full_imclass_name, changeown_method_name);
@@ -1851,7 +1864,7 @@ public:
// Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
if (derived) {
String *smartptr = Getattr(n, "feature:smartptr");
- String *upcast_method = Swig_name_member(getNSpace(), proxy_class_name, smartptr != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
+ String *upcast_method = Swig_name_member(getNSpace(), getClassPrefix(), smartptr != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
String *jniname = makeValidJniName(upcast_method);
String *wname = Swig_name_wrapper(jniname);
Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method);
@@ -1908,13 +1921,29 @@ public:
virtual int classHandler(Node *n) {
File *f_proxy = NULL;
+ String *old_proxy_class_name = proxy_class_name;
+ String *old_full_proxy_class_name = full_proxy_class_name;
+ String *old_full_imclass_name = full_imclass_name;
+ String *old_destructor_call = destructor_call;
+ String *old_destructor_throws_clause = destructor_throws_clause;
+ String *old_proxy_class_constants_code = proxy_class_constants_code;
+ String *old_proxy_class_def = proxy_class_def;
+ String *old_proxy_class_code = proxy_class_code;
if (proxy_flag) {
proxy_class_name = NewString(Getattr(n, "sym:name"));
String *nspace = getNSpace();
constructIntermediateClassName(n);
+ String *outerClassesPrefix = 0;
+ if (Node *outer = Getattr(n, "nested:outer")) {
+ outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
+ for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
+ Push(outerClassesPrefix, ".");
+ Push(outerClassesPrefix, Getattr(outer, "sym:name"));
+ }
+ }
if (!nspace) {
- full_proxy_class_name = NewStringf("%s", proxy_class_name);
+ full_proxy_class_name = outerClassesPrefix ? NewStringf("%s.%s", outerClassesPrefix, proxy_class_name) : NewStringf("%s", proxy_class_name);
if (Cmp(proxy_class_name, imclass_name) == 0) {
Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
@@ -1926,54 +1955,73 @@ public:
SWIG_exit(EXIT_FAILURE);
}
} else {
- if (package)
- full_proxy_class_name = NewStringf("%s.%s.%s", package, nspace, proxy_class_name);
- else
- full_proxy_class_name = NewStringf("%s.%s", nspace, proxy_class_name);
+ if (outerClassesPrefix) {
+ if (package)
+ full_proxy_class_name = NewStringf("%s.%s.%s.%s", package, nspace, outerClassesPrefix, proxy_class_name);
+ else
+ full_proxy_class_name = NewStringf("%s.%s.%s", nspace, outerClassesPrefix, proxy_class_name);
+ } else {
+ if (package)
+ full_proxy_class_name = NewStringf("%s.%s.%s", package, nspace, proxy_class_name);
+ else
+ full_proxy_class_name = NewStringf("%s.%s", nspace, proxy_class_name);
+ }
}
- if (!addSymbol(proxy_class_name, n, nspace))
- return SWIG_ERROR;
-
- String *output_directory = outputDirectory(nspace);
- String *filen = NewStringf("%s%s.java", output_directory, proxy_class_name);
- f_proxy = NewFile(filen, "w", SWIG_output_files());
- if (!f_proxy) {
- FileErrorDisplay(filen);
- SWIG_exit(EXIT_FAILURE);
+ if (outerClassesPrefix) {
+ Replaceall(outerClassesPrefix, ".", "::");
+ String *fnspace = nspace ? NewStringf("%s::%s", nspace, outerClassesPrefix) : outerClassesPrefix;
+ if (!addSymbol(proxy_class_name, n, fnspace))
+ return SWIG_ERROR;
+ if (nspace)
+ Delete(fnspace);
+ Delete(outerClassesPrefix);
+ }
+ else {
+ if (!addSymbol(proxy_class_name, n, nspace))
+ return SWIG_ERROR;
}
- Append(filenames_list, Copy(filen));
- Delete(filen);
- filen = NULL;
- // Start writing out the proxy class file
- emitBanner(f_proxy);
+ if (!Getattr(n, "nested:outer")) {
+ String *output_directory = outputDirectory(nspace);
+ String *filen = NewStringf("%s%s.java", output_directory, proxy_class_name);
+ f_proxy = NewFile(filen, "w", SWIG_output_files());
+ if (!f_proxy) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ Delete(output_directory);
- if (package || nspace) {
- Printf(f_proxy, "package ");
- if (package)
- Printv(f_proxy, package, nspace ? "." : "", NIL);
- if (nspace)
- Printv(f_proxy, nspace, NIL);
- Printf(f_proxy, ";\n");
- }
+ // Start writing out the proxy class file
+ emitBanner(f_proxy);
- Clear(proxy_class_def);
- Clear(proxy_class_code);
+ if (package || nspace) {
+ Printf(f_proxy, "package ");
+ if (package)
+ Printv(f_proxy, package, nspace ? "." : "", NIL);
+ if (nspace)
+ Printv(f_proxy, nspace, NIL);
+ Printf(f_proxy, ";\n");
+ }
+ }
+ else
+ ++nesting_depth;
+ proxy_class_def = NewString("");
+ proxy_class_code = NewString("");
destructor_call = NewString("");
destructor_throws_clause = NewString("");
proxy_class_constants_code = NewString("");
- Delete(output_directory);
}
-
Language::classHandler(n);
if (proxy_flag) {
emitProxyClassDefAndCPPCasts(n);
- String *javaclazzname = Swig_name_member(getNSpace(), proxy_class_name, ""); // mangled full proxy class name
+ String *javaclazzname = Swig_name_member(getNSpace(), getClassPrefix(), ""); // mangled full proxy class name
Replaceall(proxy_class_def, "$javaclassname", proxy_class_name);
Replaceall(proxy_class_code, "$javaclassname", proxy_class_name);
@@ -1991,22 +2039,43 @@ public:
Replaceall(proxy_class_code, "$imclassname", full_imclass_name);
Replaceall(proxy_class_constants_code, "$imclassname", full_imclass_name);
- Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
+ bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
+ if (!has_outerclass)
+ Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
+ else {
+ Swig_offset_string(proxy_class_def, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_def);
+ Swig_offset_string(proxy_class_code, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_code);
+ }
// Write out all the constants
- if (Len(proxy_class_constants_code) != 0)
- Printv(f_proxy, proxy_class_constants_code, NIL);
+ if (Len(proxy_class_constants_code) != 0) {
+ if (!has_outerclass)
+ Printv(f_proxy, proxy_class_constants_code, NIL);
+ else {
+ Swig_offset_string(proxy_class_constants_code, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_constants_code);
+ }
+ }
- Printf(f_proxy, "}\n");
- Delete(f_proxy);
- f_proxy = NULL;
+ if (!has_outerclass) {
+ Printf(f_proxy, "}\n");
+ Delete(f_proxy);
+ f_proxy = NULL;
+ } else {
+ for (int i = 0; i < nesting_depth; ++i)
+ Append(old_proxy_class_code, " ");
+ Append(old_proxy_class_code, "}\n\n");
+ --nesting_depth;
+ }
/* Output the downcast method, if necessary. Note: There's no other really
good place to put this code, since Abstract Base Classes (ABCs) can and should have
downcasts, making the constructorHandler() a bad place (because ABCs don't get to
have constructors emitted.) */
if (GetFlag(n, "feature:javadowncast")) {
- String *downcast_method = Swig_name_member(getNSpace(), proxy_class_name, "SWIGDowncast");
+ String *downcast_method = Swig_name_member(getNSpace(), getClassPrefix(), "SWIGDowncast");
String *jniname = makeValidJniName(downcast_method);
String *wname = Swig_name_wrapper(jniname);
@@ -2038,17 +2107,21 @@ public:
Delete(javaclazzname);
Delete(proxy_class_name);
- proxy_class_name = NULL;
+ proxy_class_name = old_proxy_class_name;
Delete(full_proxy_class_name);
- full_proxy_class_name = NULL;
+ full_proxy_class_name = old_full_proxy_class_name;
Delete(full_imclass_name);
- full_imclass_name = NULL;
+ full_imclass_name = old_full_imclass_name;
Delete(destructor_call);
- destructor_call = NULL;
+ destructor_call = old_destructor_call;
Delete(destructor_throws_clause);
- destructor_throws_clause = NULL;
+ destructor_throws_clause = old_destructor_throws_clause;
Delete(proxy_class_constants_code);
- proxy_class_constants_code = NULL;
+ proxy_class_constants_code = old_proxy_class_constants_code;
+ Delete(proxy_class_def);
+ proxy_class_def = old_proxy_class_def;
+ Delete(proxy_class_code);
+ proxy_class_code = old_proxy_class_code;
}
return SWIG_OK;
@@ -2064,7 +2137,7 @@ public:
if (proxy_flag) {
String *overloaded_name = getOverloadedName(n);
- String *intermediary_function_name = Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
+ String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
Setattr(n, "imfuncname", intermediary_function_name);
proxyClassFunctionHandler(n);
@@ -2086,7 +2159,7 @@ public:
if (proxy_flag) {
String *overloaded_name = getOverloadedName(n);
- String *intermediary_function_name = Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
+ String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
Setattr(n, "imfuncname", intermediary_function_name);
proxyClassFunctionHandler(n);
@@ -2162,7 +2235,7 @@ public:
if (wrapping_member_flag && !enum_constant_flag) {
// For wrapping member variables (Javabean setter)
- setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, proxy_class_name, variable_name))) == 0);
+ setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) == 0);
}
/* Start generating the proxy function */
@@ -2316,7 +2389,7 @@ public:
Node *explicit_n = Getattr(n, "explicitcallnode");
if (explicit_n) {
String *ex_overloaded_name = getOverloadedName(explicit_n);
- String *ex_intermediary_function_name = Swig_name_member(getNSpace(), proxy_class_name, ex_overloaded_name);
+ String *ex_intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), ex_overloaded_name);
String *ex_imcall = Copy(imcall);
Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
@@ -3399,7 +3472,7 @@ public:
// Output the director connect method:
String *jni_imclass_name = makeValidJniName(imclass_name);
String *norm_name = SwigType_namestr(Getattr(n, "name"));
- String *swig_director_connect = Swig_name_member(getNSpace(), proxy_class_name, "director_connect");
+ String *swig_director_connect = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect");
String *swig_director_connect_jni = makeValidJniName(swig_director_connect);
String *smartptr = Getattr(n, "feature:smartptr");
String *dirClassName = directorClassName(n);
@@ -3439,7 +3512,7 @@ public:
Delete(swig_director_connect);
// Output the swigReleaseOwnership, swigTakeOwnership methods:
- String *changeown_method_name = Swig_name_member(getNSpace(), proxy_class_name, "change_ownership");
+ String *changeown_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "change_ownership");
String *changeown_jnimethod_name = makeValidJniName(changeown_method_name);
Printf(imclass_class_code, " public final static native void %s(%s obj, long cptr, boolean take_or_release);\n", changeown_method_name, full_proxy_class_name);
@@ -4519,6 +4592,9 @@ public:
Setattr(n, "director:ctor", class_ctor);
}
+ bool nestedClassesSupported() const {
+ return true;
+ }
}; /* class JAVA */
/* -----------------------------------------------------------------------------
diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx
index e50a50a6d..78c37dbb9 100644
--- a/Source/Modules/lang.cxx
+++ b/Source/Modules/lang.cxx
@@ -20,7 +20,7 @@ static int director_mode = 0;
static int director_protected_mode = 1;
static int all_protected_mode = 0;
static int naturalvar_mode = 0;
-Language* Language::this_ = 0;
+Language *Language::this_ = 0;
/* Set director_protected_mode */
void Wrapper_director_mode_set(int flag) {
@@ -355,7 +355,7 @@ Language::~Language() {
String *dirclassname;
String *nspace = NewString(Getattr(n, "sym:nspace"));
const char *attrib = "director:classname";
- String *classname = Getattr(n, "sym:name");
+ String *classname = getClassPrefix();
Replace(nspace, NSPACE_SEPARATOR, "_", DOH_REPLACE_ANY);
if (Len(nspace) > 0)
@@ -1015,8 +1015,6 @@ int Language::cDeclaration(Node *n) {
/* Some kind of variable declaration */
String *declaration = Copy(decl);
Delattr(n, "decl");
- if (Getattr(n, "nested"))
- SetFlag(n, "feature:immutable");
if (!CurrentClass) {
if (Swig_storage_isextern(n) || ForceExtern) {
if (AddExtern) {
@@ -2362,6 +2360,15 @@ int Language::classDeclaration(Node *n) {
return SWIG_NOWRAP;
}
+ // save class local variables for nested classes support
+ int oldInClass = InClass;
+ String *oldClassType = ClassType;
+ String *oldClassPrefix = ClassPrefix;
+ String *oldClassName = ClassName;
+ String *oldDirectorClassName = DirectorClassName;
+ String *oldNSpace = NSpace;
+ Node *oldCurrentClass = CurrentClass;
+
String *kind = Getattr(n, "kind");
String *name = Getattr(n, "name");
String *tdname = Getattr(n, "tdname");
@@ -2370,6 +2377,8 @@ int Language::classDeclaration(Node *n) {
int strip = CPlusPlus ? 1 : unnamed && tdname;
+ if (cplus_mode != PUBLIC)
+ return SWIG_NOWRAP;
if (!name) {
Swig_warning(WARN_LANG_CLASS_UNNAMED, input_file, line_number, "Can't generate wrappers for unnamed struct/class.\n");
return SWIG_NOWRAP;
@@ -2380,15 +2389,21 @@ int Language::classDeclaration(Node *n) {
Swig_warning(WARN_LANG_IDENTIFIER, input_file, line_number, "Can't wrap class %s unless renamed to a valid identifier.\n", SwigType_namestr(symname));
return SWIG_NOWRAP;
}
-
+ AccessMode oldAccessMode = cplus_mode;
+ Node *outerClass = Getattr(n, "nested:outer");
+ if (outerClass && oldAccessMode != PUBLIC)
+ return SWIG_NOWRAP;
+ ClassName = Copy(name);
+ ClassPrefix = Copy(symname);
if (Cmp(kind, "class") == 0) {
cplus_mode = PRIVATE;
} else {
cplus_mode = PUBLIC;
}
-
- ClassName = Copy(name);
- ClassPrefix = Copy(symname);
+ for (; outerClass; outerClass = Getattr(outerClass, "nested:outer")) {
+ Push(ClassPrefix, "_");
+ Push(ClassPrefix, Getattr(outerClass, "sym:name"));
+ }
if (strip) {
ClassType = Copy(name);
} else {
@@ -2399,9 +2414,8 @@ int Language::classDeclaration(Node *n) {
InClass = 1;
CurrentClass = n;
-
- String *oldNSpace = NSpace;
NSpace = Getattr(n, "sym:nspace");
+ int oldAbstract = Abstract;
/* Call classHandler() here */
if (!ImportMode) {
@@ -2443,25 +2457,27 @@ int Language::classDeclaration(Node *n) {
classDirector(n);
}
/* check for abstract after resolving directors */
- Abstract = abstractClassTest(n);
+ Abstract = abstractClassTest(n);
classHandler(n);
} else {
Abstract = abstractClassTest(n);
Language::classHandler(n);
}
+ Abstract = oldAbstract;
+ cplus_mode = oldAccessMode;
NSpace = oldNSpace;
- InClass = 0;
- CurrentClass = 0;
+ InClass = oldInClass;
+ CurrentClass = oldCurrentClass;
Delete(ClassType);
- ClassType = 0;
+ ClassType = oldClassType;
Delete(ClassPrefix);
- ClassPrefix = 0;
+ ClassPrefix = oldClassPrefix;
Delete(ClassName);
- ClassName = 0;
+ ClassName = oldClassName;
Delete(DirectorClassName);
- DirectorClassName = 0;
+ DirectorClassName = oldDirectorClassName;
return SWIG_OK;
}
@@ -2640,7 +2656,7 @@ int Language::constructorDeclaration(Node *n) {
String *scope = Swig_scopename_check(ClassName) ? Swig_scopename_prefix(ClassName) : 0;
String *actual_name = scope ? NewStringf("%s::%s", scope, name) : NewString(name);
Delete(scope);
- if (!Equal(actual_name, expected_name) && !(Getattr(n, "template"))) {
+ if (!Equal(actual_name, expected_name) && !SwigType_istemplate(expected_name)) {
bool illegal_name = true;
if (Extend) {
// Check for typedef names used as a constructor name in %extend. This is deprecated except for anonymous
@@ -3426,6 +3442,9 @@ bool Language::extraDirectorProtectedCPPMethodsRequired() const {
return true;
}
+bool Language::nestedClassesSupported() const {
+ return false;
+}
/* -----------------------------------------------------------------------------
* Language::is_wrapping_class()
* ----------------------------------------------------------------------------- */
@@ -3612,3 +3631,4 @@ Language *Language::instance() {
Hash *Language::getClassHash() const {
return classhash;
}
+
diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx
index 4076b9206..f3aff2349 100644
--- a/Source/Modules/main.cxx
+++ b/Source/Modules/main.cxx
@@ -483,6 +483,10 @@ void SWIG_getoptions(int argc, char *argv[]) {
Preprocessor_define((DOH *) "__cplusplus __cplusplus", 0);
Swig_cparse_cplusplus(1);
Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-c++out") == 0) {
+ // Undocumented
+ Swig_cparse_cplusplusout(1);
+ Swig_mark_arg(i);
} else if (strcmp(argv[i], "-fcompact") == 0) {
Wrapper_compact_print_mode_set(1);
Swig_mark_arg(i);
@@ -855,8 +859,9 @@ void SWIG_getoptions(int argc, char *argv[]) {
}
}
-
-
+static void flatten_nested() {
+ Swig_feature_set(Swig_cparse_features(), "", 0, "feature:flatnested", "1", 0);
+}
int SWIG_main(int argc, char *argv[], Language *l) {
@@ -947,6 +952,11 @@ int SWIG_main(int argc, char *argv[], Language *l) {
// Don't check for an input file if -external-runtime is passed
Swig_check_options(external_runtime ? 0 : 1);
+ if (CPlusPlus && cparse_cplusplusout) {
+ Printf(stderr, "The -c++out option is for C input but C++ input has been requested via -c++\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
install_opts(argc, argv);
// Add language dependent directory to the search path
@@ -1151,6 +1161,10 @@ int SWIG_main(int argc, char *argv[], Language *l) {
fflush(stdout);
}
+ // add "ignore" directive if nested classes are not supported
+ if (!lang->nestedClassesSupported())
+ flatten_nested();
+
Node *top = Swig_cparse(cpps);
if (dump_top & STAGE1) {
@@ -1161,6 +1175,11 @@ int SWIG_main(int argc, char *argv[], Language *l) {
Printf(stdout, "debug-module stage 1\n");
Swig_print_tree(Getattr(top, "module"));
}
+ if (!CPlusPlus) {
+ if (Verbose)
+ Printf(stdout, "Processing unnamed structs...\n");
+ Swig_nested_name_unnamed_c_structs(top);
+ }
if (Verbose) {
Printf(stdout, "Processing types...\n");
@@ -1181,6 +1200,12 @@ int SWIG_main(int argc, char *argv[], Language *l) {
}
Swig_default_allocators(top);
+ if (CPlusPlus) {
+ if (Verbose)
+ Printf(stdout, "Processing nested classes...\n");
+ Swig_nested_process_classes(top);
+ }
+
if (dump_top & STAGE3) {
Printf(stdout, "debug-top stage 3\n");
Swig_print_tree(top);
diff --git a/Source/Modules/nested.cxx b/Source/Modules/nested.cxx
new file mode 100644
index 000000000..a62a9e9da
--- /dev/null
+++ b/Source/Modules/nested.cxx
@@ -0,0 +1,444 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * nested.cxx
+ *
+ * Nested structs support
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+// Nested classes processing section
+static Hash *classhash = 0;
+
+static String *make_name(Node *n, String *name, SwigType *decl) {
+ int destructor = name && (*(Char(name)) == '~');
+ if (String *yyrename = Getattr(n, "class_rename")) {
+ String *s = NewString(yyrename);
+ Delattr(n, "class_rename");
+ if (destructor && (*(Char(s)) != '~')) {
+ Insert(s, 0, "~");
+ }
+ return s;
+ }
+
+ if (!name)
+ return 0;
+ return Swig_name_make(n, 0, name, decl, 0);
+}
+
+// C version of add_symbols()
+static void add_symbols_c(Node *n) {
+ String *decl;
+ String *wrn = 0;
+ String *symname = 0;
+ int iscdecl = Cmp(nodeType(n), "cdecl") == 0;
+ Setattr(n, "ismember", "1");
+ Setattr(n, "access", "public");
+ if (Getattr(n, "sym:name"))
+ return;
+ decl = Getattr(n, "decl");
+ if (!SwigType_isfunction(decl)) {
+ String *name = Getattr(n, "name");
+ String *makename = Getattr(n, "parser:makename");
+ if (iscdecl) {
+ String *storage = Getattr(n, "storage");
+ if (Cmp(storage, "typedef") == 0) {
+ Setattr(n, "kind", "typedef");
+ } else {
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ Setattr(n, "kind", "variable");
+ if (value && Len(value)) {
+ Setattr(n, "hasvalue", "1");
+ }
+ if (type) {
+ SwigType *ty;
+ SwigType *tmp = 0;
+ if (decl) {
+ ty = tmp = Copy(type);
+ SwigType_push(ty, decl);
+ } else {
+ ty = type;
+ }
+ if (!SwigType_ismutable(ty)) {
+ SetFlag(n, "hasconsttype");
+ SetFlag(n, "feature:immutable");
+ }
+ if (tmp)
+ Delete(tmp);
+ }
+ if (!type) {
+ Printf(stderr, "notype name %s\n", name);
+ }
+ }
+ }
+ Swig_features_get(Swig_cparse_features(), 0, name, 0, n);
+ if (makename) {
+ symname = make_name(n, makename, 0);
+ Delattr(n, "parser:makename"); /* temporary information, don't leave it hanging around */
+ } else {
+ makename = name;
+ symname = make_name(n, makename, 0);
+ }
+
+ if (!symname) {
+ symname = Copy(Getattr(n, "unnamed"));
+ }
+ if (symname) {
+ wrn = Swig_name_warning(n, 0, symname, 0);
+ }
+ } else {
+ String *name = Getattr(n, "name");
+ SwigType *fdecl = Copy(decl);
+ SwigType *fun = SwigType_pop_function(fdecl);
+ if (iscdecl) {
+ Setattr(n, "kind", "function");
+ }
+
+ Swig_features_get(Swig_cparse_features(), 0, name, fun, n);
+
+ symname = make_name(n, name, fun);
+ wrn = Swig_name_warning(n, 0, symname, fun);
+
+ Delete(fdecl);
+ Delete(fun);
+
+ }
+ if (!symname)
+ return;
+ if (GetFlag(n, "feature:ignore")) {
+ /* Only add to C symbol table and continue */
+ Swig_symbol_add(0, n);
+ } else if (strncmp(Char(symname), "$ignore", 7) == 0) {
+ char *c = Char(symname) + 7;
+ SetFlag(n, "feature:ignore");
+ if (strlen(c)) {
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(0, Getfile(n), Getline(n), "%s\n", c + 1);
+ SWIG_WARN_NODE_END(n);
+ }
+ Swig_symbol_add(0, n);
+ } else {
+ Node *c;
+ if ((wrn) && (Len(wrn))) {
+ String *metaname = symname;
+ if (!Getmeta(metaname, "already_warned")) {
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(0, Getfile(n), Getline(n), "%s\n", wrn);
+ SWIG_WARN_NODE_END(n);
+ Setmeta(metaname, "already_warned", "1");
+ }
+ }
+ c = Swig_symbol_add(symname, n);
+
+ if (c != n) {
+ /* symbol conflict attempting to add in the new symbol */
+ if (Getattr(n, "sym:weak")) {
+ Setattr(n, "sym:name", symname);
+ } else {
+ String *e = NewStringEmpty();
+ String *en = NewStringEmpty();
+ String *ec = NewStringEmpty();
+ int redefined = Swig_need_redefined_warn(n, c, true);
+ if (redefined) {
+ Printf(en, "Identifier '%s' redefined (ignored)", symname);
+ Printf(ec, "previous definition of '%s'", symname);
+ } else {
+ Printf(en, "Redundant redeclaration of '%s'", symname);
+ Printf(ec, "previous declaration of '%s'", symname);
+ }
+ if (Cmp(symname, Getattr(n, "name"))) {
+ Printf(en, " (Renamed from '%s')", SwigType_namestr(Getattr(n, "name")));
+ }
+ Printf(en, ",");
+ if (Cmp(symname, Getattr(c, "name"))) {
+ Printf(ec, " (Renamed from '%s')", SwigType_namestr(Getattr(c, "name")));
+ }
+ Printf(ec, ".");
+ SWIG_WARN_NODE_BEGIN(n);
+ if (redefined) {
+ Swig_warning(WARN_PARSE_REDEFINED, Getfile(n), Getline(n), "%s\n", en);
+ Swig_warning(WARN_PARSE_REDEFINED, Getfile(c), Getline(c), "%s\n", ec);
+ } else {
+ Swig_warning(WARN_PARSE_REDUNDANT, Getfile(n), Getline(n), "%s\n", en);
+ Swig_warning(WARN_PARSE_REDUNDANT, Getfile(c), Getline(c), "%s\n", ec);
+ }
+ SWIG_WARN_NODE_END(n);
+ Printf(e, "%s:%d:%s\n%s:%d:%s\n", Getfile(n), Getline(n), en, Getfile(c), Getline(c), ec);
+ Setattr(n, "error", e);
+ Delete(e);
+ Delete(en);
+ Delete(ec);
+ }
+ }
+ }
+ Delete(symname);
+}
+
+/* Strips C-style and C++-style comments from string in-place. */
+static void strip_comments(char *string) {
+ int state = 0;
+ /*
+ * 0 - not in comment
+ * 1 - in c-style comment
+ * 2 - in c++-style comment
+ * 3 - in string
+ * 4 - after reading / not in comments
+ * 5 - after reading * in c-style comments
+ * 6 - after reading \ in strings
+ */
+ char *c = string;
+ while (*c) {
+ switch (state) {
+ case 0:
+ if (*c == '\"')
+ state = 3;
+ else if (*c == '/')
+ state = 4;
+ break;
+ case 1:
+ if (*c == '*')
+ state = 5;
+ *c = ' ';
+ break;
+ case 2:
+ if (*c == '\n')
+ state = 0;
+ else
+ *c = ' ';
+ break;
+ case 3:
+ if (*c == '\"')
+ state = 0;
+ else if (*c == '\\')
+ state = 6;
+ break;
+ case 4:
+ if (*c == '/') {
+ *(c - 1) = ' ';
+ *c = ' ';
+ state = 2;
+ } else if (*c == '*') {
+ *(c - 1) = ' ';
+ *c = ' ';
+ state = 1;
+ } else
+ state = 0;
+ break;
+ case 5:
+ if (*c == '/')
+ state = 0;
+ else
+ state = 1;
+ *c = ' ';
+ break;
+ case 6:
+ state = 3;
+ break;
+ }
+ ++c;
+ }
+}
+
+// Create a %insert with a typedef to make a new name visible to C
+static Node *create_insert(Node *n, bool noTypedef = false) {
+ // format a typedef
+ String *ccode = Getattr(n, "code");
+ Push(ccode, " ");
+ if (noTypedef) {
+ Push(ccode, Getattr(n, "name"));
+ Push(ccode, " ");
+ Push(ccode, Getattr(n, "kind"));
+ } else {
+ Push(ccode, Getattr(n, "kind"));
+ Push(ccode, "typedef ");
+ Append(ccode, " ");
+ Append(ccode, Getattr(n, "tdname"));
+ }
+ Append(ccode, ";");
+
+ /* Strip comments - further code may break in presence of comments. */
+ strip_comments(Char(ccode));
+
+ /* Make all SWIG created typedef structs/unions/classes unnamed else
+ redefinition errors occur - nasty hack alert. */
+ if (!noTypedef) {
+ const char *types_array[3] = { "struct", "union", "class" };
+ for (int i = 0; i < 3; i++) {
+ char *code_ptr = Char(ccode);
+ while (code_ptr) {
+ /* Replace struct name (as in 'struct name {...}' ) with whitespace
+ name will be between struct and opening brace */
+
+ code_ptr = strstr(code_ptr, types_array[i]);
+ if (code_ptr) {
+ char *open_bracket_pos;
+ code_ptr += strlen(types_array[i]);
+ open_bracket_pos = strchr(code_ptr, '{');
+ if (open_bracket_pos) {
+ /* Make sure we don't have something like struct A a; */
+ char *semi_colon_pos = strchr(code_ptr, ';');
+ if (!(semi_colon_pos && (semi_colon_pos < open_bracket_pos)))
+ while (code_ptr < open_bracket_pos)
+ *code_ptr++ = ' ';
+ }
+ }
+ }
+ }
+ }
+ {
+ /* Remove SWIG directive %constant which may be left in the SWIG created typedefs */
+ char *code_ptr = Char(ccode);
+ while (code_ptr) {
+ code_ptr = strstr(code_ptr, "%constant");
+ if (code_ptr) {
+ char *directive_end_pos = strchr(code_ptr, ';');
+ if (directive_end_pos) {
+ while (code_ptr <= directive_end_pos)
+ *code_ptr++ = ' ';
+ }
+ }
+ }
+ }
+ Node *newnode = NewHash();
+ set_nodeType(newnode, "insert");
+ Setfile(newnode, Getfile(n));
+ Setline(newnode, Getline(n));
+ String *code = NewStringEmpty();
+ Wrapper_pretty_print(ccode, code);
+ Setattr(newnode, "code", code);
+ Delete(code);
+ Delattr(n, "code");
+ return newnode;
+}
+
+static void insertNodeAfter(Node *n, Node *c) {
+ Node *g = parentNode(n);
+ set_parentNode(c, g);
+ Node *ns = nextSibling(n);
+ if (Node *outer = Getattr(c, "nested:outer")) {
+ while (ns && outer == Getattr(ns, "nested:outer")) {
+ n = ns;
+ ns = nextSibling(n);
+ }
+ }
+ if (!ns) {
+ set_lastChild(g, c);
+ } else {
+ set_nextSibling(c, ns);
+ set_previousSibling(ns, c);
+ }
+ set_nextSibling(n, c);
+ set_previousSibling(c, n);
+}
+
+void Swig_nested_name_unnamed_c_structs(Node *n) {
+ if (!classhash)
+ classhash = Getattr(n, "classes");
+ Node *c = firstChild(n);
+ while (c) {
+ Node *next = nextSibling(c);
+ if (String *declName = Getattr(c, "nested:unnamed")) {
+ if (Node *outer = Getattr(c, "nested:outer")) {
+ // generate a name
+ String *name = NewStringf("%s_%s", Getattr(outer, "name"), declName);
+ Delattr(c, "nested:unnamed");
+ // set the name to the class and symbol table
+ Setattr(c, "tdname", name);
+ Setattr(c, "name", name);
+ Swig_symbol_setscope(Getattr(c, "symtab"));
+ Swig_symbol_setscopename(name);
+ // now that we have a name - gather base symbols
+ if (List *publicBases = Getattr(c, "baselist")) {
+ List *bases = Swig_make_inherit_list(name, publicBases, 0);
+ Swig_inherit_base_symbols(bases);
+ Delete(bases);
+ }
+ Setattr(classhash, name, c);
+ Swig_symbol_popscope();
+ // process declarations following this type (assign correct new type)
+ SwigType *ty = Copy(name);
+ Node *decl = nextSibling(c);
+ List *declList = NewList();
+ while (decl && Getattr(decl, "nested:unnamedtype") == c) {
+ Setattr(decl, "type", ty);
+ Append(declList, decl);
+ Delattr(decl, "nested:unnamedtype");
+ SetFlag(decl, "feature:immutable");
+ add_symbols_c(decl);
+ decl = nextSibling(decl);
+ }
+ Delete(ty);
+ // Check for extensions
+/* // TODO: we can save extensions hash like class hash and move check_extensions() after nesting processing
+ if (extendhash) {
+ if (Node *am = Getattr(extendhash, name)) {
+ // Merge the extension into the symbol table
+ merge_extensions(c, am);
+ append_previous_extension(c, am);
+ Delattr(extendhash, clsname);
+ }
+ }*/
+ Swig_symbol_setscope(Swig_symbol_global_scope());
+ add_symbols_c(c);
+
+ Node *ins = create_insert(c);
+ insertNodeAfter(c, ins);
+ removeNode(c);
+ insertNodeAfter(n, c);
+ Delete(ins);
+ Delattr(c, "nested:outer");
+ } else {
+ // global unnamed struct - ignore it
+ c = next;
+ continue;
+ }
+ } else if (cparse_cplusplusout) {
+ if (Getattr(c, "nested:outer")) {
+ Node *ins = create_insert(c, true);
+ insertNodeAfter(c, ins);
+ Delete(ins);
+ Delattr(c, "nested:outer");
+ }
+ }
+ // process children
+ Swig_nested_name_unnamed_c_structs(c);
+ c = next;
+ }
+}
+
+static void remove_outer_class_reference(Node *n) {
+ for (Node *c = firstChild(n); c; c = nextSibling(c)) {
+ if (GetFlag(c, "feature:flatnested")) {
+ Delattr(c, "nested:outer");
+ remove_outer_class_reference(c);
+ }
+ }
+}
+
+void Swig_nested_process_classes(Node *n) {
+ Node *c = firstChild(n);
+ while (c) {
+ Node *next = nextSibling(c);
+ if (!Getattr(c, "templatetype")) {
+ if (GetFlag(c, "nested") && GetFlag(c, "feature:flatnested")) {
+ removeNode(c);
+ if (!checkAttribute(c, "access", "public"))
+ SetFlag(c, "feature:ignore");
+ else
+ insertNodeAfter(n, c);
+ }
+ Swig_nested_process_classes(c);
+ }
+ c = next;
+ }
+ remove_outer_class_reference(n);
+}
+
diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx
index 65a1ad701..14118972d 100644
--- a/Source/Modules/octave.cxx
+++ b/Source/Modules/octave.cxx
@@ -12,6 +12,7 @@
* ----------------------------------------------------------------------------- */
#include "swigmod.h"
+#include "cparse.h"
static String *global_name = 0;
static String *op_prefix = 0;
@@ -132,6 +133,10 @@ public:
SWIG_config_file("octave.swg");
SWIG_typemap_lang("octave");
allow_overloading();
+
+ // Octave API is C++, so output must be C++ compatibile even when wrapping C code
+ if (!cparse_cplusplus)
+ Swig_cparse_cplusplusout(1);
}
virtual int top(Node *n) {
diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h
index 3a7e8a8d6..9e76b4d10 100644
--- a/Source/Modules/swigmod.h
+++ b/Source/Modules/swigmod.h
@@ -297,6 +297,16 @@ protected:
/* Some language modules require additional wrappers for virtual methods not declared in sub-classes */
virtual bool extraDirectorProtectedCPPMethodsRequired() const;
+public:
+ /* Does target language support nested classes? Default is 'false'. If 'false' is returned, then
+ %rename("$ignore", %$isnested) statement will be issued at the top, and the nested classes
+ will be ignored. Note that even if the target language does not support the notion of class
+ nesting, the language module may nevertheless return true from this function, and use
+ %feature "flatnested" to move nested classes to the global scope, instead of ignoring them.
+ */
+ virtual bool nestedClassesSupported() const;
+
+protected:
/* Identifies if a protected members that are generated when the allprotected option is used.
This does not include protected virtual methods as they are turned on with the dirprot option. */
bool isNonVirtualProtectedAccess(Node *n) const;
@@ -410,5 +420,7 @@ int Swig_contract_mode_get();
void Swig_browser(Node *n, int);
void Swig_default_allocators(Node *n);
void Swig_process_types(Node *n);
+void Swig_nested_process_classes(Node *n);
+void Swig_nested_name_unnamed_c_structs(Node *n);
#endif
diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx
index 7eebfe80b..3f8e33dae 100644
--- a/Source/Modules/typepass.cxx
+++ b/Source/Modules/typepass.cxx
@@ -178,6 +178,20 @@ class TypePass:private Dispatcher {
}
continue;
}
+ // A case when both outer and nested classes inherit from the same parent. Constructor may be found instead of the class itself.
+ } else if (GetFlag(cls, "nested") && checkAttribute(bcls, "nodeType", "constructor")) {
+ bcls = Getattr(bcls, "parentNode");
+ if (Getattr(bcls, "typepass:visit")) {
+ if (!Getattr(bcls, "feature:onlychildren")) {
+ if (!ilist)
+ ilist = alist = NewList();
+ Append(ilist, bcls);
+ } else {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
+ }
+ }
+ break;
}
if (Strcmp(nodeType(bcls), "classforward") != 0) {
Swig_error(Getfile(bname), Getline(bname), "'%s' is not a valid base class.\n", SwigType_namestr(bname));
@@ -462,6 +476,17 @@ class TypePass:private Dispatcher {
if (unnamed && tdname && (Cmp(storage, "typedef") == 0)) {
SwigType_typedef(unnamed, tdname);
}
+ // name of the outer class should already be patched to contain it's outer classes names, but not to contain namespaces
+ // namespace name (if present) is added after processing child nodes
+ if (Getattr(n, "nested:outer") && name) {
+ String *outerName = Getattr(Getattr(n, "nested:outer"), "name");
+ name = NewStringf("%s::%s", outerName, name);
+ Setattr(n, "name", name);
+ if (tdname) {
+ tdname = NewStringf("%s::%s", outerName, tdname);
+ Setattr(n, "tdname", tdname);
+ }
+ }
if (nsname && name) {
nname = NewStringf("%s::%s", nsname, name);
@@ -479,7 +504,7 @@ class TypePass:private Dispatcher {
SwigType_attach_symtab(Getattr(n, "symtab"));
/* Inherit type definitions into the class */
- if (name) {
+ if (name && !(GetFlag(n, "nested") && GetFlag(n, "feature:flatnested") && !checkAttribute(n, "access", "public"))) {
cplus_inherit_types(n, 0, nname ? nname : (fname ? fname : name));
}
@@ -653,7 +678,7 @@ class TypePass:private Dispatcher {
if (GetFlag(n, "conversion_operator")) {
/* The call to the operator in the generated wrapper must be fully qualified in order to compile */
SwigType *name = Getattr(n, "name");
- SwigType *qualifiedname = Swig_symbol_string_qualify(name,0);
+ SwigType *qualifiedname = Swig_symbol_string_qualify(name, 0);
Clear(name);
Append(name, qualifiedname);
Delete(qualifiedname);
@@ -1090,8 +1115,7 @@ class TypePass:private Dispatcher {
* list of overloaded methods we have just added in as child nodes to the "using" node.
* The node will still exist, it is just the symbol table linked list of overloaded methods
* which is hacked. */
- if (Getattr(n, "sym:overloaded"))
- {
+ if (Getattr(n, "sym:overloaded")) {
int cnt = 0;
#ifdef DEBUG_OVERLOADED
Node *debugnode = n;
@@ -1154,7 +1178,7 @@ class TypePass:private Dispatcher {
#ifdef DEBUG_OVERLOADED
show_overloaded(debugnode);
#endif
- clean_overloaded(n); // Needed?
+ clean_overloaded(n); // Needed?
}
}
}
@@ -1258,3 +1282,4 @@ void Swig_process_types(Node *n) {
return;
TypePass::pass(n);
}
+
diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c
index 6f8fa39e9..04845f3cf 100644
--- a/Source/Swig/cwrap.c
+++ b/Source/Swig/cwrap.c
@@ -13,8 +13,8 @@
* ----------------------------------------------------------------------------- */
#include "swig.h"
+#include "cparse.h"
-extern int cparse_cplusplus;
static const char *cresult_variable_name = "result";
static Parm *nonvoid_parms(Parm *p) {
@@ -775,7 +775,25 @@ String *Swig_cmemberset_call(const_String_or_char_ptr name, SwigType *type, Stri
if (SwigType_type(type) != T_ARRAY) {
if (!Strstr(type, "enum $unnamed")) {
String *dref = Swig_wrapped_var_deref(type, pname1, varcref);
- Printf(func, "if (%s) %s%s = %s", pname0, self, name, dref);
+ int extra_cast = 0;
+ if (cparse_cplusplusout) {
+ /* Required for C nested structs compiled as C++ as a duplicate of the nested struct is put into the global namespace.
+ * We could improve this by adding the extra casts just for nested structs rather than all structs. */
+ String *base = SwigType_base(type);
+ extra_cast = SwigType_isclass(base);
+ Delete(base);
+ }
+ if (extra_cast) {
+ String *lstr;
+ SwigType *ptype = Copy(type);
+ SwigType_add_pointer(ptype);
+ lstr = SwigType_lstr(ptype, 0);
+ Printf(func, "if (%s) *(%s)&%s%s = %s", pname0, lstr, self, name, dref);
+ Delete(lstr);
+ Delete(ptype);
+ } else {
+ Printf(func, "if (%s) %s%s = %s", pname0, self, name, dref);
+ }
Delete(dref);
} else {
Printf(func, "if (%s && sizeof(int) == sizeof(%s%s)) *(int*)(void*)&(%s%s) = %s", pname0, self, name, self, name, pname1);
diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c
index 769882bf8..7d8180d1c 100644
--- a/Source/Swig/misc.c
+++ b/Source/Swig/misc.c
@@ -1147,6 +1147,55 @@ String *Swig_string_strip(String *s) {
return ns;
}
+/* -----------------------------------------------------------------------------
+ * Swig_offset_string()
+ *
+ * Insert number tabs before each new line in s
+ * ----------------------------------------------------------------------------- */
+
+void Swig_offset_string(String *s, int number) {
+ char *res;
+ char *p;
+ char *end;
+ /* count a number of lines in s */
+ int lines = 1;
+ int len = Len(s);
+ char *start = strchr(Char(s), '\n');
+ while (start) {
+ ++lines;
+ start = strchr(start + 1, '\n');
+ }
+ /* do not count pending new line */
+ if ((Char(s))[len-1] == '\n')
+ --lines;
+ /* allocate a temporary storage for a padded string */
+ res = (char*)malloc(len + lines * number * 2 + 1);
+ res[len + lines * number * 2] = 0;
+
+ /* copy lines to res, prepending tabs to each line */
+ p = res; /* output pointer */
+ start = Char(s); /* start of a current line */
+ end = strchr(start, '\n'); /* end of a current line */
+ while (end) {
+ memset(p, ' ', number*2);
+ p += number*2;
+ memcpy(p, start, end - start + 1);
+ p += end - start + 1;
+ start = end + 1;
+ end = strchr(start, '\n');
+ }
+ /* process the last line */
+ if (*start) {
+ memset(p, ' ', number*2);
+ p += number*2;
+ strcpy(p, start);
+ }
+ /* replace 's' contents with 'res' */
+ Clear(s);
+ Append(s, res);
+ free(res);
+}
+
#ifdef HAVE_PCRE
#include <pcre.h>
diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c
index 119f816dc..9e2b4a436 100644
--- a/Source/Swig/naming.c
+++ b/Source/Swig/naming.c
@@ -774,7 +774,7 @@ void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *d
* concatenating the feature name plus ':' plus the attribute name.
* ----------------------------------------------------------------------------- */
-void Swig_feature_set(Hash *features, const_String_or_char_ptr name, SwigType *decl, const_String_or_char_ptr featurename, String *value, Hash *featureattribs) {
+void Swig_feature_set(Hash *features, const_String_or_char_ptr name, SwigType *decl, const_String_or_char_ptr featurename, const_String_or_char_ptr value, Hash *featureattribs) {
Hash *n;
Hash *fhash;
@@ -1649,6 +1649,80 @@ void Swig_name_inherit(String *base, String *derived) {
}
/* -----------------------------------------------------------------------------
+ * Swig_inherit_base_symbols()
+ * ----------------------------------------------------------------------------- */
+
+void Swig_inherit_base_symbols(List *bases) {
+ if (bases) {
+ Iterator s;
+ for (s = First(bases); s.item; s = Next(s)) {
+ Symtab *st = Getattr(s.item, "symtab");
+ if (st) {
+ Setfile(st, Getfile(s.item));
+ Setline(st, Getline(s.item));
+ Swig_symbol_inherit(st);
+ }
+ }
+ Delete(bases);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_make_inherit_list()
+ * ----------------------------------------------------------------------------- */
+
+List *Swig_make_inherit_list(String *clsname, List *names, String *Namespaceprefix) {
+ int i, ilen;
+ String *derived;
+ List *bases = NewList();
+
+ if (Namespaceprefix)
+ derived = NewStringf("%s::%s", Namespaceprefix, clsname);
+ else
+ derived = NewString(clsname);
+
+ ilen = Len(names);
+ for (i = 0; i < ilen; i++) {
+ String *base;
+ String *n = Getitem(names, i);
+ /* Try to figure out where this symbol is */
+ Node *s = Swig_symbol_clookup(n, 0);
+ if (s) {
+ while (s && (Strcmp(nodeType(s), "class") != 0)) {
+ /* Not a class. Could be a typedef though. */
+ String *storage = Getattr(s, "storage");
+ if (storage && (Strcmp(storage, "typedef") == 0)) {
+ String *nn = Getattr(s, "type");
+ s = Swig_symbol_clookup(nn, Getattr(s, "sym:symtab"));
+ } else {
+ break;
+ }
+ }
+ if (s && ((Strcmp(nodeType(s), "class") == 0) || (Strcmp(nodeType(s), "template") == 0))) {
+ String *q = Swig_symbol_qualified(s);
+ Append(bases, s);
+ if (q) {
+ base = NewStringf("%s::%s", q, Getattr(s, "name"));
+ Delete(q);
+ } else {
+ base = NewString(Getattr(s, "name"));
+ }
+ } else {
+ base = NewString(n);
+ }
+ } else {
+ base = NewString(n);
+ }
+ if (base) {
+ Swig_name_inherit(base, derived);
+ Delete(base);
+ }
+ }
+ return bases;
+}
+
+
+/* -----------------------------------------------------------------------------
* void Swig_name_str()
*
* Return a stringified version of a C/C++ symbol from a node.
diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c
index 181d9aa74..a32828b58 100644
--- a/Source/Swig/scanner.c
+++ b/Source/Swig/scanner.c
@@ -1547,6 +1547,114 @@ int Scanner_skip_balanced(Scanner * s, int startchar, int endchar) {
}
/* -----------------------------------------------------------------------------
+ * Scanner_get_raw_text_balanced()
+ *
+ * Returns raw text between 2 braces, does not change scanner state in any way
+ * ----------------------------------------------------------------------------- */
+
+String *Scanner_get_raw_text_balanced(Scanner *s, int startchar, int endchar) {
+ String *result = 0;
+ char c;
+ int old_line = s->line;
+ String *old_text = Copy(s->text);
+ int position = Tell(s->str);
+
+ int num_levels = 1;
+ int state = 0;
+ char temp[2] = { 0, 0 };
+ temp[0] = (char) startchar;
+ Clear(s->text);
+ Setfile(s->text, Getfile(s->str));
+ Setline(s->text, s->line);
+ Append(s->text, temp);
+ while (num_levels > 0) {
+ if ((c = nextchar(s)) == 0) {
+ Clear(s->text);
+ Append(s->text, old_text);
+ Delete(old_text);
+ s->line = old_line;
+ return 0;
+ }
+ switch (state) {
+ case 0:
+ if (c == startchar)
+ num_levels++;
+ else if (c == endchar)
+ num_levels--;
+ else if (c == '/')
+ state = 10;
+ else if (c == '\"')
+ state = 20;
+ else if (c == '\'')
+ state = 30;
+ break;
+ case 10:
+ if (c == '/')
+ state = 11;
+ else if (c == '*')
+ state = 12;
+ else if (c == startchar) {
+ state = 0;
+ num_levels++;
+ }
+ else
+ state = 0;
+ break;
+ case 11:
+ if (c == '\n')
+ state = 0;
+ else
+ state = 11;
+ break;
+ case 12: /* first character inside C comment */
+ if (c == '*')
+ state = 14;
+ else
+ state = 13;
+ break;
+ case 13:
+ if (c == '*')
+ state = 14;
+ break;
+ case 14: /* possible end of C comment */
+ if (c == '*')
+ state = 14;
+ else if (c == '/')
+ state = 0;
+ else
+ state = 13;
+ break;
+ case 20:
+ if (c == '\"')
+ state = 0;
+ else if (c == '\\')
+ state = 21;
+ break;
+ case 21:
+ state = 20;
+ break;
+ case 30:
+ if (c == '\'')
+ state = 0;
+ else if (c == '\\')
+ state = 31;
+ break;
+ case 31:
+ state = 30;
+ break;
+ default:
+ break;
+ }
+ }
+ Seek(s->str, position, SEEK_SET);
+ result = Copy(s->text);
+ Clear(s->text);
+ Append(s->text, old_text);
+ Delete(old_text);
+ s->line = old_line;
+ return result;
+}
+/* -----------------------------------------------------------------------------
* Scanner_isoperator()
*
* Returns 0 or 1 depending on whether or not a token corresponds to a C/C++
diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h
index b730ab04d..95d9189b3 100644
--- a/Source/Swig/swig.h
+++ b/Source/Swig/swig.h
@@ -286,6 +286,8 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern Hash *Swig_name_namewarn_get(Node *n, String *prefix, String *name, SwigType *decl);
extern void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *namewrn, ParmList *declaratorparms);
extern void Swig_name_inherit(String *base, String *derived);
+ extern List *Swig_make_inherit_list(String *clsname, List *names, String *Namespaceprefix);
+ extern void Swig_inherit_base_symbols(List *bases);
extern int Swig_need_protected(Node *n);
extern int Swig_need_name_warning(Node *n);
extern int Swig_need_redefined_warn(Node *a, Node *b, int InClass);
@@ -302,7 +304,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType *decl);
extern void Swig_name_object_inherit(Hash *namehash, String *base, String *derived);
extern void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *decl, Node *n);
- extern void Swig_feature_set(Hash *features, const_String_or_char_ptr name, SwigType *decl, const_String_or_char_ptr featurename, String *value, Hash *featureattribs);
+ extern void Swig_feature_set(Hash *features, const_String_or_char_ptr name, SwigType *decl, const_String_or_char_ptr featurename, const_String_or_char_ptr value, Hash *featureattribs);
/* --- Misc --- */
extern char *Swig_copy_string(const char *c);
@@ -330,6 +332,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern String *Swig_string_lower(String *s);
extern String *Swig_string_upper(String *s);
extern String *Swig_string_title(String *s);
+ extern void Swig_offset_string(String *s, int number);
extern String *Swig_pcre_version(void);
extern void Swig_init(void);
extern int Swig_value_wrapper_mode(int mode);
diff --git a/Source/Swig/swigscan.h b/Source/Swig/swigscan.h
index 017ef58d5..6a181f86f 100644
--- a/Source/Swig/swigscan.h
+++ b/Source/Swig/swigscan.h
@@ -22,6 +22,7 @@ extern int Scanner_token(Scanner *);
extern String *Scanner_text(Scanner *);
extern void Scanner_skip_line(Scanner *);
extern int Scanner_skip_balanced(Scanner *, int startchar, int endchar);
+extern String *Scanner_get_raw_text_balanced(Scanner *, int startchar, int endchar);
extern void Scanner_set_location(Scanner *, String *file, int line);
extern String *Scanner_file(Scanner *);
extern int Scanner_line(Scanner *);
diff --git a/Source/Swig/swigtree.h b/Source/Swig/swigtree.h
index 5decb79e3..acd0e5e90 100644
--- a/Source/Swig/swigtree.h
+++ b/Source/Swig/swigtree.h
@@ -38,6 +38,7 @@ extern void appendChild(Node *node, Node *child);
extern void prependChild(Node *node, Node *child);
extern void removeNode(Node *node);
extern Node *copyNode(Node *node);
+extern void appendSibling(Node *node, Node *child);
/* Node restoration/restore functions */
diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c
index 784d3ab84..d817f1a85 100644
--- a/Source/Swig/tree.c
+++ b/Source/Swig/tree.c
@@ -171,6 +171,24 @@ void prependChild(Node *node, Node *chd) {
}
}
+void appendSibling(Node *node, Node *chd) {
+ Node *parent;
+ Node *lc = node;
+ while (nextSibling(lc))
+ lc = nextSibling(lc);
+ set_nextSibling(lc, chd);
+ set_previousSibling(chd, lc);
+ parent = parentNode(node);
+ if (parent) {
+ while (chd) {
+ lc = chd;
+ set_parentNode(chd, parent);
+ chd = nextSibling(chd);
+ }
+ set_lastChild(parent, lc);
+ }
+}
+
/* -----------------------------------------------------------------------------
* removeNode()
*